From 24dd33862a1c42cdb57464acc448ef79de1ff085 2010-08-05 15:56:40 From: epatters Date: 2010-08-05 15:56:40 Subject: [PATCH] Kernel subprocess parent polling is now implemented correctly for Unix. --- diff --git a/IPython/zmq/kernel.py b/IPython/zmq/kernel.py index cf82f12..4fb4f49 100755 --- a/IPython/zmq/kernel.py +++ b/IPython/zmq/kernel.py @@ -348,22 +348,35 @@ class Kernel(object): # Kernel main and launch functions #----------------------------------------------------------------------------- -class UnixPoller(Thread): +class ExitPollerUnix(Thread): + """ A Unix-specific daemon thread that terminates the program immediately + when this process' parent process no longer exists. + """ def __init__(self): - super(UnixPoller, self).__init__() + super(ExitPollerUnix, self).__init__() self.daemon = True def run(self): + # We cannot use os.waitpid because it works only for child processes. + from errno import EINTR while True: - if os.getppid() == 1: - os._exit(1) - time.sleep(5.0) - -class WindowsPoller(Thread): + try: + if os.getppid() == 1: + os._exit(1) + time.sleep(1.0) + except OSError, e: + if e.errno == EINTR: + continue + raise + +class ExitPollerWindows(Thread): + """ A Windows-specific daemon thread that terminates the program immediately + when a Win32 handle is signaled. + """ def __init__(self, handle): - super(WindowsPoller, self).__init__() + super(ExitPollerWindows, self).__init__() self.daemon = True self.handle = handle @@ -373,6 +386,7 @@ class WindowsPoller(Thread): if result == WAIT_OBJECT_0: os._exit(1) + def bind_port(socket, ip, port): """ Binds the specified ZMQ socket. If the port is less than zero, a random port is chosen. Returns the port that was bound. @@ -385,6 +399,7 @@ def bind_port(socket, ip, port): socket.bind(connection) return port + def main(): """ Main entry point for launching a kernel. """ @@ -435,17 +450,11 @@ def main(): # Configure this kernel/process to die on parent termination, if necessary. if namespace.parent: - if sys.platform == 'linux2': - import ctypes, ctypes.util, signal - PR_SET_PDEATHSIG = 1 - libc = ctypes.CDLL(ctypes.util.find_library('c')) - libc.prctl(PR_SET_PDEATHSIG, signal.SIGKILL) - elif sys.platform == 'win32': - poller = WindowsPoller(namespace.parent) - poller.start() + if sys.platform == 'win32': + poller = ExitPollerWindows(namespace.parent) else: - poller = UnixPoller() - poller.start() + poller = ExitPollerUnix() + poller.start() # Start the kernel mainloop. kernel.start() diff --git a/IPython/zmq/kernelmanager.py b/IPython/zmq/kernelmanager.py index 166147d..e0089e2 100644 --- a/IPython/zmq/kernelmanager.py +++ b/IPython/zmq/kernelmanager.py @@ -448,6 +448,7 @@ class KernelManager(HasTraits): def __init__(self, xreq_address=None, sub_address=None, rep_address=None, context=None, session=None): + super(KernelManager, self).__init__() self._xreq_address = (LOCALHOST, 0) if xreq_address is None else xreq_address self._sub_address = (LOCALHOST, 0) if sub_address is None else sub_address self._rep_address = (LOCALHOST, 0) if rep_address is None else rep_address