如何检查线程当前是否持有GIL?

17

我试图找到一个函数来告诉我当前线程是否持有全局解释器锁。

Python/C-API文档似乎没有包含这样的函数。

我的解决方案是在使用 PyEval_SaveThread 释放锁之前,使用 PyGILState_Ensure()获取锁,以避免尝试释放未由当前线程获取的锁。

(顺便问一下,“issues a fatal error”是什么意思?)

这个问题的背景是,我有一个嵌入了Python的多线程应用程序。如果一个线程关闭而没有释放锁(这可能是由于崩溃导致的),其他线程将无法再运行。因此,在清理/关闭线程时,我想检查该线程是否持有锁,并在这种情况下释放它。

感谢您提前的回答!


6
如果一个线程在持有全局解释器锁(GIL)时崩溃,我无法想象运行另一个Python线程会是安全的。 - Dietrich Epp
6
为什么不直接修复你的线程代码,这样就不会崩溃了? - Jochen Ritzel
@dietrich-epp:导致崩溃的代码通常不是Python,实际上可能甚至不一定是Python代码。大多数数据都是线程本地的(唯一的例外是Python解释器中的部分),因此一个线程中的崩溃不会对其他线程产生(太多)副作用。 - Adrian Genaid
@jochen-ritzel:代码库相当庞大,即使大多数Python API部分都是以防御性编码的方式编写的,但使用Python进行脚本编写可能会揭示出更多的缺陷。 - Adrian Genaid
你可以在Python 3.3中使用faulthandler模块。 - Ramchandra Apte
2个回答

17
如果您正在使用(或可以使用)Python 3.4,那么有一个新的函数可用于完全相同的目的:

如果您正在使用(或可以使用)Python 3.4,那么有一个新的函数可用于完全相同的目的:

if (PyGILState_Check()) {
    /* I have the GIL */
}

https://docs.python.org/zh-cn/3/c-api/init.html?highlight=pygilstate_check#c.PyGILState_Check

如果当前线程保持全局解释器锁(GIL),则返回1;否则返回0。该函数可以在任何线程中的任何时间调用。只有当前线程状态已初始化并且当前持有 GIL,它才会返回 1。这主要是一个辅助/诊断函数。例如,在回调上下文或内存分配函数中,如果知道 GIL 被锁定,调用者可以执行敏感操作或以其他方式行为不同,则此函数可能很有用。

在 Python 2 中,您可以尝试以下内容:

int PyGILState_Check2(void) {
    PyThreadState * tstate = _PyThreadState_Current;
    return tstate && (tstate == PyGILState_GetThisThreadState());
}

我尝试过的情况下看起来运行良好。 https://github.com/pankajp/pygilstate_check/blob/master/_pygilstate_check.c#L9


2

我不知道您正在寻找什么……但是您应该考虑使用两个宏Py_BEGIN_ALLOW_THREADSPy_END_ALLOW_THREADS,使用这些宏可以确保它们之间的代码没有GIL锁定,并且其中的任何随机崩溃都将得到保证。


我已经在使用函数PyGILState_Ensure()/PyGILState_Release()获取/释放GIL。此外,当调用/离开C库代码时,SWIG会获取/释放锁定。因此,在我的情况下不需要使用Py_BEGIN_ALLOW_THREADS和Py_END_ALLOW_THREADS。但是,你说的随机崩溃只能发生在未锁定状态下是正确的。 - Adrian Genaid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接