Repository navigation
Crash Due to Exception in threading._shutdown() #113148
Copy link
Copy link
Closed
Labels
3.12only security fixesonly security fixes3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-subinterpreterstype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Description
One of the first thing that happens during interpreter finalization is waiting for all non-daemon threads to finish. This is implemented by calling threading._shutdown(). If an exception is raised there (e.g. in a threading "atexit" function), it gets ignored and we end up with non-daemon threads still running. In subinterpreters that results in a fatal error almost immediately after, since we make sure there's only one thread state left at that point.
Reproducer:
$ cat > /tmp/crash-interp-lingering-thread.py << EOF
import threading
from test.support import interpreters
interp = interpreters.create()
interp.exec_sync(f"""if True:
import threading
import time
done = False
def notify_fini():
global done
done = True
raise Exception # <-------
t.join()
threading._register_atexit(notify_fini)
def task():
while not done:
time.sleep(0.1)
t = threading.Thread(target=task)
t.start()
""")
interp.close()
EOF
$ ./python /tmp/crash-interp-lingering-thread.py
Exception ignored on threading shutdown:
Traceback (most recent call last):
File "./cpython/Lib/threading.py", line 1623, in _shutdown
atexit_call()
File "<string>", line 10, in notify_fini
Exception:
Fatal Python error: Py_EndInterpreter: not the last thread
Python runtime state: initialized
Current thread 0x00007fc8bf76a100 (most recent call first):
<no Python frame>
Thread 0x00007fc8bd3d5700 (most recent call first):
File "<string>", line 16 in task
File "./cpython/Lib/threading.py", line 1020 in run
File "./cpython/Lib/threading.py", line 1083 in _bootstrap_inner
File "./cpython/Lib/threading.py", line 1040 in _bootstrap
Aborted (core dumped)
The solution? Make sure threading._shutdown() finishes its fundamental job: stop all non-daemon threads and wait for them to finish. At the very least, this means ignoring exceptions from functions registered with threading._register_atexit().
Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
3.12only security fixesonly security fixes3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-subinterpreterstype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Projects
- StatusShow more project fieldsDone
- StatusShow more project fieldsDone
Activity
devdanzin commentedon Feb 23, 2025
On code generated by fuzzing, I get the same error as above 99.9% of the time, but there's a rare segfault coming from the same code (in a GILfull build), here's the backtrace:
Do you think it's the same issue, or should it be filed as a new one?
Since the segfault is very rare, it's hard to reduce the test case :(
pythongh-113148: Handle exceptions from threading.atexit functions
Merge branch 'main' into pythongh-113148-handle-exceptions-at-thread-…
devdanzin commentedon Mar 25, 2025
If this is the same issue, the reproducer can be simplified to:
devdanzin commentedon Mar 26, 2025
Here's the backtrace for an even harder to trigger (1 in 1500 runs, as opposed to 1 in 600 runs for the other one) segfault from the repro above:
ZeroIntensity commentedon Mar 26, 2025
That looks like a duplicate of #128639.
ZeroIntensity commentedon Sep 19, 2025
I can no longer reproduce this, so I think we finished this one.