Skip to content
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

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

Open
ericsnowcurrently opened this issue Dec 14, 2023 · 0 comments
Open

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

ericsnowcurrently opened this issue Dec 14, 2023 · 0 comments
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-subinterpreters type-crash A hard crash of the interpreter, possibly with a core dump

Comments

@ericsnowcurrently
Copy link
Member

ericsnowcurrently commented Dec 14, 2023

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().

@ericsnowcurrently ericsnowcurrently added type-bug An unexpected behavior, bug, or error interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-subinterpreters 3.12 bugs and security fixes 3.13 bugs and security fixes labels Dec 14, 2023
@ericsnowcurrently ericsnowcurrently added type-crash A hard crash of the interpreter, possibly with a core dump and removed type-bug An unexpected behavior, bug, or error labels Feb 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-subinterpreters type-crash A hard crash of the interpreter, possibly with a core dump
Projects
Status: Todo
Status: No status
Development

No branches or pull requests

1 participant