Как проверить, содержит ли поток текущий GIL?

Я попытался найти функцию, которая сообщает мне, имеет ли текущий поток глобальный интерпретатор или нет.

Документация Python/C-API, похоже, не содержит такой функции.

Мое текущее решение состоит в том, чтобы просто получить блокировку с помощью PyGILState_Ensure(), прежде чем отпускать ее, используя PyEval_SaveThread, чтобы не пытаться освободить блокировку, которая не была получена текущим потоком.

(Кстати, что означает "выдает фатальную ошибку"?)

Предыстория вопроса: У меня многопоточное приложение, в которое встроен Python. Если поток закрыт, не отпуская блокировку (что может произойти из-за сбоев), другие потоки больше не могут запускаться. Таким образом, при очистке/закрытии нитки, я хотел бы проверить, удерживается ли замок этой нитью и освобождает ее в этом случае.

Заранее благодарим за ответы!

Ответ 1

Если вы используете (или можете использовать) Python 3.4, есть новая функция для той же цели:

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

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

Возвращает 1, если текущий поток удерживает GIL и 0 в противном случае. Эта функция может быть вызвана из любого потока в любое время. Только если он инициализировал состояние потока Python и в настоящее время удерживает 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_THREADS и Py_END_ALLOW_THREADS, с помощью этих макросов вы можете убедиться, что код между ними не имеет GIL заблокирован и случайные сбои внутри них будут уверены.