Iterating generator from C

sven.suursoho at gmail.com sven.suursoho at gmail.com
Sat Jun 17 05:07:25 EDT 2006


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.lang.python/browse_thread/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;
}




More information about the Python-list mailing list