@@ -1923,6 +1923,9 @@ resolve_final_tstate(_PyRuntimeState *runtime, struct pyfinalize_args *args)
1923
1923
assert (tstate -> interp -> runtime == runtime );
1924
1924
assert (tstate -> thread_id == PyThread_get_thread_ident ());
1925
1925
PyInterpreterState * main_interp = _PyInterpreterState_Main ();
1926
+ PyThreadState * main_tstate = runtime -> main_tstate ;
1927
+
1928
+ /* First we report unexpected Py_Finalize() usage. */
1926
1929
1927
1930
#define PRINT_ERROR (msg ) \
1928
1931
if (args->verbose) { \
@@ -1931,9 +1934,10 @@ resolve_final_tstate(_PyRuntimeState *runtime, struct pyfinalize_args *args)
1931
1934
1932
1935
/* The main tstate is set by Py_Initialize(), but can be unset
1933
1936
* or even replaced in unlikely cases. */
1934
- PyThreadState * main_tstate = runtime -> main_tstate ;
1935
1937
if (main_tstate == NULL ) {
1936
1938
PRINT_ERROR ("main thread state not set" );
1939
+ /* Ideally, we would make sure a main tstate is set.
1940
+ For now we leave it unset. */
1937
1941
}
1938
1942
else {
1939
1943
assert (main_tstate -> thread_id == runtime -> main_thread );
@@ -1949,48 +1953,51 @@ resolve_final_tstate(_PyRuntimeState *runtime, struct pyfinalize_args *args)
1949
1953
}
1950
1954
}
1951
1955
1952
- if (_Py_IsMainThread ()) {
1956
+ if (!_Py_IsMainThread ()) {
1957
+ PRINT_ERROR ("expected to be in the main thread" );
1958
+ }
1959
+
1960
+ if (tstate -> interp != main_interp ) {
1961
+ PRINT_ERROR ("expected main interpreter to be active" );
1962
+ }
1963
+
1964
+ #undef PRINT_ERROR
1965
+
1966
+ /* Then we decide the thread state we should use for finalization. */
1967
+
1968
+ PyThreadState * final_tstate = tstate ;
1969
+ if (_Py_IsMainThread () && main_tstate != NULL ) {
1953
1970
if (tstate != main_tstate ) {
1954
1971
/* This implies that Py_Finalize() was called while
1955
1972
a non-main interpreter was active or while the main
1956
1973
tstate was temporarily swapped out with another.
1957
1974
Neither case should be allowed, but, until we get around
1958
1975
to fixing that (and Py_Exit()), we're letting it go. */
1959
- if (tstate -> interp != main_interp ) {
1960
- PRINT_ERROR ("expected main interpreter to be active" );
1961
- }
1962
- (void )PyThreadState_Swap (main_tstate );
1976
+ final_tstate = main_tstate ;
1963
1977
}
1964
1978
}
1965
1979
else {
1966
- PRINT_ERROR ("expected to be in the main thread" );
1967
1980
/* This is another unfortunate case where Py_Finalize() was
1968
1981
called when it shouldn't have been. We can't simply switch
1969
1982
over to the main thread. At the least, however, we can make
1970
1983
sure the main interpreter is active. */
1971
- if (!_Py_IsMainInterpreter (tstate -> interp )) {
1972
- PRINT_ERROR ("expected main interpreter to be active" );
1984
+ if (tstate -> interp != main_interp ) {
1973
1985
/* We don't go to the trouble of updating runtime->main_tstate
1974
1986
since it will be dead soon anyway. */
1975
- main_tstate =
1987
+ final_tstate =
1976
1988
_PyThreadState_New (main_interp , _PyThreadState_WHENCE_FINI );
1977
- if (main_tstate != NULL ) {
1978
- _PyThreadState_Bind (main_tstate );
1979
- (void )PyThreadState_Swap (main_tstate );
1980
- }
1981
- else {
1982
- /* Fall back to the current tstate. It's better than nothing. */
1983
- main_tstate = tstate ;
1989
+ if (final_tstate != NULL ) {
1990
+ _PyThreadState_Bind (final_tstate );
1984
1991
}
1992
+ /* Otherwise we fall back to the current tstate.
1993
+ It's better than nothing. */
1985
1994
}
1986
1995
}
1987
- assert (main_tstate != NULL );
1996
+ assert (final_tstate != NULL );
1988
1997
1989
- /* We might want to warn if main_tstate ->current_frame != NULL. */
1998
+ /* We might want to warn if final_tstate ->current_frame != NULL. */
1990
1999
1991
- return main_tstate ;
1992
-
1993
- #undef PRINT_ERROR
2000
+ return final_tstate ;
1994
2001
}
1995
2002
1996
2003
int
@@ -2003,8 +2010,11 @@ _Py_Finalize(_PyRuntimeState *runtime, struct pyfinalize_args *args)
2003
2010
return status ;
2004
2011
}
2005
2012
2006
- /* Get final thread state pointer. */
2013
+ /* Get/attach the final thread state pointer. */
2007
2014
PyThreadState * tstate = resolve_final_tstate (runtime , args );
2015
+ if (tstate != _PyThreadState_GET ()) {
2016
+ (void )PyThreadState_Swap (tstate );
2017
+ }
2008
2018
2009
2019
// Block some operations.
2010
2020
tstate -> interp -> finalizing = 1 ;
0 commit comments