@@ -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
@@ -2414,9 +2422,8 @@ Py_NewInterpreter(void)
24142422 return tstate ;
24152423}
24162424
2417- /* Delete an interpreter and its last thread. This requires that the
2418- given thread state is current, that the thread has no remaining
2419- frames, and that it is its interpreter's only remaining thread.
2425+ /* Delete an interpreter. This requires that the given thread state
2426+ is current, and that the thread has no remaining frames.
24202427 It is a fatal error to violate these constraints.
24212428
24222429 (Py_FinalizeEx() doesn't have these constraints -- it zaps
@@ -2446,15 +2453,20 @@ Py_EndInterpreter(PyThreadState *tstate)
24462453 _Py_FinishPendingCalls (tstate );
24472454
24482455 _PyAtExit_Call (tstate -> interp );
2449-
2450- if (tstate != interp -> threads .head || tstate -> next != NULL ) {
2451- Py_FatalError ("not the last thread" );
2452- }
2453-
2456+ _PyRuntimeState * runtime = interp -> runtime ;
2457+ _PyEval_StopTheWorldAll (runtime );
24542458 /* Remaining daemon threads will automatically exit
24552459 when they attempt to take the GIL (ex: PyEval_RestoreThread()). */
24562460 _PyInterpreterState_SetFinalizing (interp , tstate );
24572461
2462+ PyThreadState * list = _PyThreadState_RemoveExcept (tstate );
2463+ for (PyThreadState * p = list ; p != NULL ; p = p -> next ) {
2464+ _PyThreadState_SetShuttingDown (p );
2465+ }
2466+
2467+ _PyEval_StartTheWorldAll (runtime );
2468+ _PyThreadState_DeleteList (list , /*is_after_fork=*/ 0 );
2469+
24582470 // XXX Call something like _PyImport_Disable() here?
24592471
24602472 _PyImport_FiniExternal (tstate -> interp );
@@ -2484,6 +2496,8 @@ finalize_subinterpreters(void)
24842496 PyInterpreterState * main_interp = _PyInterpreterState_Main ();
24852497 assert (final_tstate -> interp == main_interp );
24862498 _PyRuntimeState * runtime = main_interp -> runtime ;
2499+ assert (!runtime -> stoptheworld .world_stopped );
2500+ assert (_PyRuntimeState_GetFinalizing (runtime ) == NULL );
24872501 struct pyinterpreters * interpreters = & runtime -> interpreters ;
24882502
24892503 /* Get the first interpreter in the list. */
@@ -2512,27 +2526,17 @@ finalize_subinterpreters(void)
25122526
25132527 /* Clean up all remaining subinterpreters. */
25142528 while (interp != NULL ) {
2515- assert (!_PyInterpreterState_IsRunningMain (interp ));
2516-
2517- /* Find the tstate to use for fini. We assume the interpreter
2518- will have at most one tstate at this point. */
2519- PyThreadState * tstate = interp -> threads .head ;
2520- if (tstate != NULL ) {
2521- /* Ideally we would be able to use tstate as-is, and rely
2522- on it being in a ready state: no exception set, not
2523- running anything (tstate->current_frame), matching the
2524- current thread ID (tstate->thread_id). To play it safe,
2525- we always delete it and use a fresh tstate instead. */
2526- assert (tstate != final_tstate );
2527- _PyThreadState_Attach (tstate );
2528- PyThreadState_Clear (tstate );
2529- _PyThreadState_Detach (tstate );
2530- PyThreadState_Delete (tstate );
2529+ /* Make a tstate for finalization. */
2530+ PyThreadState * tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
2531+ if (tstate == NULL ) {
2532+ // XXX Some graceful way to always get a thread state?
2533+ Py_FatalError ("thread state allocation failed" );
25312534 }
2532- tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
25332535
2534- /* Destroy the subinterpreter. */
2536+ /* Enter the subinterpreter. */
25352537 _PyThreadState_Attach (tstate );
2538+
2539+ /* Destroy the subinterpreter. */
25362540 Py_EndInterpreter (tstate );
25372541 assert (_PyThreadState_GET () == NULL );
25382542
0 commit comments