-
-
Notifications
You must be signed in to change notification settings - Fork 31.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PyGILState_Ensure
in one thread causes the thread-local storage of other threads to be GCed
#130394
Comments
PyGILState_Ensure
in one thread causes the thread-local storage of other threads to be GCedPyGILState_Ensure
in one thread causes the thread-local storage of other threads to be GCed
PyGILState_Ensure
in one thread causes the thread-local storage of other threads to be GCedPyGILState_Ensure
in one thread causes the thread-local storage of other threads to be GCed
Hi! I'm not familiar with This may seem a little counterintuitive, but the GIL can also be released randomly in-between execution of Python instructions, not just calls to
That aside, I would suggest avoiding passing I've seen several reports before due to |
Hi @ZeroIntensity, thank you for the quick reply!
This differs from my understanding of how # Download https://gist.github.com/kevin85421/2d4fd5620ffdd7a1dfd36fd734fa7afe
python3 example.py
Worker-0 set value: Worker-0
Worker-1 set value: Worker-1
Worker-2 set value: Worker-2
Worker-0 read value: Worker-0
Worker-1 read value: Worker-1
Worker-2 read value: Worker-2
My observation based on the following example is that the GIL doesn't implicitly switch. Instead, the thread holds the thread should call # Download: https://gist.github.com/kevin85421/d34df2fac0af85efe25b3c3e4bf0ceea
g++ switchinterval.cc -I/usr/include/python3.12 -lpython3.12 -lpthread -o switchinterval
./switchinterval
[C++][17:18:34.651] Sleep 10 seconds
[C++][17:18:34.651] Hello from the default_pool in init_python_thread
[C++][17:18:34.651] Hello from the custom_pool in init_python_thread
Hello from default_pool, a = 1!
sys.getswitchinterval() = 0.005
[C++][17:18:44.651] Hello from the default_pool in release_gstate
Hello from custom_pool, a = 1! <---------- `custom_pool` gets the GIL after `default_pool` calls `PyGILState_Release`
sys.getswitchinterval() = 0.005
[C++][17:18:44.651] Hello from the custom_pool in release_gstate
a = 1 in release_gstate!
a = 1 in release_gstate!
Traceback (most recent call last):
File "<string>", line 1, in <module>
AttributeError: '_thread._local' object has no attribute 'name'
thread_local.name = custom_pool in release_gstate! My current guess is that when The following link points to the function that cleans up data related to a thread when it is garbage-collected. cpython/Lib/_threading_local.py Line 184 in 0c4248f
|
That would normally be right, but the important part about your example is that you redeclare the In fact, I'm not even really sure what happens when you set a You should refactor your code to something more like: Py_Initialize();
PyRun_SimpleString("import threading; thread_local = threading.local()");
thread1 = run_in_thread("thread_local.name = 'first'");
thread2 = run_in_thread("thread_local.name = 'second'");
// ...
Py_Finalize(); |
Oops, my bad. I don't notice that I redeclare it. The following gist can get the threading local state in both threads. https://gist.github.com/kevin85421/4b646b0ee07e5168b333d3325a59ca4c |
This is the doc I read: https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock. There are something possible to improve:
Following up on my comment: Will the GIL be released based on the switch interval in this case?
To provide more context, I am working on ray-project/ray, a distributed computing engine. Users add the Currently, we don't use A C++ thread:
To avoid this issue, I want the Python interpreter to treat the C++ thread as a Python thread, regardless of whether it is executing a Python function. My current solution:
|
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
default_pool
andcustom_pool
, and calls Python code.void init_python_thread
): Each threadPyGILState_Ensure()
a
and creates a thread-local state usingthreading.local()
.PyEval_SaveThread
to release GIL.void release_gstate
): Each threadPyEval_RestoreThread(*tstate)
to acquire GIL and restore thread state.a
PyGILState_Release
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.CPython versions tested on:
3.12
Operating systems tested on:
Linux
The text was updated successfully, but these errors were encountered: