@@ -1474,6 +1474,15 @@ free_threadstate(_PyThreadStateImpl *tstate)
1474
1474
}
1475
1475
}
1476
1476
1477
+ static void
1478
+ decref_threadstate (_PyThreadStateImpl * tstate )
1479
+ {
1480
+ if (_Py_atomic_add_ssize (& tstate -> refcount , -1 ) == 1 ) {
1481
+ // The last reference to the thread state is gone.
1482
+ free_threadstate (tstate );
1483
+ }
1484
+ }
1485
+
1477
1486
/* Get the thread state to a minimal consistent state.
1478
1487
Further init happens in pylifecycle.c before it can be used.
1479
1488
All fields not initialized here are expected to be zeroed out,
@@ -1938,8 +1947,12 @@ _PyThreadState_RemoveExcept(PyThreadState *tstate)
1938
1947
// Deletes the thread states in the linked list `list`.
1939
1948
//
1940
1949
// This is intended to be used in conjunction with _PyThreadState_RemoveExcept.
1950
+ //
1951
+ // If `is_after_fork` is true, the thread states are immediately freed.
1952
+ // Otherwise, they are decref'd because they may still be referenced by an
1953
+ // OS thread.
1941
1954
void
1942
- _PyThreadState_DeleteList (PyThreadState * list )
1955
+ _PyThreadState_DeleteList (PyThreadState * list , int is_after_fork )
1943
1956
{
1944
1957
// The world can't be stopped because we PyThreadState_Clear() can
1945
1958
// call destructors.
@@ -1949,7 +1962,12 @@ _PyThreadState_DeleteList(PyThreadState *list)
1949
1962
for (p = list ; p ; p = next ) {
1950
1963
next = p -> next ;
1951
1964
PyThreadState_Clear (p );
1952
- free_threadstate ((_PyThreadStateImpl * )p );
1965
+ if (is_after_fork ) {
1966
+ free_threadstate ((_PyThreadStateImpl * )p );
1967
+ }
1968
+ else {
1969
+ decref_threadstate ((_PyThreadStateImpl * )p );
1970
+ }
1953
1971
}
1954
1972
}
1955
1973
@@ -2082,12 +2100,19 @@ static void
2082
2100
tstate_wait_attach (PyThreadState * tstate )
2083
2101
{
2084
2102
do {
2085
- int expected = _Py_THREAD_SUSPENDED ;
2086
-
2087
- // Wait until we're switched out of SUSPENDED to DETACHED.
2088
- _PyParkingLot_Park (& tstate -> state , & expected , sizeof (tstate -> state ),
2089
- /*timeout=*/ -1 , NULL , /*detach=*/ 0 );
2090
-
2103
+ int state = _Py_atomic_load_int_relaxed (& tstate -> state );
2104
+ if (state == _Py_THREAD_SUSPENDED ) {
2105
+ // Wait until we're switched out of SUSPENDED to DETACHED.
2106
+ _PyParkingLot_Park (& tstate -> state , & state , sizeof (tstate -> state ),
2107
+ /*timeout=*/ -1 , NULL , /*detach=*/ 0 );
2108
+ }
2109
+ else if (state == _Py_THREAD_SHUTTING_DOWN ) {
2110
+ // We're shutting down, so we can't attach.
2111
+ _PyThreadState_HangThread (tstate );
2112
+ }
2113
+ else {
2114
+ assert (state == _Py_THREAD_DETACHED );
2115
+ }
2091
2116
// Once we're back in DETACHED we can re-attach
2092
2117
} while (!tstate_try_attach (tstate ));
2093
2118
}
@@ -2118,7 +2143,7 @@ _PyThreadState_Attach(PyThreadState *tstate)
2118
2143
tstate_activate (tstate );
2119
2144
2120
2145
#ifdef Py_GIL_DISABLED
2121
- if (_PyEval_IsGILEnabled (tstate ) && !tstate -> _status . holds_gil ) {
2146
+ if (_PyEval_IsGILEnabled (tstate ) && !tstate -> holds_gil ) {
2122
2147
// The GIL was enabled between our call to _PyEval_AcquireLock()
2123
2148
// and when we attached (the GIL can't go from enabled to disabled
2124
2149
// here because only a thread holding the GIL can disable
@@ -2201,6 +2226,15 @@ _PyThreadState_Suspend(PyThreadState *tstate)
2201
2226
HEAD_UNLOCK (runtime );
2202
2227
}
2203
2228
2229
+ void
2230
+ _PyThreadState_SetShuttingDown (PyThreadState * tstate )
2231
+ {
2232
+ _Py_atomic_store_int (& tstate -> state , _Py_THREAD_SHUTTING_DOWN );
2233
+ #ifdef Py_GIL_DISABLED
2234
+ _PyParkingLot_UnparkAll (& tstate -> state );
2235
+ #endif
2236
+ }
2237
+
2204
2238
// Decrease stop-the-world counter of remaining number of threads that need to
2205
2239
// pause. If we are the final thread to pause, notify the requesting thread.
2206
2240
static void
@@ -3001,43 +3035,27 @@ _PyThreadState_CheckConsistency(PyThreadState *tstate)
3001
3035
#endif
3002
3036
3003
3037
3004
- // Check if a Python thread must exit immediately, rather than taking the GIL
3005
- // if Py_Finalize() has been called.
3038
+ // Check if a Python thread must call _PyThreadState_HangThread(), rather than
3039
+ // taking the GIL or attaching to the interpreter if Py_Finalize() has been
3040
+ // called.
3006
3041
//
3007
3042
// When this function is called by a daemon thread after Py_Finalize() has been
3008
- // called, the GIL does no longer exist.
3009
- //
3010
- // tstate can be a dangling pointer (point to freed memory): only tstate value
3011
- // is used, the pointer is not deferenced.
3043
+ // called, the GIL may no longer exist.
3012
3044
//
3013
3045
// tstate must be non-NULL.
3014
3046
int
3015
3047
_PyThreadState_MustExit (PyThreadState * tstate )
3016
3048
{
3017
- /* bpo-39877: Access _PyRuntime directly rather than using
3018
- tstate->interp->runtime to support calls from Python daemon threads.
3019
- After Py_Finalize() has been called, tstate can be a dangling pointer:
3020
- point to PyThreadState freed memory. */
3021
- unsigned long finalizing_id = _PyRuntimeState_GetFinalizingID (& _PyRuntime );
3022
- PyThreadState * finalizing = _PyRuntimeState_GetFinalizing (& _PyRuntime );
3023
- if (finalizing == NULL ) {
3024
- // XXX This isn't completely safe from daemon thraeds,
3025
- // since tstate might be a dangling pointer.
3026
- finalizing = _PyInterpreterState_GetFinalizing (tstate -> interp );
3027
- finalizing_id = _PyInterpreterState_GetFinalizingID (tstate -> interp );
3028
- }
3029
- // XXX else check &_PyRuntime._main_interpreter._initial_thread
3030
- if (finalizing == NULL ) {
3031
- return 0 ;
3032
- }
3033
- else if (finalizing == tstate ) {
3034
- return 0 ;
3035
- }
3036
- else if (finalizing_id == PyThread_get_thread_ident ()) {
3037
- /* gh-109793: we must have switched interpreters. */
3038
- return 0 ;
3039
- }
3040
- return 1 ;
3049
+ int state = _Py_atomic_load_int_relaxed (& tstate -> state );
3050
+ return state == _Py_THREAD_SHUTTING_DOWN ;
3051
+ }
3052
+
3053
+ void
3054
+ _PyThreadState_HangThread (PyThreadState * tstate )
3055
+ {
3056
+ _PyThreadStateImpl * tstate_impl = (_PyThreadStateImpl * )tstate ;
3057
+ decref_threadstate (tstate_impl );
3058
+ PyThread_hang_thread ();
3041
3059
}
3042
3060
3043
3061
/********************/
0 commit comments