Segfault in multithreaded python extension in C

I have a very stripped-down example that creates a segfault that I cannot get rid of. The Python script calls the C function in the extension, which creates a new thread using pthreads. I am using PyGILState_Ensure and PyGILState_Release around my python call (PyRun_SimpleString) in a new thread, but maybe I am not using them correctly or skipped some other step. Commenting out python calls in the receive_audio function, segfault no longer occurs. Any ideas?

Conclusion:

python lib / test.py
(Main topic) initmodule complete
(Main thread) Call run_thread ()
(Main topic) Creating a thread
(New Topic) In receive_audio () - receiving GIL
(New Topic) python print!
(New Topic) In receive_audio () - GIL released
(New Topic) Looping 0
Segmentation error

C The code is as follows:

PyMODINIT_FUNC streamaudio() { PyObject *m = Py_InitModule("streamaudio", methods); PyEval_InitThreads(); mainThreadState = PyThreadState_Get(); PyEval_ReleaseLock(); printf("(Main Thread) initmodule complete\n"); } static PyObject* run_thread(PyObject* self, PyObject* args) { int ok, stream_id; PyGILState_STATE gstate; gstate = PyGILState_Ensure(); ok = PyArg_ParseTuple(args, "i", &stream_id); PyRun_SimpleString("print '(Main Thread) Creating thread'\n"); int rc = pthread_create(&thread, NULL, receive_audio, (void*)stream_id); PyRun_SimpleString("print '(Main Thread) Thread created'\n"); PyGILState_Release(gstate); return Py_BuildValue("i", rc); } void* receive_audio(void *x) { printf("(New Thread) In receive_audio() - acquiring GIL\n"); PyGILState_STATE gstate; gstate = PyGILState_Ensure(); PyRun_SimpleString("print '(New Thread) python print!'\n"); PyGILState_Release(gstate); printf("(New Thread) In receive_audio() - released GIL\n"); int i; for (i = 0; i < 100; i++) { printf("(New Thread) Looping %d\n", i); sleep(1); } } 
+4
source share
1 answer

I'm not sure if this will be relevant to your question, but one thing that looks suspicious is calling PyEval_ReleaseLock () in your module initialization function. I doubt that Python expects your module initializer to get the GIL out from under it, and a quick look at some sample code here doesn't show anything in this direction. Could you try to remove this call to PyEval_ReleaseLock () and tell us what is going on?

By the way, I agree that calls to PyGILState _ * () in run_thread () should not have an effect; you should just delete them.

+3
source

Source: https://habr.com/ru/post/1304587/


All Articles