Commit cbc718d7 by Baruch Sterin

pyabc changes for HWMCC13

parent 7a1c4ee8
...@@ -34,6 +34,12 @@ ifdef ABC_PYTHON ...@@ -34,6 +34,12 @@ ifdef ABC_PYTHON
$(ABC_PYTHON_FILES_PREFIX)/dist \ $(ABC_PYTHON_FILES_PREFIX)/dist \
pyabc.tgz pyabc.tgz
ABC_PYABC_DIR ?= pyabc
ABC_PYABC_TGZ ?= pyabc.tgz
ABC_PYABC_EXTRA_BIN ?=
ABC_PYABC_EXTRA_LIB ?=
%_wrap.c %.py : %.i %_wrap.c %.py : %.i
$(ABC_SWIG) -python -outdir $(<D) $< $(ABC_SWIG) -python -outdir $(<D) $<
...@@ -53,11 +59,18 @@ pyabc_extension_install : pyabc_extension_build ...@@ -53,11 +59,18 @@ pyabc_extension_install : pyabc_extension_build
pyabc_extension_bdist : pyabc_extension_build pyabc_extension_bdist : pyabc_extension_build
( cd $(ABC_PYTHON_FILES_PREFIX) && python setup.py bdist ) ( cd $(ABC_PYTHON_FILES_PREFIX) && python setup.py bdist )
pyabc.tgz : $(PROG) $(ABC_PYTHON_SRC:_wrap.c=.py) $(ABC_PYTHON_FILES_PREFIX)/abc.sh $(ABC_PYTHON_FILES_PREFIX)/package.py .PHONY: pyabc_tgz
pyabc_tgz : $(ABC_PYABC_TGZ)
$(ABC_PYABC_TGZ) : $(PROG) $(ABC_PYTHON_SRC:_wrap.c=.py) $(ABC_PYTHON_FILES_PREFIX)/abc.sh $(ABC_PYTHON_FILES_PREFIX)/package.py
$(ABC_PYTHON) $(ABC_PYTHON_FILES_PREFIX)/package.py \ $(ABC_PYTHON) $(ABC_PYTHON_FILES_PREFIX)/package.py \
--pyabc_dir=$(ABC_PYABC_DIR) \
--abc=$(PROG) \ --abc=$(PROG) \
--abc_sh=$(ABC_PYTHON_FILES_PREFIX)/abc.sh \ --abc_sh=$(ABC_PYTHON_FILES_PREFIX)/abc.sh \
--pyabc=$(ABC_PYTHON_FILES_PREFIX) \ --pyabc=$(ABC_PYTHON_FILES_PREFIX) \
--extra_bin="$(ABC_PYABC_EXTRA_BIN)" \
--extra_lib="$(ABC_PYABC_EXTRA_LIB)" \
--out=$@ \ --out=$@ \
$(ABC_PYTHON_OPTIONS) $(ABC_PYTHON_OPTIONS)
......
...@@ -5,6 +5,7 @@ import zipfile ...@@ -5,6 +5,7 @@ import zipfile
import tarfile import tarfile
import tempfile import tempfile
import time import time
import py_compile
def zip_library(f, extra_files = []): def zip_library(f, extra_files = []):
lib = "%s/lib/python%s/"%(sys.prefix,sys.version[:3]) lib = "%s/lib/python%s/"%(sys.prefix,sys.version[:3])
...@@ -15,13 +16,25 @@ def zip_library(f, extra_files = []): ...@@ -15,13 +16,25 @@ def zip_library(f, extra_files = []):
arcroot = os.path.relpath(root, lib) arcroot = os.path.relpath(root, lib)
for f in files: for f in files:
_, ext = os.path.splitext(f) _, ext = os.path.splitext(f)
if ext in ['.py', '.pyo', '.pyc']: if ext in ['.py']:
zf.write(os.path.join(root,f), os.path.join(arcroot, f)) zf.write(os.path.join(root,f), os.path.join(arcroot, f))
for s, r in extra_files: for s, r in extra_files:
zf.write( s, r ) zf.write( s, r )
zf.close() zf.close()
def add_python_lib(tf, lib_dir, lib, mtime):
for root, _, files in os.walk(lib):
arcroot = os.path.join( lib_dir, os.path.relpath(root, lib) )
add_dir(tf, arcroot, mtime)
for f in files:
_, ext = os.path.splitext(f)
if ext in ['.py']:
add_file( tf, os.path.join(root,f), os.path.join(arcroot, f), 0666, mtime)
def add_dir(tf, dir, mtime): def add_dir(tf, dir, mtime):
ti = tarfile.TarInfo(dir) ti = tarfile.TarInfo(dir)
...@@ -43,21 +56,23 @@ def add_fileobj(tf, f, arcname, mode, mtime): ...@@ -43,21 +56,23 @@ def add_fileobj(tf, f, arcname, mode, mtime):
tf.addfile(ti, f) tf.addfile(ti, f)
def add_file(tf, fname, arcname, mode, mtime): def add_file(tf, fname, arcname, mode, mtime):
f = open(fname, "rb") print "\t adding %s as %s"%(fname, arcname)
add_fileobj(tf, f, arcname, mode, mtime)
f.close() with open(fname, "rb") as f:
add_fileobj(tf, f, arcname, mode, mtime)
def package(abc_exe, abc_sh, pyabc, ofname, scripts_dir, use_sys): def package(pyabc_dir, extra_bin, extra_lib, abc_exe, abc_sh, pyabc, ofname, scripts_dir, use_sys):
mtime = time.time() mtime = time.time()
tf = tarfile.open(ofname, "w:gz") tf = tarfile.open(ofname, "w:gz")
add_dir(tf, "pyabc", mtime) add_dir(tf, "%s"%pyabc_dir, mtime)
add_dir(tf, "pyabc/bin", mtime) add_dir(tf, "%s/bin"%pyabc_dir, mtime)
add_file(tf, abc_exe, "pyabc/bin/abc_exe", 0777, mtime) add_file(tf, abc_exe, "%s/bin/abc_exe"%pyabc_dir, 0777, mtime)
add_file(tf, abc_sh, "pyabc/bin/abc", 0777, mtime) add_file(tf, abc_sh, "%s/bin/abc"%pyabc_dir, 0777, mtime)
if scripts_dir: if scripts_dir:
for fn in os.listdir(scripts_dir): for fn in os.listdir(scripts_dir):
...@@ -65,15 +80,23 @@ def package(abc_exe, abc_sh, pyabc, ofname, scripts_dir, use_sys): ...@@ -65,15 +80,23 @@ def package(abc_exe, abc_sh, pyabc, ofname, scripts_dir, use_sys):
if os.path.isfile(fullname): if os.path.isfile(fullname):
fnroot, fnext = os.path.splitext(fn) fnroot, fnext = os.path.splitext(fn)
if fnext==".sh": if fnext==".sh":
add_file( tf, fullname, os.path.join("pyabc/bin", fnroot), 0777, mtime) add_file( tf, fullname, os.path.join("%s/bin"%pyabc_dir, fnroot), 0777, mtime)
else: elif fnext not in ( '.pyc', '.pyo'):
add_file( tf, fullname, os.path.join("pyabc/scripts", fn), 0666, mtime) add_file( tf, fullname, os.path.join("%s/scripts"%pyabc_dir, fn), 0666, mtime)
add_dir(tf, "pyabc/lib", mtime) for bin in extra_bin:
add_file( tf, bin, os.path.join("%s/bin"%pyabc_dir, os.path.basename(bin)), 0777, mtime)
lib_dir = "%s/lib"%pyabc_dir
add_dir(tf, lib_dir, mtime)
for lib in extra_lib:
add_python_lib( tf, lib_dir, lib, mtime)
for entry in os.listdir(pyabc): for entry in os.listdir(pyabc):
if entry.endswith('.py'): if entry.endswith('.py'):
add_file( tf, os.path.join(pyabc, entry), os.path.join("pyabc/lib", entry), 0666, mtime) add_file( tf, os.path.join(pyabc, entry), os.path.join("%s/lib"%pyabc_dir, entry), 0666, mtime)
if not use_sys: if not use_sys:
# ZIP standard library # ZIP standard library
...@@ -82,7 +105,7 @@ def package(abc_exe, abc_sh, pyabc, ofname, scripts_dir, use_sys): ...@@ -82,7 +105,7 @@ def package(abc_exe, abc_sh, pyabc, ofname, scripts_dir, use_sys):
zip_library(zf, []) zip_library(zf, [])
zf.flush() zf.flush()
add_fileobj(tf, zf, "pyabc/lib/python_library.zip", 0666, mtime) add_fileobj(tf, zf, "%s/lib/python_library.zip"%pyabc_dir, 0666, mtime)
zf.close() zf.close()
...@@ -93,7 +116,7 @@ def package(abc_exe, abc_sh, pyabc, ofname, scripts_dir, use_sys): ...@@ -93,7 +116,7 @@ def package(abc_exe, abc_sh, pyabc, ofname, scripts_dir, use_sys):
for fn in os.listdir(lib_dynload): for fn in os.listdir(lib_dynload):
fullname = os.path.join(lib_dynload, fn) fullname = os.path.join(lib_dynload, fn)
if os.path.isfile(fullname): if os.path.isfile(fullname):
add_file( tf, fullname, os.path.join("pyabc/lib", fn), 0666, mtime) add_file( tf, fullname, os.path.join("%s/lib"%pyabc_dir, fn), 0666, mtime)
tf.close() tf.close()
...@@ -104,6 +127,9 @@ def main(args): ...@@ -104,6 +127,9 @@ def main(args):
parser = optparse.OptionParser(usage) parser = optparse.OptionParser(usage)
parser.add_option("-d", "--pyabc_dir", dest="pyabc_dir", help="name of generated directory" )
parser.add_option("-b", "--extra_bin", dest="extra_bin", help="extra binaries to pack" )
parser.add_option("-l", "--extra_lib", dest="extra_lib", help="extra directories in lib to pack" )
parser.add_option("-a", "--abc", dest="abc", help="location of the ABC exeutable") parser.add_option("-a", "--abc", dest="abc", help="location of the ABC exeutable")
parser.add_option("-s", "--abc_sh", dest="abc_sh", help="location of the ABC setup script") parser.add_option("-s", "--abc_sh", dest="abc_sh", help="location of the ABC setup script")
parser.add_option("-p", "--pyabc", dest="pyabc", help="location of pyabc.py") parser.add_option("-p", "--pyabc", dest="pyabc", help="location of pyabc.py")
...@@ -117,11 +143,14 @@ def main(args): ...@@ -117,11 +143,14 @@ def main(args):
parser.print_help() parser.print_help()
return 1 return 1
if not options.abc or not options.abc_sh or not options.pyabc or not options.out: if not options.pyabc_dir or not options.abc or not options.abc_sh or not options.pyabc or not options.out:
parser.print_help() parser.print_help()
return 1 return 1
return package(options.abc, options.abc_sh, options.pyabc, options.out, options.scripts, options.sys) extra_bin = options.extra_bin.split(',') if options.extra_bin else []
extra_lib = options.extra_lib.split(',') if options.extra_lib else []
return package(options.pyabc_dir, extra_bin, extra_lib, options.abc, options.abc_sh, options.pyabc, options.out, options.scripts, options.sys)
if __name__=="__main__": if __name__=="__main__":
main(sys.argv) main(sys.argv)
...@@ -430,7 +430,7 @@ void pyabc_internal_register_command( char * sGroup, char * sName, int fChanges ...@@ -430,7 +430,7 @@ void pyabc_internal_register_command( char * sGroup, char * sName, int fChanges
{ {
Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame(); Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame();
Cmd_CommandAdd( pAbc, sGroup, sName, (int(*)(Abc_Frame_t*, int, char**))pyabc_internal_abc_command_callback, fChanges); Cmd_CommandAdd( pAbc, sGroup, sName, (Cmd_CommandFuncType)pyabc_internal_abc_command_callback, fChanges);
} }
static int sigchld_pipe_fd = -1; static int sigchld_pipe_fd = -1;
...@@ -637,7 +637,14 @@ int _posix_kill(int pid, int signum) ...@@ -637,7 +637,14 @@ int _posix_kill(int pid, int signum)
void _set_death_signal() void _set_death_signal()
{ {
// send SIGINT if parent process is dead
prctl(PR_SET_PDEATHSIG, SIGINT); prctl(PR_SET_PDEATHSIG, SIGINT);
// if parent process is already dead (and adopted by init)
if ( getppid() == 1)
{
raise(SIGINT);
}
} }
%} %}
......
...@@ -90,6 +90,8 @@ import cPickle as pickle ...@@ -90,6 +90,8 @@ import cPickle as pickle
import signal import signal
import cStringIO import cStringIO
import traceback
from contextlib import contextmanager from contextlib import contextmanager
import pyabc import pyabc
...@@ -107,8 +109,7 @@ def _retry_select(rlist): ...@@ -107,8 +109,7 @@ def _retry_select(rlist):
class _splitter(object): class _splitter(object):
def __init__(self, funcs): def __init__(self):
self.funcs = funcs
self.pids = [] self.pids = []
self.fds = {} self.fds = {}
self.buffers = {} self.buffers = {}
...@@ -117,27 +118,49 @@ class _splitter(object): ...@@ -117,27 +118,49 @@ class _splitter(object):
def is_done(self): def is_done(self):
return len(self.fds) == 0 return len(self.fds) == 0
def cleanup(self): def _kill(self, pids):
# close pipes and kill child processes # close pipes and kill child processes
for pid,(i,fd) in self.fds.iteritems(): for pid in pids:
if pid == -1:
continue
i, fd = self.fds[pid]
del self.buffers[fd]
del self.fds[pid]
self.pids[i] = -1
self.results[pid] = None
os.close(fd) os.close(fd)
try: try:
os.kill( pid, signal.SIGINT ) os.kill( pid, signal.SIGINT)
except Exception as e: except Exception as e:
print >>sys.stderr, 'exception while trying to kill pid=%d: '%pid, e print >>sys.stderr, 'exception while trying to kill pid=%d: '%pid, e
raise raise
# wait for termination and update result # wait for termination and update result
for pid, _ in self.fds.iteritems(): for pid in pids:
os.waitpid( pid, 0 ) os.waitpid( pid, 0 )
self.results[pid] = None
def kill(self, ids):
self._kill( [ self.pids[i] for i in ids ] )
self.fds = {} def cleanup(self):
self.buffers = {} self._kill( self.fds.keys() )
def child( self, fdw, f): def child( self, fdw, f):
# call function # call function
res = f() try:
res = f()
except:
traceback.print_exc()
raise
# write return value into pipe # write return value into pipe
with os.fdopen( fdw, "w" ) as fout: with os.fdopen( fdw, "w" ) as fout:
...@@ -145,7 +168,7 @@ class _splitter(object): ...@@ -145,7 +168,7 @@ class _splitter(object):
return 0 return 0
def fork_one(self, f): def _fork_one(self, f):
# create a pipe to communicate with the child process # create a pipe to communicate with the child process
pr,pw = os.pipe() pr,pw = os.pipe()
...@@ -177,13 +200,17 @@ class _splitter(object): ...@@ -177,13 +200,17 @@ class _splitter(object):
if os.getpid() != parentpid: if os.getpid() != parentpid:
os._exit(rc) os._exit(rc)
def fork_all(self): def fork_one(self, func):
for i,f in enumerate(self.funcs): pid, fd = self._fork_one(func)
pid, fd = self.fork_one(f) i = len(self.pids)
self.pids.append(pid) self.pids.append(pid)
self.fds[pid] = (i,fd) self.fds[pid] = (i, fd)
self.buffers[fd] = cStringIO.StringIO() self.buffers[fd] = cStringIO.StringIO()
return i
def fork_all(self, funcs):
return [ self.fork_one(f) for f in funcs ]
def communicate(self): def communicate(self):
rlist = [ fd for _, (_,fd) in self.fds.iteritems() ] rlist = [ fd for _, (_,fd) in self.fds.iteritems() ]
...@@ -216,6 +243,9 @@ class _splitter(object): ...@@ -216,6 +243,9 @@ class _splitter(object):
i, fd = self.fds[pid] i, fd = self.fds[pid]
del self.fds[pid] del self.fds[pid]
# remove the pid
self.pids[i] = -1
# retrieve the buffer # retrieve the buffer
buffer = self.buffers[fd] buffer = self.buffers[fd]
del self.buffers[fd] del self.buffers[fd]
...@@ -226,29 +256,37 @@ class _splitter(object): ...@@ -226,29 +256,37 @@ class _splitter(object):
if not s: if not s:
break break
buffer.write(s) buffer.write(s)
os.close(fd)
try: try:
return (i, pickle.loads(buffer.getvalue())) return (i, pickle.loads(buffer.getvalue()))
except EOFError, pickle.UnpicklingError: except EOFError, pickle.UnpicklingError:
return (i, None) return (i, None)
def __iter__(self):
def iterator():
while not self.is_done():
yield self.get_next_result()
return iterator()
@contextmanager @contextmanager
def _splitter_wrapper(funcs): def make_splitter():
# ensure cleanup of child processes # ensure cleanup of child processes
s = _splitter(funcs) s = _splitter()
try: try:
yield s yield s
finally: finally:
s.cleanup() s.cleanup()
def split_all_full(funcs): def split_all_full(funcs):
# provide an iterator for child process result # provide an iterator for child process result
with _splitter_wrapper(funcs) as s: with make_splitter() as s:
s.fork_all() s.fork_all(funcs)
while not s.is_done(): for res in s:
yield s.get_next_result() yield res
def defer(f): def defer(f):
return lambda *args, **kwargs: lambda : f(*args,**kwargs) return lambda *args, **kwargs: lambda : f(*args,**kwargs)
......
...@@ -25,6 +25,23 @@ def _dup( f ): ...@@ -25,6 +25,23 @@ def _dup( f ):
os.close(fd) os.close(fd)
@contextmanager @contextmanager
def save_stdout( src = sys.stdout ):
"""
Redirect
"""
fd = os.dup( src.fileno() )
own = True
try:
with os.fdopen( fd, "w", 0) as f:
own = False
yield f
except:
if own:
os.close(fd)
raise
@contextmanager
def redirect(dst = null_file, src = sys.stdout): def redirect(dst = null_file, src = sys.stdout):
""" """
......
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