
I have a problem with threading using the Python/C API. I have an extension that implements a timer, and the C++ timer callback function calls a Python function. The relevant code looks like this: staticPyObject *timer_setmodname( PyObject *pSelf, PyObject *pArgs ) {
char *b;
PyArg_ParseTuple( pArgs, "s", &b );
mod = PyImport_ImportModule(b);
if( mod == NULL )
{
printf("Could not import %s\n",b);
return Py_None;
}
modsetFlag = TRUE;
return Py_None;
}
staticPyObject *timer_setprocname( PyObject *pSelf, PyObject *pArgs ) { char *b; if( !modsetFlag )return Py_None; PyArg_ParseTuple( pArgs, "s", &b ); attr = PyObject_GetAttrString(mod,b); if( attr == NULL ) { printf("Could not import %s\n",b); return Py_None; } attrsetFlag = TRUE; return Py_None; } staticvoid CALLBACK PeriodicTimer(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) { PyGILState_STATE pgs;
pgs = PyGILState_Ensure();
if(attrsetFlag)
{
pres = PyObject_CallFunction(attr,NULL);
if( pres == NULL )printf("CallFunction failed!\n");
}
PyGILState_Release( pgs );
}
The Python code that sets this up looks like this:
fetimer.setmodname("Timeslice3") fetimer.setprocname("Timetester") print "\n Program Waiting for Time Slice" while True: time.sleep(0.010)
and the module Timeslice3.py looks like this:
#Timeslice3.py def Timetester(): pass
When I run this stuff, it works fine for hundreds, often even thousands, of timer ticks (I’ve been testing with about thirty ticks per second, but it doesn’t matter – it still crashes at ten or fewer ticks per second). Sometimes it runs for only a few seconds, sometimes for ten minutes or so. But it always eventually crashes Python. Usually it gives no error message. Sometimes, though, it does give an error message, but not always the same one. I’ve noted three that it has given in my testing so far:
Fatal Python Error: This thread state must be current when releasing
Fatal Python Error: PyThreadState_DeleteCurrent: no current tstate
Fatal Python Error: PyEval_SaveThread: NULL tstate
Can anybody help me make this code stable, so that it works all the time? I’m using Python 2.6.5 under Windows Vista, but it crashes under Windows XP as well.

Paul Grunau <paul@anilabsys.com> writes:
Python functions are expected to return a new reference, so you should Py_INCREF None (or any other returned Python object) before returning it. This applies to both setmodname and setprocname.
pres = PyObject_CallFunction(attr,NULL); if( pres == NULL )printf("CallFunction failed!\n");
PyObject_CallFunction returns a new reference, so you should Py_DECREF pres in the case when it is not NULL and you no longer need it.
Also, posting a complete code sample in C, that we can build and test ourselves, might help debugging the specific problem you are having, which may or may not be related to the above reference-counting errors.

Paul Grunau <paul@anilabsys.com> writes:
Python functions are expected to return a new reference, so you should Py_INCREF None (or any other returned Python object) before returning it. This applies to both setmodname and setprocname.
pres = PyObject_CallFunction(attr,NULL); if( pres == NULL )printf("CallFunction failed!\n");
PyObject_CallFunction returns a new reference, so you should Py_DECREF pres in the case when it is not NULL and you no longer need it.
Also, posting a complete code sample in C, that we can build and test ourselves, might help debugging the specific problem you are having, which may or may not be related to the above reference-counting errors.
participants (2)
-
Hrvoje Niksic
-
Paul Grunau