Does messing with signal handlers and longjmp affect Python
interpreter?
I'm trying to find solution for problem, described in
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_i ternext = 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_CompileStrin g("fn()", "<string>", Py_eval_input);
// do call
PyObject *gen = PyEval_EvalCode ((PyCodeObject *)code, globals, NULL);
gen = PyObject_GetIte r((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_i ternext = yes;
signal(SIGABRT, old_abrt);
}
}
if (has_buggy_gen_ iternext == yes)
printf("generat ors are disabled\n");
else {
// iterate result
PyObject *item;
while ((item = PyIter_Next(gen ))) {
printf("> %ld\n", PyInt_AsLong(it em));
Py_DECREF(item) ;
}
if (has_buggy_gen_ iternext == detect) {
// ok, restore old signal handler
has_buggy_gen_i ternext = no;
signal(SIGABRT, old_abrt);
}
}
Py_DECREF(gen);
Py_DECREF(code) ;
Py_DECREF(globa ls);
Py_Finalize();
return 0;
}
interpreter?
I'm trying to find solution for problem, described in
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_i ternext = 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_CompileStrin g("fn()", "<string>", Py_eval_input);
// do call
PyObject *gen = PyEval_EvalCode ((PyCodeObject *)code, globals, NULL);
gen = PyObject_GetIte r((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_i ternext = yes;
signal(SIGABRT, old_abrt);
}
}
if (has_buggy_gen_ iternext == yes)
printf("generat ors are disabled\n");
else {
// iterate result
PyObject *item;
while ((item = PyIter_Next(gen ))) {
printf("> %ld\n", PyInt_AsLong(it em));
Py_DECREF(item) ;
}
if (has_buggy_gen_ iternext == detect) {
// ok, restore old signal handler
has_buggy_gen_i ternext = no;
signal(SIGABRT, old_abrt);
}
}
Py_DECREF(gen);
Py_DECREF(code) ;
Py_DECREF(globa ls);
Py_Finalize();
return 0;
}