From 34d59b0b91f09b35b7c3b4e74411f11b8b3994cc Mon Sep 17 00:00:00 2001 From: Baruch Sterin Date: Sun, 27 Feb 2011 18:33:56 -0800 Subject: fixes to pyabc kill mechanism --- src/python/pyabc.i | 719 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 691 insertions(+), 28 deletions(-) (limited to 'src/python/pyabc.i') diff --git a/src/python/pyabc.i b/src/python/pyabc.i index 0bf58288..e258575e 100644 --- a/src/python/pyabc.i +++ b/src/python/pyabc.i @@ -23,9 +23,18 @@ %{ #include +#include + #include #include -#include "utilSignal.h" + +#include +#include +#include +#include +#include +#include +#include int n_ands() { @@ -160,6 +169,56 @@ int n_phases() return pNtk ? Abc_NtkPhaseFrameNum(pNtk) : 1; } +Abc_Cex_t* _cex_get() +{ + Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame(); + Abc_Cex_t* pCex = Abc_FrameReadCex(pAbc); + + if ( ! pCex ) + { + return NULL; + } + + return Abc_CexDup( pCex, -1 ); +} + +void _cex_put(Abc_Cex_t* pCex) +{ + Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame(); + + if ( pCex ) + { + pCex = Abc_CexDup(pCex, -1); + } + + Abc_FrameSetCex( Abc_CexDup(pCex, -1) ); +} + +void _cex_free(Abc_Cex_t* pCex) +{ + Abc_CexFree(pCex); +} + +int _cex_n_regs(Abc_Cex_t* pCex) +{ + return pCex->nRegs; +} + +int _cex_n_pis(Abc_Cex_t* pCex) +{ + return pCex->nPis; +} + +int _cex_get_po(Abc_Cex_t* pCex) +{ + return pCex->iPo; +} + +int _cex_get_frame(Abc_Cex_t* pCex) +{ + return pCex->iFrame; +} + static PyObject* pyabc_internal_python_command_callback = 0; void pyabc_internal_set_command_callback( PyObject* callback ) @@ -170,6 +229,8 @@ void pyabc_internal_set_command_callback( PyObject* callback ) pyabc_internal_python_command_callback = callback; } +PyThreadState *_save; + static int pyabc_internal_abc_command_callback(Abc_Frame_t * pAbc, int argc, char ** argv) { int i; @@ -183,6 +244,8 @@ static int pyabc_internal_abc_command_callback(Abc_Frame_t * pAbc, int argc, cha if ( !pyabc_internal_python_command_callback ) return 0; + Py_BLOCK_THREADS + args = PyList_New(argc); for( i=0 ; i0: + return pid, status + + elif pid==0: + return 0,0 + + elif pid == -1 and e == errno.ECHILD: + return 0,0 + + elif pid==-1 and e != errno.EINTR: + raise OSError(e, 'unknown error in wait3()') + +def _sigint_wait_thread_func(fd): + + global _die_flag + + while True: + + _retry_select(fd) + _retry_read(fd) + + with _active_lock: + + if _die_flag: + os._exit(-1) + + _die_flag = True + + for pid in _active_pids: + rc = _posix_kill(pid, signal.SIGINT) + + for fname in _active_temp_files: + os.remove(fname) + + os._exit(-1) + +def _child_wait_thread_func(fd): + + while True: + + _retry_select(fd) + rc = _retry_read(fd) + + with _active_lock: + + while True: + + pid, status = _retry_wait() + + if pid==0: + break + + if pid in _active_pids: + _active_pids.remove(pid) + + _terminated_pids[pid] = status + _terminated_pids_cond.notifyAll() + +_sigint_pipe_read_fd = -1 +_sigint_pipe_write_fd = -1 + +_sigchld_pipe_read_fd = -1 +_sigchld_pipe_write_fd = -1 + +def _start_threads(): + + global _sigint_pipe_read_fd, _sigint_pipe_write_fd + + _sigint_pipe_read_fd, _sigint_pipe_write_fd = os.pipe() + sigint_read = os.fdopen(_sigint_pipe_read_fd, "r", 0 ) + + sigint_wait_thread = threading.Thread(target=_sigint_wait_thread_func, name="SIGINT wait thread", args=(sigint_read,)) + sigint_wait_thread.setDaemon(True) + sigint_wait_thread.start() + + install_sigint_handler(_sigint_pipe_write_fd) + + global _sigchld_pipe_read_fd, _sigchld_pipe_write_fd + + _sigchld_pipe_read_fd, _sigchld_pipe_write_fd = os.pipe() + sigchld_read = os.fdopen(_sigchld_pipe_read_fd, "r", 0 ) + + child_wait_thread = threading.Thread(target=_child_wait_thread_func, name="child process wait thread", args=(sigchld_read,)) + child_wait_thread.setDaemon(True) + child_wait_thread.start() + + install_sigchld_handler(_sigchld_pipe_write_fd) + +_close_on_fork = [] + +def close_on_fork(fd): + _close_on_fork.append(fd) + +def after_fork(): + + _set_death_signal() + + global _close_on_fork + + for fd in _close_on_fork: + os.close(fd) + + _close_on_fork = [] + + os.close(_sigint_pipe_read_fd) + os.close(_sigint_pipe_write_fd) + + os.close(_sigchld_pipe_read_fd) + os.close(_sigchld_pipe_write_fd) + + global _active_lock + _active_lock = threading.Lock() + + global _terminated_pids_cond + _terminated_pids_cond = threading.Condition(_active_lock) + + global _terminated_pids + _terminated_pids = {} + + global _active_pids + _active_pids = set() + + global _active_temp_files + _active_temp_files = set() + + _start_threads() + +class _sigint_block_section(object): + def __init__(self): + self.blocked = False + + def __enter__(self): + block_sigint() + self.blocked = True + + def __exit__(self, type, value, traceback): + self.release() + + def release(self): + if self.blocked: + self.blocked = False + unblock_sigint() + +_old_os_fork = os.fork + +def _fork(): + + ppid = os.getpid() + + with _sigint_block_section() as cs: + + with _active_lock: + + if _die_flag: + os._exit(-1) + + pid = _old_os_fork() + + if pid == 0: + after_fork() + + if pid > 0: + _active_pids.add(pid) + + return pid + +def _waitpid(pid, options=0): + + while True: + + with _active_lock: + + if pid in _terminated_pids: + status = _terminated_pids[pid] + del _terminated_pids[pid] + return pid, status + + if options==os.WNOHANG: + return 0, 0 + + _terminated_pids_cond.wait() + +def _wait(options=0): + + while True: + + with _active_lock: + + for pid, status in _terminated_pids.iteritems(): + del _terminated_pids[pid] + return pid, status + + if options==os.WNOHANG: + return 0, 0 + + _terminated_pids_cond.wait() + +_old_os_kill = os.kill + +def _kill(pid, sig): + + with _active_lock: + + if pid in _terminated_pids: + return None + + return _old_os_kill(pid,sig) + +os.kill = _kill +os.fork = _fork +os.wait = _wait +os.waitpid = _waitpid + +def _split_command_line(cmd): + + args = [] + + i=0 + + while i= len(cmd): + break + + arg = [] + + in_quotes = None + + while i': + + with open(args[-1],'w') as fout: + p = subprocess.Popen(args[:-2], stdout=fout) + rc = p.wait() + return rc + + else: + p = subprocess.Popen(args) + return p.wait() + +def tmpfile(prefix, suffix): + + with _active_lock: + with tempfile.NamedTemporaryFile(delete=False, prefix=prefix, suffix=suffix) as file: + _active_temp_files.add(file.name) + return file.name + +def tmpfile_remove(fname, leave): + + with _active_lock: + os.remove(fname) + _active_temp_files.remove(fname) + +pyabc_internal_set_util_callbacks( system, tmpfile,tmpfile_remove ) + + +_start_threads() + + _registered_commands = {} def _cmd_callback(args): @@ -309,7 +974,8 @@ def _cmd_callback(args): return res except Exception, e: - print "Python error: ", e + import traceback + traceback.print_exc() except SystemExit, se: pass @@ -322,14 +988,11 @@ def add_abc_command(fcmd, group, cmd, change): _registered_commands[ cmd ] = fcmd pyabc_internal_register_command( group, cmd, change) -import sys import optparse -import os.path -import __main__ +xxx = {} def cmd_python(cmd_args): - global __main__ usage = "usage: %prog [options] " @@ -345,7 +1008,7 @@ def cmd_python(cmd_args): return 0 if options.cmd: - exec options.cmd in __main__.__dict__ + exec options.cmd in xxx return 0 scripts_dir = os.getenv('ABC_PYTHON_SCRIPTS', ".") @@ -353,12 +1016,12 @@ def cmd_python(cmd_args): for fname in args[1:]: if os.path.isabs(fname): - execfile(fname, __main__.__dict__) + execfile(fname, xxx) else: for d in scripts_dirs: fname = os.path.join(scripts_dir, fname) if os.path.exists(fname): - execfile(fname, __main__.__dict__) + execfile(fname, xxx) break return 0 -- cgit v1.2.3