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