@@ -74,6 +74,7 @@ static PyStatus init_sys_streams(PyThreadState *tstate);
74
74
static PyStatus init_android_streams (PyThreadState * tstate );
75
75
#endif
76
76
static void wait_for_thread_shutdown (PyThreadState * tstate );
77
+ static void finalize_subinterpreters (void );
77
78
static void call_ll_exitfuncs (_PyRuntimeState * runtime );
78
79
79
80
/* The following places the `_PyRuntime` structure in a location that can be
@@ -1908,20 +1909,73 @@ finalize_interp_delete(PyInterpreterState *interp)
1908
1909
}
1909
1910
1910
1911
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 )
1913
1969
{
1914
1970
int status = 0 ;
1915
1971
1916
- _PyRuntimeState * runtime = & _PyRuntime ;
1972
+ /* Bail out early if already finalized (or never initialized). */
1917
1973
if (!runtime -> initialized ) {
1918
1974
return status ;
1919
1975
}
1920
1976
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 );
1925
1979
1926
1980
// Block some operations.
1927
1981
tstate -> interp -> finalizing = 1 ;
@@ -1944,6 +1998,8 @@ Py_FinalizeEx(void)
1944
1998
1945
1999
_PyAtExit_Call (tstate -> interp );
1946
2000
2001
+ assert (_PyThreadState_GET () == tstate );
2002
+
1947
2003
/* Copy the core config, PyInterpreterState_Delete() free
1948
2004
the core config memory */
1949
2005
#ifdef Py_REF_DEBUG
@@ -2024,6 +2080,9 @@ Py_FinalizeEx(void)
2024
2080
_PyImport_FiniExternal (tstate -> interp );
2025
2081
finalize_modules (tstate );
2026
2082
2083
+ /* Clean up any lingering subinterpreters. */
2084
+ finalize_subinterpreters ();
2085
+
2027
2086
/* Print debug stats if any */
2028
2087
_PyEval_Fini ();
2029
2088
@@ -2141,10 +2200,16 @@ Py_FinalizeEx(void)
2141
2200
return status ;
2142
2201
}
2143
2202
2203
+ int
2204
+ Py_FinalizeEx (void )
2205
+ {
2206
+ return _Py_Finalize (& _PyRuntime );
2207
+ }
2208
+
2144
2209
void
2145
2210
Py_Finalize (void )
2146
2211
{
2147
- Py_FinalizeEx ( );
2212
+ ( void ) _Py_Finalize ( & _PyRuntime );
2148
2213
}
2149
2214
2150
2215
@@ -2356,6 +2421,79 @@ _Py_IsInterpreterFinalizing(PyInterpreterState *interp)
2356
2421
return finalizing != NULL ;
2357
2422
}
2358
2423
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
+
2359
2497
/* Add the __main__ module */
2360
2498
2361
2499
static PyStatus
@@ -3217,7 +3355,7 @@ Py_Exit(int sts)
3217
3355
if (tstate != NULL && _PyThreadState_IsRunningMain (tstate )) {
3218
3356
_PyInterpreterState_SetNotRunningMain (tstate -> interp );
3219
3357
}
3220
- if (Py_FinalizeEx ( ) < 0 ) {
3358
+ if (_Py_Finalize ( & _PyRuntime ) < 0 ) {
3221
3359
sts = 120 ;
3222
3360
}
3223
3361
0 commit comments