@@ -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