Commit 34d59b0b by Baruch Sterin

fixes to pyabc kill mechanism

parent 02081dba
......@@ -12,23 +12,35 @@ from contextlib import contextmanager, nested
import pyabc
def wait_with_timeout(p, timeout):
def popen_and_wait_with_timeout(timeout,cmd, *args, **kwargs):
""" Wait for a subprocess.Popen object to terminate, or until timeout (in seconds) expires. """
if timeout <= 0:
timeout = None
t = threading.Thread(target=lambda: p.wait())
t.start()
t.join(timeout)
if t.is_alive():
p.kill()
t.join()
return p.returncode
p = None
t = None
try:
p = subprocess.Popen(cmd, *args, **kwargs)
if timeout <= 0:
timeout = None
t = threading.Thread(target=lambda: p.communicate())
t.start()
t.join(timeout)
finally:
if p is not None and p.poll() is None:
p.kill()
if t is not None and t.is_alive():
t.join()
if p is not None:
return p.returncode
return -1
@contextmanager
def replace_sys_argv(argv):
......@@ -74,13 +86,11 @@ def run_reachx_cmd(effort, timeout):
'qua_ffix -effort %d -L %s'%(effort, cygpath(tmplog_name)),
'quit'
]
cmd = ["jabc", "-c", " ; ".join(cmdline)]
p = subprocess.Popen(cmd, shell=False, stdout=sys.stdout, stderr=sys.stderr)
rc = wait_with_timeout(p,timeout)
rc = popen_and_wait_with_timeout(timeout, cmd, shell=False, stdout=sys.stdout, stderr=sys.stderr)
if rc != 0:
# jabc failed or stopped. Write a status file to update the status to unknown
with open(tmplog_name, "w") as f:
......
......@@ -44,14 +44,7 @@ ABC_NAMESPACE_HEADER_START
////////////////////////////////////////////////////////////////////////
/*=== utilSignal.c ==========================================================*/
extern void Util_SignalCleanup();
extern void Util_SignalStartHandler();
extern void Util_SignalResetHandler();
extern void Util_SignalStopHandler();
extern void Util_SignalBlockSignals();
extern void Util_SignalUnblockSignals();
extern void Util_SignalAddChildPid(int pid);
extern void Util_SignalRemoveChildPid(int pid);
extern int Util_SignalTmpFile(const char* prefix, const char* suffix, char** out_name);
extern void Util_SignalTmpFileRemove(const char* fname, int fLeave);
extern int Util_SignalSystem(const char* cmd);
......
......@@ -61,4 +61,21 @@ pyabc.tgz : $(PROG) $(ABC_PYTHON_SRC:_wrap.c=.py) $(ABC_PYTHON_FILES_PREFIX)/abc
--out=$@ \
$(ABC_PYTHON_OPTIONS)
PYABC_INSTALL_TARGET ?= $(shell date +%Y-%m-%d_%H-%M.%N_${USER})
PYABC_INSTALL_TARGET := $(PYABC_INSTALL_TARGET)
PYABC_INSTALL_DIR ?= /hd/common/pyabc/builds/pyabc_builds/
.PHONY: zzz
pyabc_install_target: pyabc_extension_bdist
mkdir -p "$(PYABC_INSTALL_DIR)/$(PYABC_INSTALL_TARGET)"
tar \
--directory="$(PYABC_INSTALL_DIR)/$(PYABC_INSTALL_TARGET)" \
--show-transformed-names \
--transform='s#^.*/##g' \
-xvzf "$(ABC_PYTHON_FILES_PREFIX)/dist/pyabc-1.0.linux-x86_64.tar.gz"
find "$(PYABC_INSTALL_DIR)/$(PYABC_INSTALL_TARGET)/"* -type d | xargs rmdir
echo "Installed at $(PYABC_INSTALL_DIR)/$(PYABC_INSTALL_TARGET)"
endif
......@@ -15,7 +15,6 @@ Caveats:
1. Global variables in the parent process are not affected by the child processes.
2. The functions can only return simple types, see the pickle module for details
3. Signals are currently not handled correctly
Usage:
......@@ -91,47 +90,6 @@ from contextlib import contextmanager
import pyabc
def _waitpid(pid, flags):
while True:
try:
res = os.waitpid(pid, flags)
return res
except OSError as e:
if e.errno != errno.EINTR:
raise
def _wait():
while True:
try:
pid,rc = os.wait()
return pid, rc
except OSError as e:
if e.errno != errno.EINTR:
raise
except Exceptions as e:
raise
class _sigint_critical_section(object):
def __init__(self):
self.blocked = False
def __enter__(self):
self.acquire()
return self
def __exit__(self, type, value, traceback):
self.release()
def acquire(self):
if not self.blocked:
self.blocked = True
pyabc.block_sigint()
def release(self):
if self.blocked:
self.blocked = False
pyabc.restore_sigint_block()
class _splitter(object):
def __init__(self, funcs):
......@@ -144,18 +102,19 @@ class _splitter(object):
return len(self.fds) == 0
def cleanup(self):
# close pipes and kill child processes
for pid,(i,fd) in self.fds.iteritems():
os.close(fd)
os.kill( pid, signal.SIGINT )
try:
os.kill( pid, signal.SIGINT )
except Exception as e:
print >>sys.stderr, 'exception while trying to kill pid=%d: '%pid, e
raise
with _sigint_critical_section() as cs:
# wait for termination and update result
for pid, _ in self.fds.iteritems():
_waitpid( pid, 0 )
pyabc.remove_child_pid(pid)
self.results[pid] = None
for pid, _ in self.fds.iteritems():
os.waitpid( pid, 0 )
self.results[pid] = None
self.fds = {}
......@@ -179,22 +138,20 @@ class _splitter(object):
try:
with _sigint_critical_section() as cs:
# create child process
pid = os.fork()
if pid == 0:
# child process:
pyabc.reset_sigint_handler()
cs.release()
os.close(pr)
rc = self.child( pw, f)
os._exit(rc)
else:
# parent process:
pyabc.add_child_pid(pid)
os.close(pw)
return (pid, pr)
# create child process
pid = os.fork()
if pid == 0:
# child process:
os.close(pr)
pyabc.close_on_fork(pw)
rc = self.child( pw, f)
os._exit(rc)
else:
# parent process:
os.close(pw)
return (pid, pr)
finally:
if os.getpid() != parentpid:
......@@ -209,12 +166,9 @@ class _splitter(object):
def get_next_result(self):
# wait for the next child process to terminate
pid, rc = _wait()
pid, rc = os.wait()
assert pid in self.fds
with _sigint_critical_section() as cs:
pyabc.remove_child_pid(pid)
# retrieve the pipe file descriptor1
i, fd = self.fds[pid]
del self.fds[pid]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment