-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
Description
Bug report
Bug description:
Currently, "pre-finalization" (callbacks executed while the interpreter is still fully intact) looks like this:
Lines 2023 to 2038 in 642e5df
wait_for_thread_shutdown(tstate); | |
// Make any remaining pending calls. | |
_Py_FinishPendingCalls(tstate); | |
/* The interpreter is still entirely intact at this point, and the | |
* exit funcs may be relying on that. In particular, if some thread | |
* or exit func is still waiting to do an import, the import machinery | |
* expects Py_IsInitialized() to return true. So don't say the | |
* runtime is uninitialized until after the exit funcs have run. | |
* Note that Threading.py uses an exit func to do a join on all the | |
* threads created thru it, so this also protects pending imports in | |
* the threads created via Threading. | |
*/ | |
_PyAtExit_Call(tstate->interp); |
Threads are joined first, then pending calls are executed, and finally atexit callbacks are executed. The problem is that any of these three can create one another, such as a pending call creating a thread, or an atexit handler scheduling a pending call. The best way to demonstrate this is by creating a new thread inside of an atexit callback:
import atexit
import threading
import time
def run():
print(24)
time.sleep(1)
print(42)
@atexit.register
def start_thread():
threading.Thread(target=run).start()
On 3.13+ (and probably earlier), you'll get one of these three outputs:
24
is printed.- Nothing is printed.
- A fatal error occurs due to the stdout lock being unavailable.
This is because the thread created is incorrectly non-daemon, because the call to threading._shutdown
(which should join it) has already happened.
@ericsnowcurrently, I discussed this with you at the PyCon sprints. I think we came to the agreement that the best way to fix this is by looping until all three of them execute no callbacks.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux