C中多线程python扩展中的段错误

Posted

技术标签:

【中文标题】C中多线程python扩展中的段错误【英文标题】:Segfault in multithreaded python extension in C 【发布时间】:2010-03-19 16:33:53 【问题描述】:

我有一个非常精简的示例,它创建了一个我似乎无法摆脱的段错误。 Python 脚本调用扩展中的 C 函数,该函数使用 pthreads 创建一个新线程。我在新线程中的 python 调用 (PyRun_SimpleString) 周围使用 PyGILState_Ensure 和 PyGILState_Release,但也许我没有正确使用它们或错过了其他步骤。注释掉 receive_audio 函数中的 python 调用,段错误不再发生。有什么想法吗?

输出:

python 库/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 调用似乎无关紧要。我认为这是可以预料的,因为它是由主线程运行的。 【参考方案1】:

我不确定这与您的问题有关,但看起来可疑的一件事是您的模块初始化程序函数中的 PyEval_ReleaseLock() 调用。我怀疑 Python 是否希望您的模块初始化程序从它下面释放 GIL,快速查看一些示例代码 here 并没有显示任何类似的内容。您能否尝试删除 PyEval_ReleaseLock() 调用并告诉我们会发生什么?

顺便说一句,我同意 run_thread() 中的 PyGILState_*() 调用应该没有效果;你应该可以删除它们。

【讨论】:

不错!做到了。我从这里跟踪代码:linuxjournal.com/article/3641?page=0,2 他的例子是在 C 中嵌入 python,而我正在做相反的事情,所以这个调用是灾难性的。谢谢!

以上是关于C中多线程python扩展中的段错误的主要内容,如果未能解决你的问题,请参考以下文章

生产者消费者程序中的段错误

当无法在多个线程上连接到服务器时,pymssql 的段错误

atoi(str) 中的段错误

c++ 类向量中的段错误

std::atomic 负载中的段错误?

使用 std::string.c_str() 作为另一个方法的参数时的段错误