@@ -1999,6 +1999,7 @@ resolve_final_tstate(_PyRuntimeState *runtime)
19991999 }
20002000 else {
20012001 /* Fall back to the current tstate. It's better than nothing. */
2002+ // XXX No it's not
20022003 main_tstate = tstate ;
20032004 }
20042005 }
@@ -2044,6 +2045,16 @@ _Py_Finalize(_PyRuntimeState *runtime)
20442045
20452046 _PyAtExit_Call (tstate -> interp );
20462047
2048+ /* Clean up any lingering subinterpreters.
2049+
2050+ Two preconditions need to be met here:
2051+
2052+ - This has to happen before _PyRuntimeState_SetFinalizing is
2053+ called, or else threads might get prematurely blocked.
2054+ - The world must not be stopped, as finalizers can run.
2055+ */
2056+ finalize_subinterpreters ();
2057+
20472058 assert (_PyThreadState_GET () == tstate );
20482059
20492060 /* Copy the core config, PyInterpreterState_Delete() free
@@ -2131,9 +2142,6 @@ _Py_Finalize(_PyRuntimeState *runtime)
21312142 _PyImport_FiniExternal (tstate -> interp );
21322143 finalize_modules (tstate );
21332144
2134- /* Clean up any lingering subinterpreters. */
2135- finalize_subinterpreters ();
2136-
21372145 /* Print debug stats if any */
21382146 _PyEval_Fini ();
21392147
@@ -2415,9 +2423,8 @@ Py_NewInterpreter(void)
24152423 return tstate ;
24162424}
24172425
2418- /* Delete an interpreter and its last thread. This requires that the
2419- given thread state is current, that the thread has no remaining
2420- frames, and that it is its interpreter's only remaining thread.
2426+ /* Delete an interpreter. This requires that the given thread state
2427+ is current, and that the thread has no remaining frames.
24212428 It is a fatal error to violate these constraints.
24222429
24232430 (Py_FinalizeEx() doesn't have these constraints -- it zaps
@@ -2447,15 +2454,20 @@ Py_EndInterpreter(PyThreadState *tstate)
24472454 _Py_FinishPendingCalls (tstate );
24482455
24492456 _PyAtExit_Call (tstate -> interp );
2450-
2451- if (tstate != interp -> threads .head || tstate -> next != NULL ) {
2452- Py_FatalError ("not the last thread" );
2453- }
2454-
2457+ _PyRuntimeState * runtime = interp -> runtime ;
2458+ _PyEval_StopTheWorldAll (runtime );
24552459 /* Remaining daemon threads will automatically exit
24562460 when they attempt to take the GIL (ex: PyEval_RestoreThread()). */
24572461 _PyInterpreterState_SetFinalizing (interp , tstate );
24582462
2463+ PyThreadState * list = _PyThreadState_RemoveExcept (tstate );
2464+ for (PyThreadState * p = list ; p != NULL ; p = p -> next ) {
2465+ _PyThreadState_SetShuttingDown (p );
2466+ }
2467+
2468+ _PyEval_StartTheWorldAll (runtime );
2469+ _PyThreadState_DeleteList (list , /*is_after_fork=*/ 0 );
2470+
24592471 // XXX Call something like _PyImport_Disable() here?
24602472
24612473 _PyImport_FiniExternal (tstate -> interp );
@@ -2485,6 +2497,8 @@ finalize_subinterpreters(void)
24852497 PyInterpreterState * main_interp = _PyInterpreterState_Main ();
24862498 assert (final_tstate -> interp == main_interp );
24872499 _PyRuntimeState * runtime = main_interp -> runtime ;
2500+ assert (!runtime -> stoptheworld .world_stopped );
2501+ assert (_PyRuntimeState_GetFinalizing (runtime ) == NULL );
24882502 struct pyinterpreters * interpreters = & runtime -> interpreters ;
24892503
24902504 /* Get the first interpreter in the list. */
@@ -2513,27 +2527,17 @@ finalize_subinterpreters(void)
25132527
25142528 /* Clean up all remaining subinterpreters. */
25152529 while (interp != NULL ) {
2516- assert (!_PyInterpreterState_IsRunningMain (interp ));
2517-
2518- /* Find the tstate to use for fini. We assume the interpreter
2519- will have at most one tstate at this point. */
2520- PyThreadState * tstate = interp -> threads .head ;
2521- if (tstate != NULL ) {
2522- /* Ideally we would be able to use tstate as-is, and rely
2523- on it being in a ready state: no exception set, not
2524- running anything (tstate->current_frame), matching the
2525- current thread ID (tstate->thread_id). To play it safe,
2526- we always delete it and use a fresh tstate instead. */
2527- assert (tstate != final_tstate );
2528- _PyThreadState_Attach (tstate );
2529- PyThreadState_Clear (tstate );
2530- _PyThreadState_Detach (tstate );
2531- PyThreadState_Delete (tstate );
2530+ /* Make a tstate for finalization. */
2531+ PyThreadState * tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
2532+ if (tstate == NULL ) {
2533+ // XXX Some graceful way to always get a thread state?
2534+ Py_FatalError ("thread state allocation failed" );
25322535 }
2533- tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
25342536
2535- /* Destroy the subinterpreter. */
2537+ /* Enter the subinterpreter. */
25362538 _PyThreadState_Attach (tstate );
2539+
2540+ /* Destroy the subinterpreter. */
25372541 Py_EndInterpreter (tstate );
25382542 assert (_PyThreadState_GET () == NULL );
25392543
0 commit comments