为什么PyGILState_Release抛出致命的 Python 错误
Why is PyGILState_Release throwing Fatal Python Errors
>已回答
好的,我解决了这个问题。这一切都取决于您如何初始化线程状态。你根本不需要使用ReleaseLock。只需将 InitThreads 调用添加到模块定义中:
BOOST_PYTHON_MODULE(ModuleName)
{
PyEval_InitThreads();
...
}
好的,我已经尝试诊断这个问题几个小时,并倾注了网络上的每一个示例。现在累了,所以我可能会错过一些明显的东西,但这是正在发生的事情:
我正在用提升蟒蛇包装一个库。我正在运行一个 python 脚本,它导入库,构造一些对象,然后从 c++ 接收回调,回调到 python。在调用任何 python 函数之前,我尝试获取全局解释器锁。下面是一些示例代码:
class ScopedGILRelease
{
public:
inline ScopedGILRelease()
{
d_gstate = PyGILState_Ensure();
}
inline ~ScopedGILRelease()
{
PyGILState_Release(d_gstate);
}
private:
PyGILState_STATE d_gstate;
};
class PyTarget : public DingoClient::ClientRequest::Target, public wrapper<DingoClient::ClientRequest::Target>
{
public:
PyTarget(PyObject* self_) : self(self_) {}
~PyTarget() {
ScopedGILRelease gil_lock;
}
PyObject* self;
void onData(const boost::shared_ptr<Datum>::P & data, const void * closure)
{
ScopedGILRelease gil_lock;
// invoke call_method to python
}
...
}
目标对象上的 onData 方法由库作为回调调用。在python中,我们继承了PyTarget并实现了另一种方法。然后我们使用call_method<>调用该方法。gil_lock获取锁,并通过 RIAA 保证获取的线程状态始终是一个释放,并且实际上在超出范围时始终释放。
但是,当我在尝试在此函数上获取大量回调的脚本中运行它时,它总是出现段错误。脚本如下所示:
# Initialize the library and setup callbacks
...
# Wait until user breaks
while 1:
pass
此外,python脚本总是构造一个运行的对象:
PyEval_InitThreads();
PyEval_ReleaseLock();
在收到任何回调之前。
我已经将代码减少到我什至没有在 onData 中调用 python 的地方,我只是在获取锁。在发布时,它总是崩溃并显示:
Fatal Python error: ceval: tstate mix-up
Fatal Python error: This thread state must be current when releasing
或
Fatal Python error: ceval: orphan tstate
Fatal Python error: This thread state must be current when releasing
这似乎是随机的。我在这里疯了吗,因为我觉得我正确使用了 GIL 锁,但它似乎根本不起作用。
其他注意事项:只有一个线程调用该 Target 对象的 onData 方法。
当我使用 time.sleep(( 在调用 python 模块的 while 循环中睡觉时,它似乎允许脚本运行更长时间,但最终脚本会因类似问题而出现段错误。它持续的时间量与 time.sleep 的量成正比(即 time.sleep(10( 比 time.sleep(0.01( 运行的时间长(。这让我有些思考脚本如何在未经我许可的情况下重新获取 GIL。
在我的代码中,PyGILState_Release和PyGILState_Ensure没有其他地方被调用,其他地方不应该调用 python。
更新
我读过另一个问题,它建议在模块中导入线程作为运行的替代方案
PyEval_InitThreads();
PyEval_ReleaseLock();
但是,当我在我的模块之前导入线程并从我的 boost python 包装器中删除上述两行时,它似乎不起作用。
好的,我解决了这个问题。这一切都取决于您如何初始化线程状态。你根本不需要使用ReleaseLock。只需将 InitThreads 调用添加到模块定义中:
BOOST_PYTHON_MODULE(ModuleName)
{
PyEval_InitThreads();
...
}
- 无法使用 SWIG 在 Python 中实例化C++类(获取属性错误)
- 为什么PyImport_ImportModule python 3.7.2 中出现段错误?
- OpenCV - Python 断言错误:SAD 算法 - 立体相机视差图计算
- 如何在 Python C++ 混合库中调试非确定性分段错误?
- 为 Python 构建共享库C++时出现分段错误
- NS3 - python.h 文件无法定位编译错误
- Python os.system() 返回错误值
- 致命的 Python 错误:无法获取随机数来初始化 Python
- 使用 Pybind11 将函数集成到 Python C++错误,同时使用 PYBIND11_MODULE
- Python 错误:在 SWIG 生成的C++模板化代码模块中没有定义构造函数
- 致命的Python错误:Py_Initialize:无法加载文件系统编解码器&ModuleNotFoundError
- Python 错误:PyThreadState_Get:编译扩展后没有当前线程
- “致命的 Python 错误:PyThreadState_Get:没有当前线程”是什么意思
- 使用 IPython 嵌入 Python 错误: [错误 193] %1 不是有效的 Win32 应用程序
- 致命 Python 错误:无法使用C++绑定创建自动 TLSkey 映射
- 如何使用Boost获取SyntaxError、NameError等的Python错误信息
- 为什么PyGILState_Release抛出致命的 Python 错误
- 由python导入的python错误
- helloworld示例中的Boost.python错误
- 不支持嵌入 python 错误按文件名导入