Hello, I'm chasing a GPF in the interpreter when running my extension module. It's not very elaborated, but uses a system (threaded) callback, and therefore the GIL. Help would be mucho appreciated. Here's the rough picture:
win32_spam.c ------------ /* code here is unit-tested OK */ typedef struct Bag { char data[128]; site_t size; } Bag; typedef void (*PCallback)(const Bag * const bag); Bag bag; PCallback user_callback = NULL; /* called by windoz */ static void CALLBACK win32_call_me(void) { memcpy(bag.data, somestuff, 100); bag.size = 100; SPAWN_THREAD(user_callback, & bag);//pseudo-code } spam_module.c ------------- /* most of the code here is pasted from doc */ static PyObject * my_callback = NULL; static PyObject * setCallback(PyObject *dummy, PyObject *args) { PyObject *result = NULL; PyObject *temp; if (PyArg_ParseTuple(args, "O:miSetCallback", &temp)) { if ((temp != Py_None) && (!PyCallable_Check(temp))) { PyErr_SetString(PyExc_TypeError, "parameter must be callable"); return NULL; } Py_XINCREF(temp); Py_XDECREF(my_callback); my_callback = temp; Py_INCREF(Py_None); result = Py_None; /* set the actual callback in win32_spam.c */ user_callback = & external_callback; } return result; } static void external_callback(const Bag * const bag) { if (my_callback && (my_callback != Py_None)) { PyObject * arglist = NULL; PyObject * result = NULL; arglist = Py_BuildValue("(s#)", bag->data, bag->size); /* do it */ PyGILState_STATE gil = PyGILState_Ensure(); result = PyEval_CallObject(my_callback, arglist); PyGILState_Release(gil); Py_DECREF(arglist); Py_DECREF(result); } } blowup_spam1.py ------------- # This throws a GPF on callback. # Why, since the GIL is acquired by the callback? import spam.py def callback(stuff): print stuff if __name__ == '__main__': spam.setCallback(callback) raw_input() blowup_spam2.py ------------- # This throws a GPF as well # Why, since we're using a threadsafe queue? import spam import Queue q = Queue.Queue() def callback(stuff): q.put(stuff) if __name__ == '__main__': spam.setCallback(callback) while True: print q.get() nice_spam.py ------------- # This works # Why, since the rest did not? import spam import Queue import threading q = Queue.Queue() def callback(stuff): q.put(stuff) def job(): while True: print q.get() if __name__ == '__main__': spam.setCallback(callback) t = threading.Thread(job) t.start() raw_input() Please point me to what I'm doing wrong... TIA, Francois PS: I've already submitted my issue under "(Win32 API) callback to Python, threading hiccups", but I guess it was poorly formulated. -- http://mail.python.org/mailman/listinfo/python-list