2010-03-19 53 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