Hi All, We create our customised manager which will fork child process with baseManager. Because we registered SIGCHLD to reap the zombie for manager, we found this causes baseManager raise RemoteError when called twice.(Test script attached.)
After look at baseManager.py we found recv() in handling the request has been interrupted by comming SIGCHLD, not retry recv(), but raise to client side directly. try: methodname = obj = None request = recv()<------------------this line been interrupted by SIGCHLD ident, methodname, args, kwds = request obj, exposed, gettypeid = id_to_obj[ident] if methodname not in exposed: raise AttributeError( 'method %r of %r object is not in exposed=%r' % (methodname, type(obj), exposed) ) function = getattr(obj, methodname) try: res = function(*args, **kwds) except Exception, e: msg = ('#ERROR', e) else: typeid = gettypeid and gettypeid.get(methodname, None) if typeid: rident, rexposed = self.create(conn, typeid, res) token = Token(typeid, self.address, rident) msg = ('#PROXY', (rexposed, token)) else: msg = ('#RETURN', res) except AttributeError: if methodname is None: msg = ('#TRACEBACK', format_exc()) else: try: fallback_func = self.fallback_mapping[methodname] result = fallback_func( self, conn, ident, obj, *args, **kwds ) msg = ('#RETURN', result) except Exception: msg = ('#TRACEBACK', format_exc()) except EOFError: util.debug('got EOF -- exiting thread serving %r', threading.current_thread().name) sys.exit(0) except Exception:<------does not handle IOError,INTR here should retry recv() msg = ('#TRACEBACK', format_exc()) REF: http://bugs.python.org/issue17097
import sys import os from time import sleep import signal from multiprocessing import Process from multiprocessing.managers import BaseManager import threading class _SuperVdsmManager(BaseManager): pass def func(): return 'func' class _SuperVdsm(object): def runChild(self): proc = Process(target=func) proc.start() proc.terminate() def _zombieReaper(signum, frame): print "sigchld!" def startSuper(): try: address = '/home/lvroyce.sock' if os.path.exists(address): os.unlink(address) signal.signal(signal.SIGCHLD, _zombieReaper) try: manager = _SuperVdsmManager(address=address, authkey='abc') manager.register('instance', callable=_SuperVdsm) server = manager.get_server() servThread = threading.Thread(target=server.serve_forever) servThread.setDaemon(True) servThread.start() while servThread.isAlive(): servThread.join(5) except: raise finally: if os.path.exists(address): os.unlink(address) except Exception: sys.exit(1) def main(): sv = Process(target=startSuper) sv.start() sleep(2) _manager = _SuperVdsmManager(address='/home/lvroyce.sock', authkey='abc') _manager.register('instance') _manager.connect() _svdsm = _manager.instance() _svdsm.runChild() sleep(4) _svdsm.runChild() if __name__ == '__main__': main()
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com