[Pyrex] Callbacks from other threads (crash in PyGILState_Release)

Geoff Schmidt gschmidt at gschmidt.org
Tue Jun 20 23:08:55 UTC 2006


Jani,

>> I tried adding the extra PyEval_Save/RestoreThread that you show in
>> your example, but I still get the same segfault. The revised code is
>> below. Could you take a look and tell me if I understood your advise?
>>
> I think you need to call PyEval_InitThreads() before pthread_create.

Thank you so much. This solved the problem.

For anyone finding this thread with Google, here is the resulting  
test program, showing the correct way to asynchronously call a Python  
callback from another, different C thread in Pyrex:

--- foo.pyx ---
cdef extern from "stdio.h":
     int printf(char *str, ...)

cdef extern from "Python.h":
     ctypedef int PyGILState_STATE
     PyGILState_STATE PyGILState_Ensure()
     void PyGILState_Release(PyGILState_STATE gstate)
     void PyEval_InitThreads()

cdef extern from "pthread.h":
     ctypedef void *pthread_t # it'll do
     int pthread_create(pthread_t *thread, void *attr,
                        void *(*start_routine)(void *), void *arg)

cdef extern void *func(void *x):
     printf("Entering func(%p)\n", x)

     cdef PyGILState_STATE st
     printf("PyGILState_Ensure\n")
     st = PyGILState_Ensure()
     printf("PyGILState_Release\n")
     PyGILState_Release(st)
     printf("Leaving func\n")

def callFuncDirectly():
     func(NULL)

def callFuncInThread():
     PyEval_InitThreads()

     cdef pthread_t thr
     pthread_create(&thr, NULL, func, NULL);

--- setup.py ---

from distutils.core import setup
from distutils.extension import Extension
from Pyrex.Distutils import build_ext

setup(
     name = 'foo',
     ext_modules = [Extension("foo", ["foo.pyx"])],
     cmdclass = {'build_ext': build_ext},
     )

--- end ---

Example usage:

$ python setup.py build_ext --inplace
$ python
 >>> import foo
 >>> foo.callFuncInThread

Geoff Schmidt
gschmidt at gschmidt.org



More information about the Pyrex mailing list