Commit 252c256f authored by Denis Bilenko's avatar Denis Bilenko

Fix #210: callbacks were not run for non-default loop

parent 7ea87d22
......@@ -36,6 +36,10 @@ static void gevent_handle_error(struct PyGeventLoopObject* loop, PyObject* conte
static CYTHON_INLINE void gevent_check_signals(struct PyGeventLoopObject* loop) {
if (!ev_is_default_loop(loop->_ptr)) {
/* only reporting signals on the default loop */
return;
}
PyErr_CheckSignals();
if (PyErr_Occurred()) gevent_handle_error(loop, Py_None);
}
......@@ -136,17 +140,16 @@ end:
static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallbackObject* cb) {
GIL_DECLARE;
/* no need for GIL here because it is only called from run_callbacks which already has GIL */
PyObject *result, *callback, *args;
GIL_ENSURE;
if (!loop || !cb)
goto end;
return;
callback = cb->callback;
args = cb->args;
if (!callback || !args)
goto end;
return;
if (callback == Py_None || args == Py_None)
goto end;
return;
Py_INCREF(loop);
Py_INCREF(callback);
Py_INCREF(args);
......@@ -170,8 +173,6 @@ static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallback
Py_DECREF(callback);
Py_DECREF(args);
Py_DECREF(loop);
end:
GIL_RELEASE;
}
......@@ -191,7 +192,7 @@ static void gevent_run_callbacks(struct ev_loop *_loop, void *watcher, int reven
PyObject *result;
GIL_DECLARE;
GIL_ENSURE;
loop = GET_OBJECT(PyGeventLoopObject, watcher, _signal_checker);
loop = GET_OBJECT(PyGeventLoopObject, watcher, _prepare);
Py_INCREF(loop);
gevent_check_signals(loop);
result = ((struct __pyx_vtabstruct_6gevent_4core_loop *)loop->__pyx_vtab)->_run_callbacks(loop);
......
......@@ -227,7 +227,7 @@ cdef bint _default_loop_destroyed = False
cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
cdef libev.ev_loop* _ptr
cdef public object error_handler
cdef libev.ev_prepare _signal_checker
cdef libev.ev_prepare _prepare
cdef public list _callbacks
cdef libev.ev_timer _timer0
#ifdef _WIN32
......@@ -237,7 +237,7 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
def __init__(self, object flags=None, object default=None, size_t ptr=0):
cdef unsigned int c_flags
cdef object old_handler = None
libev.ev_prepare_init(&self._signal_checker, <void*>gevent_run_callbacks)
libev.ev_prepare_init(&self._prepare, <void*>gevent_run_callbacks)
#ifdef _WIN32
libev.ev_timer_init(&self._periodic_signal_checker, <void*>gevent_periodic_signal_check, 0.3, 0.3)
#endif
......@@ -256,8 +256,6 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
self._ptr = libev.gevent_ev_default_loop(c_flags)
if not self._ptr:
raise SystemError("ev_default_loop(%s) failed" % (c_flags, ))
libev.ev_prepare_start(self._ptr, &self._signal_checker)
libev.ev_unref(self._ptr)
#ifdef _WIN32
libev.ev_timer_start(self._ptr, &self._periodic_signal_checker)
libev.ev_unref(self._ptr)
......@@ -268,6 +266,8 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
raise SystemError("ev_loop_new(%s) failed" % (c_flags, ))
if default or __SYSERR_CALLBACK is None:
set_syserr_cb(self._handle_syserr)
libev.ev_prepare_start(self._ptr, &self._prepare)
libev.ev_unref(self._ptr)
self._callbacks = []
cdef _run_callbacks(self):
......@@ -286,9 +286,9 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
libev.ev_timer_start(self._ptr, &self._timer0)
def _stop_watchers(self):
if libev.ev_is_active(&self._signal_checker):
if libev.ev_is_active(&self._prepare):
libev.ev_ref(self._ptr)
libev.ev_prepare_stop(self._ptr, &self._signal_checker)
libev.ev_prepare_stop(self._ptr, &self._prepare)
#ifdef _WIN32
if libev.ev_is_active(&self._periodic_signal_checker):
libev.ev_ref(self._ptr)
......
# test for issue #210
from gevent import core
import time
import sys
import os
import threading
class alarm(threading.Thread):
# can't use signal.alarm because of Windows
def __init__(self, timeout):
threading.Thread.__init__(self)
self.setDaemon(True)
self.timeout = timeout
self.start()
def run(self):
time.sleep(self.timeout)
sys.stderr.write('Timeout.\n')
os._exit(5)
alarm(1)
log = []
loop = core.loop(default=False)
loop.run_callback(log.append, 1)
loop.run()
assert log == [1], log
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