Skip to content

Crash Due to Exception in threading._shutdown() #113148

Open
@ericsnowcurrently

Description

@ericsnowcurrently

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.12only security fixes3.13bugs and security fixes3.14bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)topic-subinterpreterstype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    Status

    Todo

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions