我有一個非常精細的例子,它創建了一個我似乎無法擺脫的段錯誤。 Python腳本在擴展中調用C函數,該函數使用pthread創建新線程。我在新線程的python調用(PyRun_SimpleString)周圍使用了PyGILState_Ensure和PyGILState_Release,但也許我沒有正確使用它們或錯過了其他一些步驟。在receive_audio函數中註釋掉python調用,segfault不再發生。有任何想法嗎?Segfault在C多線程python擴展中
輸出:
蟒蛇的lib/test.py
(主線程)initmodule完整
(主線程)調用run_thread()
(主線程)創建線程
(新主題)在receive_audio () - 獲取GIL
(新主題)python print!
(新主題)在receive_audio() - 釋放GIL
(新主題)循環0
分段故障
C代碼如下:
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);
}
}
請注意 - 圍繞pthread_create函數調用PyGILState_Ensure()和PyGILState_Release似乎是無關緊要的。我認爲這是可以預料的,因爲它是由主線程運行的。 – cursemyziti 2010-03-19 16:37:27