@@ -2054,12 +2054,23 @@ _Py_Finalize(_PyRuntimeState *runtime)
20542054 int malloc_stats = tstate -> interp -> config .malloc_stats ;
20552055#endif
20562056
2057+ /* Clean up any lingering subinterpreters.
2058+
2059+ Two preconditions need to be met here:
2060+
2061+ - This has to happen before _PyRuntimeState_SetFinalizing is
2062+ called, or else threads might get prematurely blocked.
2063+ - The world must not be stopped, as finalizers can run.
2064+ */
2065+ finalize_subinterpreters ();
2066+
20572067 /* Ensure that remaining threads are detached */
20582068 _PyEval_StopTheWorldAll (runtime );
20592069
20602070 /* Remaining daemon threads will be trapped in PyThread_hang_thread
20612071 when they attempt to take the GIL (ex: PyEval_RestoreThread()). */
20622072 _PyInterpreterState_SetFinalizing (tstate -> interp , tstate );
2073+
20632074 _PyRuntimeState_SetFinalizing (runtime , tstate );
20642075 runtime -> initialized = 0 ;
20652076 runtime -> core_initialized = 0 ;
@@ -2121,9 +2132,6 @@ _Py_Finalize(_PyRuntimeState *runtime)
21212132 _PyImport_FiniExternal (tstate -> interp );
21222133 finalize_modules (tstate );
21232134
2124- /* Clean up any lingering subinterpreters. */
2125- finalize_subinterpreters ();
2126-
21272135 /* Print debug stats if any */
21282136 _PyEval_Fini ();
21292137
@@ -2438,14 +2446,15 @@ Py_EndInterpreter(PyThreadState *tstate)
24382446 _Py_FinishPendingCalls (tstate );
24392447
24402448 _PyAtExit_Call (tstate -> interp );
2441-
2442- if (tstate != interp -> threads .head || tstate -> next != NULL ) {
2443- Py_FatalError ("not the last thread" );
2444- }
2449+ _PyRuntimeState * runtime = interp -> runtime ;
2450+ _PyEval_StopTheWorldAll (runtime );
2451+ PyThreadState * list = _PyThreadState_RemoveExcept (tstate );
24452452
24462453 /* Remaining daemon threads will automatically exit
24472454 when they attempt to take the GIL (ex: PyEval_RestoreThread()). */
24482455 _PyInterpreterState_SetFinalizing (interp , tstate );
2456+ _PyEval_StartTheWorldAll (runtime );
2457+ _PyThreadState_DeleteList (list );
24492458
24502459 // XXX Call something like _PyImport_Disable() here?
24512460
@@ -2476,6 +2485,8 @@ finalize_subinterpreters(void)
24762485 PyInterpreterState * main_interp = _PyInterpreterState_Main ();
24772486 assert (final_tstate -> interp == main_interp );
24782487 _PyRuntimeState * runtime = main_interp -> runtime ;
2488+ assert (!runtime -> stoptheworld .world_stopped );
2489+ assert (_PyRuntimeState_GetFinalizing (runtime ) == NULL );
24792490 struct pyinterpreters * interpreters = & runtime -> interpreters ;
24802491
24812492 /* Get the first interpreter in the list. */
@@ -2504,27 +2515,18 @@ finalize_subinterpreters(void)
25042515
25052516 /* Clean up all remaining subinterpreters. */
25062517 while (interp != NULL ) {
2507- assert (!_PyInterpreterState_IsRunningMain (interp ));
2508-
2509- /* Find the tstate to use for fini. We assume the interpreter
2510- will have at most one tstate at this point. */
2511- PyThreadState * tstate = interp -> threads .head ;
2512- if (tstate != NULL ) {
2513- /* Ideally we would be able to use tstate as-is, and rely
2514- on it being in a ready state: no exception set, not
2515- running anything (tstate->current_frame), matching the
2516- current thread ID (tstate->thread_id). To play it safe,
2517- we always delete it and use a fresh tstate instead. */
2518- assert (tstate != final_tstate );
2519- _PyThreadState_Attach (tstate );
2520- PyThreadState_Clear (tstate );
2521- _PyThreadState_Detach (tstate );
2522- PyThreadState_Delete (tstate );
2518+ /* Make a tstate for finalization. */
2519+ PyThreadState * tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
2520+ if (tstate == NULL )
2521+ {
2522+ // XXX Some graceful way to always get a thread state?
2523+ Py_FatalError ("thread state allocation failed" );
25232524 }
2524- tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
25252525
2526- /* Destroy the subinterpreter. */
2526+ /* Enter the subinterpreter. */
25272527 _PyThreadState_Attach (tstate );
2528+
2529+ /* Destroy the subinterpreter. */
25282530 Py_EndInterpreter (tstate );
25292531 assert (_PyThreadState_GET () == NULL );
25302532
0 commit comments