You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Starting new thread during finalization leads to call to PyMem_Free without holding the GIL #109795
Since #109135, thread_run checks if it is called during finalization, and in this case it frees thread bootstate in thread_bootstate_free and returns. The problem is that PyMem_Free shouldn't be called if GIL is not held.
$ ./python repro.py
0 ...................................failed with exit code 1
Traceback (most recent call last):
File "/home/vstinner/python/main/Lib/threading.py", line 641, in wait
signaled = self._cond.wait(timeout)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/vstinner/python/main/Lib/threading.py", line 337, in wait
saved_state = self._release_save()
^^^^^^^^^^^^^^^^^^^^
File "/home/vstinner/python/main/Lib/threading.py", line 295, in _release_save
self._lock.release() # No state to save
^^^^^^^^^^^^^^^^^^^^
KeyboardInterrupt
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 6, in <module>
File "/home/vstinner/python/main/Lib/threading.py", line 983, in start
self._started.wait()
File "/home/vstinner/python/main/Lib/threading.py", line 638, in wait
with self._cond:
File "/home/vstinner/python/main/Lib/threading.py", line 289, in __exit__
return self._lock.__exit__(*args)
^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: release unlocked lock
Yep, it takes precise timing for interrupt to make Python finalize before new thread will be started in thread_PyThread_start_new_thread. The repro I attached is fittable for my machine, but may not work on others.
Activity
vstinner commentedon Sep 24, 2023
thread_PyThread_start_new_thread() can easily use PyMem_RawMalloc() instead of PyMem_Malloc(). Do you want to propose a fix?
chgnrdv commentedon Sep 24, 2023
@vstinner, yes, I'll submit a PR shortly :)
gh-109795: `_thread.start_new_thread`: allocate thread bootstate usin…
pythongh-109795: `_thread.start_new_thread`: allocate thread bootstat…
vstinner commentedon Sep 25, 2023
Ah. After many attempts, I managed to reproduce the bug without the fix:
I modified the reproducer script:
Sometimes, I get other bugs like:
vstinner commentedon Sep 25, 2023
Thanks for the reproducer @chgnrdv!
The bug is hard to trigger :-( But apparently, I cannot reproduce the bug anymore. Good :-)
[3.11] gh-109795: `_thread.start_new_thread`: allocate thread bootsta…
chgnrdv commentedon Sep 25, 2023
@vstinner thank you for review :)
Yep, it takes precise timing for interrupt to make Python finalize before new thread will be started in
thread_PyThread_start_new_thread. The repro I attached is fittable for my machine, but may not work on others.pythongh-109795: `_thread.start_new_thread`: allocate thread bootstat…
pythongh-109795: `_thread.start_new_thread`: allocate thread bootstat…
[3.12] gh-108987: Fix _thread.start_new_thread() race condition (#109135
pythongh-109795: `_thread.start_new_thread`: allocate thread bootstat…