S
sven.suursoho
Does messing with signal handlers and longjmp affect Python
interpreter?
I'm trying to find solution for problem, described in
http://groups.google.com/group/comp...read/thread/98cbae94ca4beefb/9d4d96fd0dd9fbc3
and came up with test application. It works well but i'm not sure it is
ok for long-running python interpreter?
#include <Python.h>
#include <signal.h>
#include <setjmp.h>
const char *py_source =
"def fn():\n"
" yield 1\n";
jmp_buf env;
enum _ { detect, no, yes } has_buggy_gen_iternext = detect;
static sighandler_t old_abrt = SIG_DFL;
void
signal_handler (int sig)
{
if (sig == SIGABRT)
longjmp(env, 1);
}
int
main (int argc, char *argv[])
{
Py_Initialize();
PyObject *globals = PyDict_New();
// insert function code into interpreter
PyObject *code = PyRun_String(py_source, Py_file_input, globals,
NULL);
Py_DECREF(code);
// compile call to the function
code = Py_CompileString("fn()", "<string>", Py_eval_input);
// do call
PyObject *gen = PyEval_EvalCode((PyCodeObject *)code, globals, NULL);
gen = PyObject_GetIter((PyObject *)gen);
// detect if we are using bad Python interpreter
if (has_buggy_gen_iternext == detect) {
if (setjmp(env) == 0)
// first time, set signal handler
old_abrt = signal(SIGABRT, signal_handler);
else {
// jumped here from signal handler -- bad Python
has_buggy_gen_iternext = yes;
signal(SIGABRT, old_abrt);
}
}
if (has_buggy_gen_iternext == yes)
printf("generators are disabled\n");
else {
// iterate result
PyObject *item;
while ((item = PyIter_Next(gen))) {
printf("> %ld\n", PyInt_AsLong(item));
Py_DECREF(item);
}
if (has_buggy_gen_iternext == detect) {
// ok, restore old signal handler
has_buggy_gen_iternext = no;
signal(SIGABRT, old_abrt);
}
}
Py_DECREF(gen);
Py_DECREF(code);
Py_DECREF(globals);
Py_Finalize();
return 0;
}
interpreter?
I'm trying to find solution for problem, described in
http://groups.google.com/group/comp...read/thread/98cbae94ca4beefb/9d4d96fd0dd9fbc3
and came up with test application. It works well but i'm not sure it is
ok for long-running python interpreter?
#include <Python.h>
#include <signal.h>
#include <setjmp.h>
const char *py_source =
"def fn():\n"
" yield 1\n";
jmp_buf env;
enum _ { detect, no, yes } has_buggy_gen_iternext = detect;
static sighandler_t old_abrt = SIG_DFL;
void
signal_handler (int sig)
{
if (sig == SIGABRT)
longjmp(env, 1);
}
int
main (int argc, char *argv[])
{
Py_Initialize();
PyObject *globals = PyDict_New();
// insert function code into interpreter
PyObject *code = PyRun_String(py_source, Py_file_input, globals,
NULL);
Py_DECREF(code);
// compile call to the function
code = Py_CompileString("fn()", "<string>", Py_eval_input);
// do call
PyObject *gen = PyEval_EvalCode((PyCodeObject *)code, globals, NULL);
gen = PyObject_GetIter((PyObject *)gen);
// detect if we are using bad Python interpreter
if (has_buggy_gen_iternext == detect) {
if (setjmp(env) == 0)
// first time, set signal handler
old_abrt = signal(SIGABRT, signal_handler);
else {
// jumped here from signal handler -- bad Python
has_buggy_gen_iternext = yes;
signal(SIGABRT, old_abrt);
}
}
if (has_buggy_gen_iternext == yes)
printf("generators are disabled\n");
else {
// iterate result
PyObject *item;
while ((item = PyIter_Next(gen))) {
printf("> %ld\n", PyInt_AsLong(item));
Py_DECREF(item);
}
if (has_buggy_gen_iternext == detect) {
// ok, restore old signal handler
has_buggy_gen_iternext = no;
signal(SIGABRT, old_abrt);
}
}
Py_DECREF(gen);
Py_DECREF(code);
Py_DECREF(globals);
Py_Finalize();
return 0;
}