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