@@ -2060,8 +2060,18 @@ interp_has_atexit_callbacks(PyInterpreterState *interp)
20602060 return PyList_GET_SIZE (interp -> atexit .callbacks ) != 0 ;
20612061}
20622062
2063+ static int
2064+ runtime_has_subinterpreters (_PyRuntimeState * runtime )
2065+ {
2066+ assert (runtime != NULL );
2067+ HEAD_LOCK (runtime );
2068+ PyInterpreterState * interp = runtime -> interpreters .head ;
2069+ HEAD_UNLOCK (runtime );
2070+ return interp -> next != NULL ;
2071+ }
2072+
20632073static void
2064- make_pre_finalization_calls (PyThreadState * tstate )
2074+ make_pre_finalization_calls (PyThreadState * tstate , int subinterpreters )
20652075{
20662076 assert (tstate != NULL );
20672077 PyInterpreterState * interp = tstate -> interp ;
@@ -2089,6 +2099,19 @@ make_pre_finalization_calls(PyThreadState *tstate)
20892099
20902100 _PyAtExit_Call (tstate -> interp );
20912101
2102+ if (subinterpreters ) {
2103+ /* Clean up any lingering subinterpreters.
2104+
2105+ Two preconditions need to be met here:
2106+
2107+ - This has to happen before _PyRuntimeState_SetFinalizing is
2108+ called, or else threads might get prematurely blocked.
2109+ - The world must not be stopped, as finalizers can run.
2110+ */
2111+ finalize_subinterpreters ();
2112+ }
2113+
2114+
20922115 /* Stop the world to prevent other threads from creating threads or
20932116 * atexit callbacks. On the default build, this is simply locked by
20942117 * the GIL. For pending calls, we acquire the dedicated mutex, because
@@ -2099,9 +2122,13 @@ make_pre_finalization_calls(PyThreadState *tstate)
20992122 // XXX Why does _PyThreadState_DeleteList() rely on all interpreters
21002123 // being stopped?
21012124 _PyEval_StopTheWorldAll (interp -> runtime );
2125+ int has_subinterpreters = subinterpreters
2126+ ? runtime_has_subinterpreters (interp -> runtime )
2127+ : 0 ;
21022128 int should_continue = (interp_has_threads (interp )
21032129 || interp_has_atexit_callbacks (interp )
2104- || interp_has_pending_calls (interp ));
2130+ || interp_has_pending_calls (interp )
2131+ || has_subinterpreters );
21052132 if (!should_continue ) {
21062133 break ;
21072134 }
@@ -2128,19 +2155,8 @@ _Py_Finalize(_PyRuntimeState *runtime)
21282155 // Block some operations.
21292156 tstate -> interp -> finalizing = 1 ;
21302157
2131- /* Clean up any lingering subinterpreters.
2132-
2133- Two preconditions need to be met here:
2134-
2135- - This has to happen before _PyRuntimeState_SetFinalizing is
2136- called, or else threads might get prematurely blocked.
2137- - The world must not be stopped, as finalizers can run.
2138- */
2139- // TODO: Prevent new subinterpreters after this point
2140- finalize_subinterpreters ();
2141-
21422158 // This call stops the world and takes the pending calls lock.
2143- make_pre_finalization_calls (tstate );
2159+ make_pre_finalization_calls (tstate , /*subinterpreters=*/ 1 );
21442160
21452161 assert (_PyThreadState_GET () == tstate );
21462162
@@ -2536,7 +2552,7 @@ Py_EndInterpreter(PyThreadState *tstate)
25362552 interp -> finalizing = 1 ;
25372553
25382554 // This call stops the world and takes the pending calls lock.
2539- make_pre_finalization_calls (tstate );
2555+ make_pre_finalization_calls (tstate , /*subinterpreters=*/ 0 );
25402556
25412557 ASSERT_WORLD_STOPPED (interp );
25422558 /* Remaining daemon threads will automatically exit
0 commit comments