Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
Description
Bug report
threading._shutdown()
relies on_main_thread
having_tstate_lock
notNone
(there is assert for that). When fork is called from a DummyThread (in my case, that's a thread created by (Py)Qt), it gets promoted to main thread, but remains very simplistic DummyThread. Especially, nobody initializes its_tstate_lock
.threading._after_fork()
handles the case of current thread not being in_active
dict at all (by creating new MainThread object), but it doesn't handle the case of having DummyThread there already. This results in AssertionError in thread shutdown method - which for example confusesmultiprocessing.Process
(it gets exit code 1, even if the process function was successful).
Reproducer:
#!/usr/bin/python3import threadingimport multiprocessingimport _threadclass Bar(multiprocessing.Process): def run(self): print("process")def run_thread(lock): # the call to current_thread() is crucial for reproducer - it allocates # DummyThread() print(f"thread: {threading.current_thread()}") p = Bar() p.start() p.join() print(f"proc exit code: {p.exitcode}") lock.release()def main(): lock = _thread.allocate_lock() lock.acquire() t = _thread.start_new_thread(run_thread, (lock,)) # t.join lock.acquire() print(f"thread exit")main()
It should print:
thread: <_DummyThread(Dummy-1, started daemon 135243893053120)>processproc exit code: 0thread exit
but it prints:
thread: <_DummyThread(Dummy-1, started daemon 135243893053120)>processproc exit code: 1thread exit
(see exit code difference)
multiprocessing.Process
(or rathermultiprocessing.popen_fork.Popen._launch()
to be specific) swallows the exception, but adding some debug prints there I get:
Traceback (most recent call last): File "/usr/lib64/python3.11/multiprocessing/popen_fork.py", line 71, in _launch code = process_obj._bootstrap(parent_sentinel=child_r) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/multiprocessing/process.py", line 332, in _bootstrap threading._shutdown() File "/usr/lib64/python3.11/threading.py", line 1553, in _shutdown assert tlock is not None ^^^^^^^^^^^^^^^^^
Your environment
- CPython versions tested on: 3.11.2
- Operating system and architecture: Fedora 37, x86_64
Linked PRs
- gh-102512: Fix threading after os.fork() called from a foreign thread #102517
- gh-102512: Fix threading after os.fork() called from a foreign thread #113261
- [3.12] gh-102512: Turn _DummyThread into _MainThread after os.fork() called from a foreign thread (GH-113261) #114430
- [3.11] gh-102512: Turn _DummyThread into _MainThread after os.fork() called from a foreign thread (GH-113261) #114431
Metadata
Metadata
Assignees
Labels
Projects
Status