@@ -1992,6 +1992,7 @@ resolve_final_tstate(_PyRuntimeState *runtime)
19921992 }
19931993 else {
19941994 /* Fall back to the current tstate. It's better than nothing. */
1995+ // XXX No it's not
19951996 main_tstate = tstate ;
19961997 }
19971998 }
@@ -2037,6 +2038,16 @@ _Py_Finalize(_PyRuntimeState *runtime)
20372038
20382039 _PyAtExit_Call (tstate -> interp );
20392040
2041+ /* Clean up any lingering subinterpreters.
2042+
2043+ Two preconditions need to be met here:
2044+
2045+ - This has to happen before _PyRuntimeState_SetFinalizing is
2046+ called, or else threads might get prematurely blocked.
2047+ - The world must not be stopped, as finalizers can run.
2048+ */
2049+ finalize_subinterpreters ();
2050+
20402051 assert (_PyThreadState_GET () == tstate );
20412052
20422053 /* Copy the core config, PyInterpreterState_Delete() free
@@ -2124,9 +2135,6 @@ _Py_Finalize(_PyRuntimeState *runtime)
21242135 _PyImport_FiniExternal (tstate -> interp );
21252136 finalize_modules (tstate );
21262137
2127- /* Clean up any lingering subinterpreters. */
2128- finalize_subinterpreters ();
2129-
21302138 /* Print debug stats if any */
21312139 _PyEval_Fini ();
21322140
@@ -2410,9 +2418,8 @@ Py_NewInterpreter(void)
24102418 return tstate ;
24112419}
24122420
2413- /* Delete an interpreter and its last thread. This requires that the
2414- given thread state is current, that the thread has no remaining
2415- frames, and that it is its interpreter's only remaining thread.
2421+ /* Delete an interpreter. This requires that the given thread state
2422+ is current, and that the thread has no remaining frames.
24162423 It is a fatal error to violate these constraints.
24172424
24182425 (Py_FinalizeEx() doesn't have these constraints -- it zaps
@@ -2442,14 +2449,15 @@ Py_EndInterpreter(PyThreadState *tstate)
24422449 _Py_FinishPendingCalls (tstate );
24432450
24442451 _PyAtExit_Call (tstate -> interp );
2445-
2446- if (tstate != interp -> threads .head || tstate -> next != NULL ) {
2447- Py_FatalError ("not the last thread" );
2448- }
2452+ _PyRuntimeState * runtime = interp -> runtime ;
2453+ _PyEval_StopTheWorldAll (runtime );
2454+ PyThreadState * list = _PyThreadState_RemoveExcept (tstate );
24492455
24502456 /* Remaining daemon threads will automatically exit
24512457 when they attempt to take the GIL (ex: PyEval_RestoreThread()). */
24522458 _PyInterpreterState_SetFinalizing (interp , tstate );
2459+ _PyEval_StartTheWorldAll (runtime );
2460+ _PyThreadState_DeleteList (list , /*is_after_fork=*/ 0 );
24532461
24542462 // XXX Call something like _PyImport_Disable() here?
24552463
@@ -2480,6 +2488,8 @@ finalize_subinterpreters(void)
24802488 PyInterpreterState * main_interp = _PyInterpreterState_Main ();
24812489 assert (final_tstate -> interp == main_interp );
24822490 _PyRuntimeState * runtime = main_interp -> runtime ;
2491+ assert (!runtime -> stoptheworld .world_stopped );
2492+ assert (_PyRuntimeState_GetFinalizing (runtime ) == NULL );
24832493 struct pyinterpreters * interpreters = & runtime -> interpreters ;
24842494
24852495 /* Get the first interpreter in the list. */
@@ -2508,27 +2518,17 @@ finalize_subinterpreters(void)
25082518
25092519 /* Clean up all remaining subinterpreters. */
25102520 while (interp != NULL ) {
2511- assert (!_PyInterpreterState_IsRunningMain (interp ));
2512-
2513- /* Find the tstate to use for fini. We assume the interpreter
2514- will have at most one tstate at this point. */
2515- PyThreadState * tstate = interp -> threads .head ;
2516- if (tstate != NULL ) {
2517- /* Ideally we would be able to use tstate as-is, and rely
2518- on it being in a ready state: no exception set, not
2519- running anything (tstate->current_frame), matching the
2520- current thread ID (tstate->thread_id). To play it safe,
2521- we always delete it and use a fresh tstate instead. */
2522- assert (tstate != final_tstate );
2523- _PyThreadState_Attach (tstate );
2524- PyThreadState_Clear (tstate );
2525- _PyThreadState_Detach (tstate );
2526- PyThreadState_Delete (tstate );
2521+ /* Make a tstate for finalization. */
2522+ PyThreadState * tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
2523+ if (tstate == NULL ) {
2524+ // XXX Some graceful way to always get a thread state?
2525+ Py_FatalError ("thread state allocation failed" );
25272526 }
2528- tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
25292527
2530- /* Destroy the subinterpreter. */
2528+ /* Enter the subinterpreter. */
25312529 _PyThreadState_Attach (tstate );
2530+
2531+ /* Destroy the subinterpreter. */
25322532 Py_EndInterpreter (tstate );
25332533 assert (_PyThreadState_GET () == NULL );
25342534
0 commit comments