Open
Description
Bug report
Bug description:
# Download https://gist.github.com/kevin85421/4616545d3bed2ebcfe5d0a01bdfde3ff
g++ example.cc -I/usr/include/python3.12 -lpython3.12 -lpthread -o example
./example
- The above script creates two C++ threads,
default_pool
andcustom_pool
, and calls Python code.- Phase 1 (
void init_python_thread
): Each thread- Calls
PyGILState_Ensure()
- Runs Python code that assigns the value 1 to the variable
a
and creates a thread-local state usingthreading.local()
. - Calls
PyEval_SaveThread
to release GIL.
- Calls
- Phase 2 (
void release_gstate
): Each thread- Calls
PyEval_RestoreThread(*tstate)
to acquire GIL and restore thread state. - Runs Python code to print
a
- Runs Python code to print thread-local state.
- Calls
PyGILState_Release
- Calls
- Phase 1 (
The thread who is the first thread to call PyGILState_Ensure()
will fail to print thread-local state in step 2.
In the following example log,
default_pool
callsPyGILState_Ensure()
and writesa=1
and thread-local state.custom_pool
callsPyGILState_Ensure()
and writesa=1
and thread-local state. => My current guess is thatPyGILState_Ensure()
here makes the thread-local state ofdefault_pool
be GCed.
[C++][08:21:37.740] Hello from the default_pool in init_python_thread
[C++][08:21:37.741] Hello from the custom_pool in init_python_thread
Hello from default_pool, a = 1!
[C++][08:21:37.744] Hello from the default_pool in release_gstate
Hello from custom_pool, a = 1!
a = 1 in release_gstate!
[C++][08:21:37.744] Hello from the custom_pool in release_gstate
Traceback (most recent call last):
File "<string>", line 1, in <module>
AttributeError: '_thread._local' object has no attribute 'name'
a = 1 in release_gstate!
thread_local.name = custom_pool in release_gstate!
CPython versions tested on:
3.12
Operating systems tested on:
Linux