https://github.com/python/cpython/commit/ef498e03366065319d57c1ce65e1d7bdcefbb498
commit: ef498e03366065319d57c1ce65e1d7bdcefbb498
branch: 3.15
author: Neil Schemenauer <[email protected]>
committer: nascheme <[email protected]>
date: 2026-10-13T12:43:19-07:00
summary:

[3.15] Fix _PyThreadState_ResumeDetached() assertion with attach waiters 
(GH-159372)

Make _PyThreadState_ResumeDetached() waiter-aware and use it from
start_the_world(), matching main branch.  Remove tstate_resume().

files:
M Include/internal/pycore_pystate.h
M Python/pystate.c

diff --git a/Include/internal/pycore_pystate.h 
b/Include/internal/pycore_pystate.h
index 78dc64b645e8c0..16edeccb7224be 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -161,8 +161,9 @@ extern void _PyThreadState_Suspend(PyThreadState *tstate);
 // Returns 1 on success, 0 if the thread was not in the "detached" state.
 extern int _PyThreadState_TrySuspendDetached(PyThreadState *tstate);
 
-// Undo a successful _PyThreadState_TrySuspendDetached(): switch the thread
-// back to "detached" and wake it if it is waiting to attach.
+// Resume a thread suspended by _PyThreadState_TrySuspendDetached() or a
+// stop-the-world pause: switch it back to "detached" or "detached-waiting"
+// and wake it if it is waiting to attach.
 extern void _PyThreadState_ResumeDetached(PyThreadState *tstate);
 #endif
 
diff --git a/Python/pystate.c b/Python/pystate.c
index 19cf1e8dfa6b14..3a748597d9cd17 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -2401,10 +2401,24 @@ void
 _PyThreadState_ResumeDetached(PyThreadState *tstate)
 {
     assert(tstate != _PyThreadState_GET());
-    assert(_Py_atomic_load_int_relaxed(&tstate->state) == 
_Py_THREAD_SUSPENDED);
-    _Py_atomic_store_int(&tstate->state, _Py_THREAD_DETACHED);
+    int state = _Py_atomic_load_int_relaxed(&tstate->state);
+    int next_state;
+    do {
+        assert(state == _Py_THREAD_SUSPENDED ||
+               state == _Py_THREAD_SUSPENDED_WAITING);
+        if (state == _Py_THREAD_SUSPENDED_WAITING) {
+            next_state = _Py_THREAD_DETACHED_WAITING;
+        }
+        else {
+            next_state = _Py_THREAD_DETACHED;
+        }
+        // Retry if an attach waiter registered concurrently.
+    } while (!_Py_atomic_compare_exchange_int(
+                &tstate->state, &state, next_state));
     // Wake the thread if it is parked in tstate_wait_attach().
-    _PyParkingLot_UnparkAll(&tstate->state);
+    if (state == _Py_THREAD_SUSPENDED_WAITING) {
+        _PyParkingLot_UnparkAll(&tstate->state);
+    }
 }
 #endif
 
@@ -2526,30 +2540,6 @@ stop_the_world(struct _stoptheworld_state *stw)
     stw->world_stopped = 1;
 }
 
-static void
-tstate_resume(PyThreadState *tstate)
-{
-    assert(tstate != _PyThreadState_GET());
-    int state = _Py_atomic_load_int_relaxed(&tstate->state);
-    int next_state;
-    do {
-        assert(state == _Py_THREAD_SUSPENDED ||
-               state == _Py_THREAD_SUSPENDED_WAITING);
-        if (state == _Py_THREAD_SUSPENDED_WAITING) {
-            next_state = _Py_THREAD_DETACHED_WAITING;
-        }
-        else {
-            next_state = _Py_THREAD_DETACHED;
-        }
-        // Retry if an attach waiter registered concurrently.
-    } while (!_Py_atomic_compare_exchange_int(
-                &tstate->state, &state, next_state));
-    // Wake the thread if it is parked in tstate_wait_attach().
-    if (state == _Py_THREAD_SUSPENDED_WAITING) {
-        _PyParkingLot_UnparkAll(&tstate->state);
-    }
-}
-
 static void
 start_the_world(struct _stoptheworld_state *stw)
 {
@@ -2563,7 +2553,7 @@ start_the_world(struct _stoptheworld_state *stw)
     _Py_FOR_EACH_STW_INTERP(stw, i) {
         _Py_FOR_EACH_TSTATE_UNLOCKED(i, t) {
             if (t != stw->requester) {
-                tstate_resume(t);
+                _PyThreadState_ResumeDetached(t);
             }
         }
     }

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to