Commit 0c5685c6 authored by Denis Bilenko's avatar Denis Bilenko

core: add child handler. WARNING: libev reaps all child processes now. to...

core: add child handler. WARNING: libev reaps all child processes now. to disable it, pass 'nochild' option to loop.
parent 64e52011
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
DEFINE_CALLBACK(idle, Idle); \ DEFINE_CALLBACK(idle, Idle); \
DEFINE_CALLBACK(prepare, Prepare); \ DEFINE_CALLBACK(prepare, Prepare); \
DEFINE_CALLBACK(fork, Fork); \ DEFINE_CALLBACK(fork, Fork); \
DEFINE_CALLBACK(async, Async); DEFINE_CALLBACK(async, Async); \
DEFINE_CALLBACK(child, Child);
DEFINE_CALLBACKS DEFINE_CALLBACKS
......
...@@ -5,7 +5,7 @@ from python cimport * ...@@ -5,7 +5,7 @@ from python cimport *
import sys import sys
import os import os
import traceback import traceback
from signal import NSIG import signal as signalmodule
__all__ = ['get_version', __all__ = ['get_version',
...@@ -70,6 +70,10 @@ NOINOTIFY = libev.EVFLAG_NOINOTIFY ...@@ -70,6 +70,10 @@ NOINOTIFY = libev.EVFLAG_NOINOTIFY
SIGNALFD = libev.EVFLAG_SIGNALFD SIGNALFD = libev.EVFLAG_SIGNALFD
NOSIGMASK = libev.EVFLAG_NOSIGMASK NOSIGMASK = libev.EVFLAG_NOSIGMASK
# gevent-added flag:
cdef int c_NOCHILD = 0x0100000U
NOCHILD = c_NOCHILD
@cython.internal @cython.internal
cdef class _EVENTSType: cdef class _EVENTSType:
...@@ -99,7 +103,8 @@ _flags = [(libev.EVBACKEND_PORT, 'port'), ...@@ -99,7 +103,8 @@ _flags = [(libev.EVBACKEND_PORT, 'port'),
(libev.EVFLAG_NOENV, 'noenv'), (libev.EVFLAG_NOENV, 'noenv'),
(libev.EVFLAG_FORKCHECK, 'forkcheck'), (libev.EVFLAG_FORKCHECK, 'forkcheck'),
(libev.EVFLAG_SIGNALFD, 'signalfd'), (libev.EVFLAG_SIGNALFD, 'signalfd'),
(libev.EVFLAG_NOSIGMASK, 'nosigmask')] (libev.EVFLAG_NOSIGMASK, 'nosigmask'),
(NOCHILD, 'nochild')]
_flags_str2int = dict((string, flag) for (flag, string) in _flags) _flags_str2int = dict((string, flag) for (flag, string) in _flags)
...@@ -229,6 +234,7 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]: ...@@ -229,6 +234,7 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
def __init__(self, object flags=None, object default=True, size_t ptr=0): def __init__(self, object flags=None, object default=True, size_t ptr=0):
cdef unsigned int c_flags cdef unsigned int c_flags
cdef object old_handler = None
libev.ev_prepare_init(&self._signal_checker, <void*>gevent_signal_check) libev.ev_prepare_init(&self._signal_checker, <void*>gevent_signal_check)
#ifdef _WIN32 #ifdef _WIN32
libev.ev_timer_init(&self._periodic_signal_checker, <void*>gevent_periodic_signal_check, 0.3, 0.3) libev.ev_timer_init(&self._periodic_signal_checker, <void*>gevent_periodic_signal_check, 0.3, 0.3)
...@@ -242,9 +248,13 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]: ...@@ -242,9 +248,13 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
if _default_loop_destroyed: if _default_loop_destroyed:
default = False default = False
if default: if default:
if c_flags & c_NOCHILD:
old_handler = signalmodule.getsignal(signalmodule.SIGCHLD)
self._ptr = libev.ev_default_loop(c_flags) self._ptr = libev.ev_default_loop(c_flags)
if not self._ptr: if not self._ptr:
raise SystemError("ev_default_loop(%s) failed" % (c_flags, )) raise SystemError("ev_default_loop(%s) failed" % (c_flags, ))
if c_flags & c_NOCHILD:
signalmodule.signal(signalmodule.SIGCHLD, old_handler)
libev.ev_prepare_start(self._ptr, &self._signal_checker) libev.ev_prepare_start(self._ptr, &self._signal_checker)
libev.ev_unref(self._ptr) libev.ev_unref(self._ptr)
#ifdef _WIN32 #ifdef _WIN32
...@@ -419,8 +429,10 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]: ...@@ -419,8 +429,10 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
def async(self, ref=True): def async(self, ref=True):
return async(self, ref) return async(self, ref)
#def child(self, int pid, bint trace=0): def child(self, int pid, bint trace=0):
# return child(self, pid, trace) if self._ptr.origflags & c_NOCHILD:
raise TypeError('child watchers are not available because "nochild" is in effect')
return child(self, pid, trace)
def callback(self): def callback(self):
return callback(self) return callback(self)
...@@ -762,7 +774,7 @@ cdef public class signal(watcher) [object PyGeventSignalObject, type PyGeventSig ...@@ -762,7 +774,7 @@ cdef public class signal(watcher) [object PyGeventSignalObject, type PyGeventSig
WATCHER(signal) WATCHER(signal)
def __init__(self, loop loop, int signalnum, ref=True): def __init__(self, loop loop, int signalnum, ref=True):
if signalnum < 1 or signalnum >= NSIG: if signalnum < 1 or signalnum >= signalmodule.NSIG:
raise ValueError('illegal signal number: %r' % signalnum) raise ValueError('illegal signal number: %r' % signalnum)
# still possible to crash on one of libev's asserts: # still possible to crash on one of libev's asserts:
# 1) "libev: ev_signal_start called with illegal signal number" # 1) "libev: ev_signal_start called with illegal signal number"
...@@ -817,11 +829,40 @@ cdef public class async(watcher) [object PyGeventAsyncObject, type PyGeventAsync ...@@ -817,11 +829,40 @@ cdef public class async(watcher) [object PyGeventAsyncObject, type PyGeventAsync
libev.ev_async_send(self.loop._ptr, &self._watcher) libev.ev_async_send(self.loop._ptr, &self._watcher)
#cdef public class child(watcher) [object PyGeventChildObject, type PyGeventChild_Type]: cdef public class child(watcher) [object PyGeventChildObject, type PyGeventChild_Type]:
#
# WATCHER(child) WATCHER(child)
#
# INIT(child, ``, int pid, bint trace=0'', ``, pid, trace'') def __init__(self, loop loop, int pid, bint trace=0, ref=True):
if not loop.default:
raise TypeError('child watchers are only available on the default loop')
libev.ev_child_init(&self._watcher, <void *>gevent_callback_child, pid, trace)
self.loop = loop
if ref:
self._flags = 0
else:
self._flags = 4
property pid:
def __get__(self):
return self._watcher.pid
property rpid:
def __get__(self):
return self._watcher.rpid
def __set__(self, int value):
self._watcher.rpid = value
property rstatus:
def __get__(self):
return self._watcher.rstatus
def __set__(self, int value):
self._watcher.rstatus = value
cdef public class callback(watcher) [object PyGeventCallbackObject, type PyGeventCallback_Type]: cdef public class callback(watcher) [object PyGeventCallbackObject, type PyGeventCallback_Type]:
......
...@@ -14,6 +14,10 @@ import gevent ...@@ -14,6 +14,10 @@ import gevent
from gevent import socket from gevent import socket
import mysubprocess as subprocess import mysubprocess as subprocess
from gevent.server import DatagramServer, StreamServer from gevent.server import DatagramServer, StreamServer
import gevent.hub
gevent.hub.Hub.backend = (getattr(gevent.hub.Hub, 'backend') or '') + ',nochild'
# Ignore tracebacks: KeyboardInterrupt # Ignore tracebacks: KeyboardInterrupt
......
...@@ -143,7 +143,6 @@ if libev_embed: ...@@ -143,7 +143,6 @@ if libev_embed:
('EV_CHECK_ENABLE', '0'), ('EV_CHECK_ENABLE', '0'),
('EV_CLEANUP_ENABLE', '0'), ('EV_CLEANUP_ENABLE', '0'),
('EV_EMBED_ENABLE', '0'), ('EV_EMBED_ENABLE', '0'),
('EV_CHILD_ENABLE', '0'),
("EV_PERIODIC_ENABLE", '0')] ("EV_PERIODIC_ENABLE", '0')]
CORE.configure = configure_libev CORE.configure = configure_libev
if sys.platform == "darwin": if sys.platform == "darwin":
......
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