@@ -2000,6 +2000,7 @@ resolve_final_tstate(_PyRuntimeState *runtime)
20002000 }
20012001 else {
20022002 /* Fall back to the current tstate. It's better than nothing. */
2003+ // XXX No it's not
20032004 main_tstate = tstate ;
20042005 }
20052006 }
@@ -2045,6 +2046,16 @@ _Py_Finalize(_PyRuntimeState *runtime)
20452046
20462047 _PyAtExit_Call (tstate -> interp );
20472048
2049+ /* Clean up any lingering subinterpreters.
2050+
2051+ Two preconditions need to be met here:
2052+
2053+ - This has to happen before _PyRuntimeState_SetFinalizing is
2054+ called, or else threads might get prematurely blocked.
2055+ - The world must not be stopped, as finalizers can run.
2056+ */
2057+ finalize_subinterpreters ();
2058+
20482059 assert (_PyThreadState_GET () == tstate );
20492060
20502061 /* Copy the core config, PyInterpreterState_Delete() free
@@ -2132,9 +2143,6 @@ _Py_Finalize(_PyRuntimeState *runtime)
21322143 _PyImport_FiniExternal (tstate -> interp );
21332144 finalize_modules (tstate );
21342145
2135- /* Clean up any lingering subinterpreters. */
2136- finalize_subinterpreters ();
2137-
21382146 /* Print debug stats if any */
21392147 _PyEval_Fini ();
21402148
@@ -2416,9 +2424,8 @@ Py_NewInterpreter(void)
24162424 return tstate ;
24172425}
24182426
2419- /* Delete an interpreter and its last thread. This requires that the
2420- given thread state is current, that the thread has no remaining
2421- frames, and that it is its interpreter's only remaining thread.
2427+ /* Delete an interpreter. This requires that the given thread state
2428+ is current, and that the thread has no remaining frames.
24222429 It is a fatal error to violate these constraints.
24232430
24242431 (Py_FinalizeEx() doesn't have these constraints -- it zaps
@@ -2448,15 +2455,20 @@ Py_EndInterpreter(PyThreadState *tstate)
24482455 _Py_FinishPendingCalls (tstate );
24492456
24502457 _PyAtExit_Call (tstate -> interp );
2451-
2452- if (tstate != interp -> threads .head || tstate -> next != NULL ) {
2453- Py_FatalError ("not the last thread" );
2454- }
2455-
2458+ _PyRuntimeState * runtime = interp -> runtime ;
2459+ _PyEval_StopTheWorldAll (runtime );
24562460 /* Remaining daemon threads will automatically exit
24572461 when they attempt to take the GIL (ex: PyEval_RestoreThread()). */
24582462 _PyInterpreterState_SetFinalizing (interp , tstate );
24592463
2464+ PyThreadState * list = _PyThreadState_RemoveExcept (tstate );
2465+ for (PyThreadState * p = list ; p != NULL ; p = p -> next ) {
2466+ _PyThreadState_SetShuttingDown (p );
2467+ }
2468+
2469+ _PyEval_StartTheWorldAll (runtime );
2470+ _PyThreadState_DeleteList (list , /*is_after_fork=*/ 0 );
2471+
24602472 // XXX Call something like _PyImport_Disable() here?
24612473
24622474 _PyImport_FiniExternal (tstate -> interp );
@@ -2486,6 +2498,8 @@ finalize_subinterpreters(void)
24862498 PyInterpreterState * main_interp = _PyInterpreterState_Main ();
24872499 assert (final_tstate -> interp == main_interp );
24882500 _PyRuntimeState * runtime = main_interp -> runtime ;
2501+ assert (!runtime -> stoptheworld .world_stopped );
2502+ assert (_PyRuntimeState_GetFinalizing (runtime ) == NULL );
24892503 struct pyinterpreters * interpreters = & runtime -> interpreters ;
24902504
24912505 /* Get the first interpreter in the list. */
@@ -2514,27 +2528,17 @@ finalize_subinterpreters(void)
25142528
25152529 /* Clean up all remaining subinterpreters. */
25162530 while (interp != NULL ) {
2517- assert (!_PyInterpreterState_IsRunningMain (interp ));
2518-
2519- /* Find the tstate to use for fini. We assume the interpreter
2520- will have at most one tstate at this point. */
2521- PyThreadState * tstate = interp -> threads .head ;
2522- if (tstate != NULL ) {
2523- /* Ideally we would be able to use tstate as-is, and rely
2524- on it being in a ready state: no exception set, not
2525- running anything (tstate->current_frame), matching the
2526- current thread ID (tstate->thread_id). To play it safe,
2527- we always delete it and use a fresh tstate instead. */
2528- assert (tstate != final_tstate );
2529- _PyThreadState_Attach (tstate );
2530- PyThreadState_Clear (tstate );
2531- _PyThreadState_Detach (tstate );
2532- PyThreadState_Delete (tstate );
2531+ /* Make a tstate for finalization. */
2532+ PyThreadState * tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
2533+ if (tstate == NULL ) {
2534+ // XXX Some graceful way to always get a thread state?
2535+ Py_FatalError ("thread state allocation failed" );
25332536 }
2534- tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
25352537
2536- /* Destroy the subinterpreter. */
2538+ /* Enter the subinterpreter. */
25372539 _PyThreadState_Attach (tstate );
2540+
2541+ /* Destroy the subinterpreter. */
25382542 Py_EndInterpreter (tstate );
25392543 assert (_PyThreadState_GET () == NULL );
25402544
0 commit comments