@@ -74,6 +74,7 @@ static PyStatus init_sys_streams(PyThreadState *tstate);
7474static PyStatus init_android_streams (PyThreadState * tstate );
7575#endif
7676static void wait_for_thread_shutdown (PyThreadState * tstate );
77+ static void finalize_subinterpreters (void );
7778static void call_ll_exitfuncs (_PyRuntimeState * runtime );
7879
7980/* The following places the `_PyRuntime` structure in a location that can be
@@ -1908,20 +1909,73 @@ finalize_interp_delete(PyInterpreterState *interp)
19081909}
19091910
19101911
1911- int
1912- Py_FinalizeEx (void )
1912+ /* Conceptually, there isn't a good reason for Py_Finalize()
1913+ to be called in any other thread than the one where Py_Initialize()
1914+ was called. Consequently, it would make sense to fail if the thread
1915+ or thread state (or interpreter) don't match. However, such
1916+ constraints have never been enforced, and, as unlikely as it may be,
1917+ there may be users relying on the unconstrained behavior. Thus,
1918+ we do our best here to accommodate that possibility. */
1919+
1920+ static PyThreadState *
1921+ resolve_final_tstate (_PyRuntimeState * runtime )
1922+ {
1923+ PyThreadState * main_tstate = runtime -> main_tstate ;
1924+ assert (main_tstate != NULL );
1925+ assert (main_tstate -> thread_id == runtime -> main_thread );
1926+ PyInterpreterState * main_interp = _PyInterpreterState_Main ();
1927+ assert (main_tstate -> interp == main_interp );
1928+
1929+ PyThreadState * tstate = _PyThreadState_GET ();
1930+ if (_Py_IsMainThread ()) {
1931+ if (tstate != main_tstate ) {
1932+ /* This implies that Py_Finalize() was called while
1933+ a non-main interpreter was active or while the main
1934+ tstate was temporarily swapped out with another.
1935+ Neither case should be allowed, but, until we get around
1936+ to fixing that (and Py_Exit()), we're letting it go. */
1937+ (void )PyThreadState_Swap (main_tstate );
1938+ }
1939+ }
1940+ else {
1941+ /* This is another unfortunate case where Py_Finalize() was
1942+ called when it shouldn't have been. We can't simply switch
1943+ over to the main thread. At the least, however, we can make
1944+ sure the main interpreter is active. */
1945+ if (!_Py_IsMainInterpreter (tstate -> interp )) {
1946+ /* We don't go to the trouble of updating runtime->main_tstate
1947+ since it will be dead soon anyway. */
1948+ main_tstate =
1949+ _PyThreadState_New (main_interp , _PyThreadState_WHENCE_FINI );
1950+ if (main_tstate != NULL ) {
1951+ _PyThreadState_Bind (main_tstate );
1952+ (void )PyThreadState_Swap (main_tstate );
1953+ }
1954+ else {
1955+ /* Fall back to the current tstate. It's better than nothing. */
1956+ main_tstate = tstate ;
1957+ }
1958+ }
1959+ }
1960+ assert (main_tstate != NULL );
1961+
1962+ /* We might want to warn if main_tstate->current_frame != NULL. */
1963+
1964+ return main_tstate ;
1965+ }
1966+
1967+ static int
1968+ _Py_Finalize (_PyRuntimeState * runtime )
19131969{
19141970 int status = 0 ;
19151971
1916- _PyRuntimeState * runtime = & _PyRuntime ;
1972+ /* Bail out early if already finalized (or never initialized). */
19171973 if (!runtime -> initialized ) {
19181974 return status ;
19191975 }
19201976
1921- /* Get current thread state and interpreter pointer */
1922- PyThreadState * tstate = _PyThreadState_GET ();
1923- // XXX assert(_Py_IsMainInterpreter(tstate->interp));
1924- // XXX assert(_Py_IsMainThread());
1977+ /* Get final thread state pointer. */
1978+ PyThreadState * tstate = resolve_final_tstate (runtime );
19251979
19261980 // Block some operations.
19271981 tstate -> interp -> finalizing = 1 ;
@@ -1944,6 +1998,8 @@ Py_FinalizeEx(void)
19441998
19451999 _PyAtExit_Call (tstate -> interp );
19462000
2001+ assert (_PyThreadState_GET () == tstate );
2002+
19472003 /* Copy the core config, PyInterpreterState_Delete() free
19482004 the core config memory */
19492005#ifdef Py_REF_DEBUG
@@ -2024,6 +2080,9 @@ Py_FinalizeEx(void)
20242080 _PyImport_FiniExternal (tstate -> interp );
20252081 finalize_modules (tstate );
20262082
2083+ /* Clean up any lingering subinterpreters. */
2084+ finalize_subinterpreters ();
2085+
20272086 /* Print debug stats if any */
20282087 _PyEval_Fini ();
20292088
@@ -2141,10 +2200,16 @@ Py_FinalizeEx(void)
21412200 return status ;
21422201}
21432202
2203+ int
2204+ Py_FinalizeEx (void )
2205+ {
2206+ return _Py_Finalize (& _PyRuntime );
2207+ }
2208+
21442209void
21452210Py_Finalize (void )
21462211{
2147- Py_FinalizeEx ( );
2212+ ( void ) _Py_Finalize ( & _PyRuntime );
21482213}
21492214
21502215
@@ -2356,6 +2421,79 @@ _Py_IsInterpreterFinalizing(PyInterpreterState *interp)
23562421 return finalizing != NULL ;
23572422}
23582423
2424+ static void
2425+ finalize_subinterpreters (void )
2426+ {
2427+ PyThreadState * final_tstate = _PyThreadState_GET ();
2428+ PyInterpreterState * main_interp = _PyInterpreterState_Main ();
2429+ assert (final_tstate -> interp == main_interp );
2430+ _PyRuntimeState * runtime = main_interp -> runtime ;
2431+ struct pyinterpreters * interpreters = & runtime -> interpreters ;
2432+
2433+ /* Get the first interpreter in the list. */
2434+ HEAD_LOCK (runtime );
2435+ PyInterpreterState * interp = interpreters -> head ;
2436+ if (interp == main_interp ) {
2437+ interp = interp -> next ;
2438+ }
2439+ HEAD_UNLOCK (runtime );
2440+
2441+ /* Bail out if there are no subinterpreters left. */
2442+ if (interp == NULL ) {
2443+ return ;
2444+ }
2445+
2446+ /* Warn the user if they forgot to clean up subinterpreters. */
2447+ (void )PyErr_WarnEx (
2448+ PyExc_RuntimeWarning ,
2449+ "remaining subinterpreters; "
2450+ "destroy them with _interpreters.destroy()" ,
2451+ 0 );
2452+
2453+ /* Swap out the current tstate, which we know must belong
2454+ to the main interpreter. */
2455+ _PyThreadState_Detach (final_tstate );
2456+
2457+ /* Clean up all remaining subinterpreters. */
2458+ while (interp != NULL ) {
2459+ assert (!_PyInterpreterState_IsRunningMain (interp ));
2460+
2461+ /* Find the tstate to use for fini. We assume the interpreter
2462+ will have at most one tstate at this point. */
2463+ PyThreadState * tstate = interp -> threads .head ;
2464+ if (tstate != NULL ) {
2465+ /* Ideally we would be able to use tstate as-is, and rely
2466+ on it being in a ready state: no exception set, not
2467+ running anything (tstate->current_frame), matching the
2468+ current thread ID (tstate->thread_id). To play it safe,
2469+ we always delete it and use a fresh tstate instead. */
2470+ assert (tstate != final_tstate );
2471+ _PyThreadState_Attach (tstate );
2472+ PyThreadState_Clear (tstate );
2473+ _PyThreadState_Detach (tstate );
2474+ PyThreadState_Delete (tstate );
2475+ }
2476+ tstate = _PyThreadState_NewBound (interp , _PyThreadState_WHENCE_FINI );
2477+
2478+ /* Destroy the subinterpreter. */
2479+ _PyThreadState_Attach (tstate );
2480+ Py_EndInterpreter (tstate );
2481+ assert (_PyThreadState_GET () == NULL );
2482+
2483+ /* Advance to the next interpreter. */
2484+ HEAD_LOCK (runtime );
2485+ interp = interpreters -> head ;
2486+ if (interp == main_interp ) {
2487+ interp = interp -> next ;
2488+ }
2489+ HEAD_UNLOCK (runtime );
2490+ }
2491+
2492+ /* Switch back to the main interpreter. */
2493+ _PyThreadState_Attach (final_tstate );
2494+ }
2495+
2496+
23592497/* Add the __main__ module */
23602498
23612499static PyStatus
@@ -3217,7 +3355,7 @@ Py_Exit(int sts)
32173355 if (tstate != NULL && _PyThreadState_IsRunningMain (tstate )) {
32183356 _PyInterpreterState_SetNotRunningMain (tstate -> interp );
32193357 }
3220- if (Py_FinalizeEx ( ) < 0 ) {
3358+ if (_Py_Finalize ( & _PyRuntime ) < 0 ) {
32213359 sts = 120 ;
32223360 }
32233361
0 commit comments