从C调用Py_Finalize()

2024-09-29 01:28:07 发布

您现在位置:Python中文网/ 问答频道 /正文

这是Call Python from C++的后续操作

在程序启动时,我调用以下函数初始化解释器:

void initPython(){
    PyEval_InitThreads();
    Py_Initialize();
    PyEval_ReleaseLock();
}

每个线程创建自己的数据结构,并通过以下方式获取锁:

^{pr2}$

一旦您理解了GIL,就可以直截了当了,但问题是在调用Py_Finalize()时,我得到了一个segfault。在

void exitPython(){
    PyEval_AcquireLock();
    Py_Finalize();
}

这个引用对Py_Finalize()相当怀疑(或者我只是读错了它),我不确定如果有一些活动线程,PyEval_AcquireLock()是否可以获取锁,如果调用Py_Finalize()时有活动线程会发生什么。在

不管怎样,我得到一个segfault,即使我确定所有线程都完成了它们的工作,但前提是至少创建了一个线程。E、 从exitPython()调用initPython()不会产生错误。在

我可以忽略这个问题,希望操作系统知道它的作用,但我更希望我能弄清楚到底发生了什么。。在


Tags: 函数frompy程序call线程解释器segfault
3条回答

你试过把你的帖子里所有的“工作”都注释掉了吗?换成一个繁忙的循环或者睡觉之类的。这将有助于查明这是您的初始化/关闭代码,还是您在这两者之间实际对Python所做的操作。也许你没有正确地设置线程-在C API中有很多线程特定的函数,我不确定你需要哪些函数来确保正确的操作。在

是的,但我觉得我的部分有点可疑。在

我必须在初始化解释器时保存PyThreadState,并在完成解释器时将其交换回原处(不知道为什么我需要一个特定的ThreadState来调用Finalize-难道每个状态都能正常工作吗?)在

不管怎样,如果其他人遇到同样的问题:

PyThreadState *mainstate;

void initPython(){
    PyEval_InitThreads();
    Py_Initialize();
    mainstate = PyThreadState_Swap(NULL);
    PyEval_ReleaseLock();
}

void exitPython(){
    PyEval_AcquireLock();
    PyThreadState_Swap(mainstate);
    Py_Finalize();
}

唯一的问题是,我可以像其他线程一样获得锁,即使仍然有线程在工作。 API没有提到在其他线程仍在工作时调用Finalize()时会发生什么。听起来是种族状况的完美例子。。在

在通过嵌入式解释器从不同线程运行包含pyxhook的脚本时,我也遇到了类似的问题。在

如果一次只运行一个脚本,就没有问题。钩子被正确释放,但是如果两个或多个脚本并行运行,钩子不会停止。虽然我的脚本正确返回,来自pyxhookcancel()也正确返回,但我认为仍有一些与xlib相关的线程正在运行。这个pyxhook问题的解决方法是保持一个全局标志来监视pyxhook是否已经在运行,而不是从每个线程重新初始化{}。在

现在关于Py_Finalize(),如果pyxhook在每个线程中被重新初始化:

如果在调用Py_Finalize()之前不调用PyEval_AcquireLock()PyThreadState_Swap(),它将在Linux中终止,但不会在Win32中终止。在Win32中,如果我不执行PyEval_AcquireLock()PyThreadState_Swap(),就会出现问题。在

对于我来说,暂时的解决方案是在两个不同的操作系统中以不同的方式终止。在

相关问题 更多 >