16

I tried to find a function that tells me whether the current thread has the global interpreter lock or not.

The Python/C-API documentation does not seem to contain such a function.

My current solution is to just acquire the lock using PyGILState_Ensure() before releasing it using PyEval_SaveThread to not try releasing a lock that wasn't acquired by the current thread.

(btw. what does "issues a fatal error" mean?)

Background of this question: I have a multithreaded application which embeds Python. If a thread is closed without releasing the lock (which might occur due to crashes), other threads are not able to run any more. Thus, when cleaning up/closing the thread, I would like to check whether the lock is held by this thread and release it in this case.

Thanks in advance for answers!

Perception
  • 79,279
  • 19
  • 185
  • 195
Adrian Genaid
  • 416
  • 5
  • 17
  • 6
    If a thread crashes while holding the GIL, I cannot imagine that it would be safe to run another Python thread. – Dietrich Epp Jul 06 '12 at 17:36
  • 6
    Why don't you just fix your thread code so it wont crash? – Jochen Ritzel Jul 06 '12 at 18:45
  • @dietrich-epp: the code that causes the crash is normally not python, in fact it might not even be necessarily python code where the crash happens. Most data is thread local (only exception are parts in the python interpreter) so a crash in one thread will not have (too much) side effects in other threads. – Adrian Genaid Jul 08 '12 at 10:08
  • @jochen-ritzel: the code base is quite huge, and even if most python API-parts were coded defensively, scripting using python might disclose further deficiencies. – Adrian Genaid Jul 08 '12 at 10:19
  • You might able to use the `faulthandler` module in Python 3.3. – Ramchandra Apte Jul 22 '12 at 03:11

2 Answers2

16

If you are using (or can use) Python 3.4, there's a new function for the exact same purpose:

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

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

Return 1 if the current thread is holding the GIL and 0 otherwise. This function can be called from any thread at any time. Only if it has had its Python thread state initialized and currently is holding the GIL will it return 1. This is mainly a helper/diagnostic function. It can be useful for example in callback contexts or memory allocation functions when knowing that the GIL is locked can allow the caller to perform sensitive actions or otherwise behave differently.

In python 2, you can try something like the following:

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

It seems to work well in the cases i have tried. https://github.com/pankajp/pygilstate_check/blob/master/_pygilstate_check.c#L9

pankaj
  • 1,450
  • 14
  • 15
2

I dont know what you are looking for ... but just you should consider the use of the both macros Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS, with this macros you can make sure that the code between them doesn't have the GIL locked and random crashes inside them will be sure.

pfreixes
  • 439
  • 2
  • 6
  • I am already using the functions PyGILState_Ensure()/PyGILState_Release() for acquiring/releasing the GIL. Additionally, SWIG acquires/releases the lock whenever calling into/leaving the C library code. So Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS are not needed in my case. But I think you are right when saying that random crashes can only occur in an unlocked state. – Adrian Genaid Mar 20 '13 at 10:27