2010-03-19 57 views
4

我有一個非常精細的例子,它創建了一個我似乎無法擺脫的段錯誤。 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); 
    } 
} 
+0

請注意 - 圍繞pthread_create函數調用PyGILState_Ensure()和PyGILState_Release似乎是無關緊要的。我認爲這是可以預料的,因爲它是由主線程運行的。 – cursemyziti 2010-03-19 16:37:27

回答

3

我還不能肯定,這將是與你的問題相關,但看起來有點可疑的是模塊初始化函數中的PyEval_ReleaseLock()調用。我懷疑Python是否期望你的模塊初始化器從它下面釋放GIL,並且快速看一下代碼here的一些示例沒有顯示這些行的任何內容。你能否嘗試刪除PyEval_ReleaseLock()調用並告訴我們會發生什麼?我同意,run_thread()內的PyGILState _ *()調用應該沒有任何影響;你應該能夠刪除它們。

+2

不錯!那樣做了。我是從這裏的代碼: http://www.linuxjournal.com/article/3641?page=0,2 他的例子是嵌入python的C,而我做的相反,所以這個電話是慘重。 謝謝! – cursemyziti 2010-03-19 18:39:03