Handling errors from signal handlers in callbacks
Created originally on Bitbucket by denis (Denis Bilenko)
Consider the following script:
#!python
pypycore ~/work/gevent $ cat cffi_signal_problem.py
import signal
from cffi import FFI
ffi = FFI()
ffi.cdef('''
void call_callback(void*);
''')
C = ffi.verify('''
#include <unistd.h>
void call_callback(void(*cb)(void));
void call_callback(void(*cb)(void)) {
sleep(2);
cb();
}
''', libraries=[])
def mycallback():
try:
print 'hello world'
except Exception, ex:
print 'caught error: %s' % ex
cb = ffi.callback("void(*)()", mycallback)
def alarm_handler(*args):
1 // 0
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(1)
C.call_callback(cb)
It will never print "caught error", instead it'll print this:
pypycore ~/work/gevent $ pypy cffi_signal_problem.py
From callback <function mycallback at 0x00007f4475e15100>:
Traceback (most recent call last):
File "cffi_signal_problem.py", line 20, in mycallback
try:
File "cffi_signal_problem.py", line 38, in alarm_handler
1 // 0
ZeroDivisionError: integer division by zero
I would like in gevent to be able to handle such errors (have my handle_error() function called) as I'd like those to be re-raised in main greenlet, as it happens with builtin blocking functions:
pypycore ~/work/gevent $ cat time_signal.py
import signal
import time
def alarm_handler(*args):
1 // 0
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(1)
try:
time.sleep(2)
except Exception, ex:
print 'caught error: %s' % ex
pypycore ~/work/gevent $ pypy time_signal.py
caught error: integer division by zero
However, I cannot currently find a way to make it work.
In CPython version of gevent I do
PyErr_CheckSignals();
if (PyErr_Occurred()) gevent_handle_error(loop, Py_None);
Would be nice to have special support for this in CFFI / PyPy, in a form of a special callback that will be called with exception converted to value for those exception that were set before entering the callback.