Hi,
There are several ways to prevent that, but none is very clean. I'd
recommend moving slightly more code to C, where it will run
uninterrupted. This assumes that you're using the API mode, not the
ABI mode. Here is a minimal example:
in file foo_build.py:
ffi=FFI()
ffi.cdef("void my_do_stuff(int arg, void **result);")
ffi.set_source("_foo_cffi", """
#include <somelib.h>
void my_do_stuff(int arg, void **result)
{
*result = somelib_doing_stuff(arg);
}
""")
ffi.compile()
Then you call lib.my_do_stuff() instead of directly
somelib_doing_stuff() from Python:
from _foo_cffi import ffi, lib
p = ffi.new("void **") # initialized to NULL
try:
lib.my_do_stuff(arg, p)
# do things with p[0]
finally:
# free p[0] if it is not NULL
The difference with your version is that you can read 'p[0]' in all
cases in the "finally" block, and you get either NULL if the C
function did not run yet, or a non-NULL value returned by
somelib_doing_stuff() if it ran. If the C function ran, then the
result is in 'p[0]' and should never be lost.
Maybe cffi could grow support to do something like that more
transparently (and a solution should also work in the ABI mode). We
could automate the "call a function and store the result here", even
though it looks like a very ad-hoc solution:
p = ffi.new("void **")
ffi.call_and_store_result(p, lib.somelib_doing_stuff, arg)
A different approach is to combine the function call with ffi.gc() on
the result. Something to do the equivalent of:
p = ffi.gc(lib.somelib_doing_stuff(arg), destructor)
but in a single call that is not interruptible, e.g.:
p = ffi.gc_call(destructor, lib.somelib_doing_stuff, arg)
or maybe with hints on ``lib.somelib_doing_stuff`` that say "you
should call ffi.gc(result, destructor)" (maybe with a #pragma in the
cdef?).
Finally, yet another solution would be to add a way to temporarily
disable or enable signal processing. In PyPy such a solution already
exists, though it's not really public: you can say
"__pypy__.thread._signals_exit()" to stop processing signals, and
later "__pypy__.thread._signals_enter()" to re-enable them.
A bientôt,
Armin.