【发布时间】:2012-01-17 02:10:11
【问题描述】:
已回答
好的,我解决了这个问题。一切都在于您如何初始化线程状态。您根本不需要使用 ReleaseLock。只需将 InitThreads 调用添加到您的模块定义中:
BOOST_PYTHON_MODULE(ModuleName)
{
PyEval_InitThreads();
...
}
好的,我已经尝试诊断这个问题好几个小时了,并仔细研究了网络上的每个示例。现在累了,所以我可能会遗漏一些明显的东西,但这是正在发生的事情:
我在 boost python 中包装了一个库。我正在运行一个 python 脚本,它导入 lib,构造一些对象,然后从 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
}
...
}
Target 对象上的 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 包装器中删除上述两行时,它似乎不起作用。
【问题讨论】:
-
很高兴你知道了。那个也让我回来了。仅供参考,您可以发布自己问题的答案。这会让喜欢你的解决方案的人投票。
-
谢谢,相对较新的堆栈溢出,仍然掌握它的窍门。将发布。
标签: c++ python boost boost-python