SEGV traceback?

Lee Merrill wrote:

Thanks, my problem in either approach appears to be that _PyThreadState_Current is NULL, which PyThreadState_Get() even considers a fatal error! But I'm using this variable in the signal handler, so I don't see how it's getting reset due to the SEGV...

It depends on where the SEGV happens. The wxPython wrappers will release Python's Global Interpreter Lock (which clears the current thread state) whenever a call is made to wx C++ code, and then reacquire it when returning to Python. It also acquires and releases the GIL when making a call to Python code or when manipulating Python objects.

I've got some helper functions that I call to restore the GIL and the interpreter state, but if you are putting this function in wxWidgets then I'm not sure you'll be able to call it directly because it actually accesses the function via a function pointer imported from the wx._core_ module. So instead I would try wrapping your block of calls to the Py functions with these:

  PyGILState_STATE state = PyGILState_Ensure();
  ...
  PyGILState_Release(state);

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Thanks, Robin, here is my fixed-up version, that prints the current thread first on a SEGV. Would it be possible to put code like this in as an option? Such errors can be very difficult to track down without knowing what line of code caused it …

Lee

#include <signal.h>

#include <python2.4/Python.h>

#include <python2.4/frameobject.h>

void wxPrintErrThreadTrace(PyThreadState *st, const char *threadLabel)

{

PyTracebackObject *tb;

PyFrameObject *frm;

fprintf(stderr, "%s\n", threadLabel);

st->curexc_traceback = NULL;

for (frm = st->frame; frm; frm = frm->f_back)

if (PyTraceBack_Here(frm) < 0) { fprintf(stderr, " PyTraceBack_Here failed\n"); return; }

tb = (PyTracebackObject *) st->curexc_traceback;

if (tb == NULL) { fprintf(stderr, " traceback is NULL in wxFatalSignalHandler\n"); return; }

while (tb) {

fprintf(stderr, " %s line %u: %s\n", PyString_AsString(tb->tb_frame->f_code->co_filename),

tb->tb_lineno, PyString_AsString(tb->tb_frame->f_code->co_name));

tb = tb->tb_next;

}

}

extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER)

{

if ( wxTheApp ) {

PyInterpreterState *firstInterp = PyInterpreterState_Head(), *interp;

PyThreadState *curThread, *st;

PyGILState_STATE state = PyGILState_Ensure();

curThread = PyThreadState_GET();

if (curThread)

wxPrintErrThreadTrace(curThread, "Current thread:");

for (interp = firstInterp; interp; interp = interp->next) {

if (firstInterp->next)

fprintf(stderr, "Interpreter:\n");

for (st = interp->tstate_head; st; st = st->next) {

if (st == curThread)

continue;

wxPrintErrThreadTrace(st, "Thread:");

}

}

PyGILState_Release(state);

}

abort();

}

···

On Wed, 2006-05-24 at 18:17 -0700, Robin Dunn wrote:

It depends on where the SEGV happens. The wxPython wrappers will
release Python's Global Interpreter Lock (which clears the current
thread state) ...

“There is nothing remarkable about it. All one has to do is press the right keys at the right time and the computer programs itself.” (ala J.S. Bach)

Unless otherwise stated, any views presented in this e-mail are solely those of the author and do not necessarily represent those of the company.