[issue13156] _PyGILState_Reinit assumes auto thread state will always exist which is not true.
Charles-François Natali
report at bugs.python.org
Wed Oct 12 09:10:04 CEST 2011
Charles-François Natali <neologix at free.fr> added the comment:
Note that this doesn't apply to default: the problem is that 2.7 and 3.2 don't use native TLS, and with the ad-hoc TLS implementation, a NULL value isn't supported:
"""
/* Internal helper.
* If the current thread has a mapping for key, the appropriate struct key*
* is returned. NB: value is ignored in this case!
* If there is no mapping for key in the current thread, then:
* If value is NULL, NULL is returned.
* Else a mapping of key to value is created for the current thread,
* and a pointer to a new struct key* is returned; except that if
* malloc() can't find room for a new struct key*, NULL is returned.
* So when value==NULL, this acts like a pure lookup routine, and when
* value!=NULL, this acts like dict.setdefault(), returning an existing
* mapping if one exists, else creating a new mapping.
"""
So PyThread_set_key_value() has different semantics between 2.7/3.2 and default...
> So _PyGILState_Reinit() is broken because it assumes that an auto
> thread state will always exist for the thread for it to reinit, which
> will not always be the case.
Hmm...
Please see http://docs.python.org/c-api/init.html#non-python-created-threads
"""
When threads are created using the dedicated Python APIs (such as the threading module), a thread state is automatically associated to them and the code showed above is therefore correct. However, when threads are created from C (for example by a third-party library with its own thread management), they don’t hold the GIL, nor is there a thread state structure for them.
If you need to call Python code from these threads (often this will be part of a callback API provided by the aforementioned third-party library), you must first register these threads with the interpreter by creating a thread state data structure, then acquiring the GIL, and finally storing their thread state pointer, before you can start using the Python/C API. When you are done, you should reset the thread state pointer, release the GIL, and finally free the thread state data structure.
The PyGILState_Ensure() and PyGILState_Release() functions do all of the above automatically. The typical idiom for calling into Python from a C thread is:
"""
I think you should be calling call PyGILState_Ensure() before (whoch does associate the thread state to the autoTLS key.
I let Antoine answer, he's got much more experience than me.
----------
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue13156>
_______________________________________
More information about the Python-bugs-list
mailing list