是否可以在阻塞并可能回调到 Python 的 C 函数之前释放 GIL?
我正在包装一个 C 函数,该函数执行阻塞操作(选择),然后处理传入消息。我的理解是,当一个 C 函数将要阻塞时,在允许其他线程运行的同时调用它的正确方法是:
Py_BEGIN_ALLOW_THREADS
blocking_function();
Py_END_ALLOW_THREADS
但是,这个函数恰好将回调指针作为参数。在处理由 C 函数预处理的传入消息时调用此回调。我已成功将此回调包装在调用 PyEval_CallObject()
的函数中,允许我向其传递 Python 回调。
现在我正在添加线程支持,我想知道是否可以同时:
- 在调用此阻塞操作之前释放 GIL。
- 让这个阻塞操作安全地回调到 python 解释器中。
这会引起问题吗?如果是这样,有办法解决吗?
谢谢。
I am wrapping a C function which performs a blocking operation (select) and then handles incoming messages. My understanding is that when a C function is going to block, the correct way to call it while allowing other threads to run is:
Py_BEGIN_ALLOW_THREADS
blocking_function();
Py_END_ALLOW_THREADS
However, it happens that this function takes as a parameter a callback pointer. This callback is called on handling the incoming message that is pre-processed by the C function. I have successfully wrapped this callback in a function which calls PyEval_CallObject()
, allowing me to pass it a Python callback.
Now that I'm adding threading support, I'm wondering if it's possible to simultaneously:
- Release the GIL before calling this blocking operation.
- Have this blocking operation safely call back into the python interpreter.
Is this going to cause problems? If so, is there a way around it?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我几个月前使用过这些API函数,我的记忆有点模糊,但我相信这段代码会解决你的问题。我假设版本 2.x(3.x 可能不同):(
以上内容取自:Python C/API 文档)
这基本上与 Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS 相反
宏。在这些函数中,您释放 GIL,但在 PyGILState 函数中您获取 GIL。
I used these API functions several months ago, and my recollection is a bit hazy, but I believe this code will solve your problem. I am assuming version 2.x (3.x may be different):
(The above was taken from: Python C/API docs)
This is basically the inverse of the Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS
macros. Within those, you release the GIL, but within the PyGILState functions you acquire the GIL.
如果我使用全局变量来存储
PyEval_SaveThread
的结果,并在回调中使用它来调用PyEval_RestoreThread
,则可以工作。我只需要弄清楚如何通过回调的上下文指针更干净地将其传递给代码中的回调。Works if I use a global to store the result of
PyEval_SaveThread
, and use this in the callback to callPyEval_RestoreThread
. I just need to figure out how to more cleanly pass this to the callback in my code through the callback's context pointer.