Skip to content

Commit cca3023

Browse files
authored
gh-115103: Fix unregistering of QSBR state (#116480)
If a thread blocks while waiting on the `shared->mutex` lock, the array of QSBR states may be reallocated. The `tstate->qsbr` values before the lock is acquired may not be the same as the value after the lock is acquired.
1 parent 7cee276 commit cca3023

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

Python/qsbr.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,17 @@ _Py_qsbr_register(_PyThreadStateImpl *tstate, PyInterpreterState *interp,
233233
void
234234
_Py_qsbr_unregister(_PyThreadStateImpl *tstate)
235235
{
236+
struct _qsbr_shared *shared = tstate->qsbr->shared;
237+
238+
PyMutex_Lock(&shared->mutex);
239+
// NOTE: we must load (or reload) the thread state's qbsr inside the mutex
240+
// because the array may have been resized (changing tstate->qsbr) while
241+
// we waited to acquire the mutex.
236242
struct _qsbr_thread_state *qsbr = tstate->qsbr;
237-
struct _qsbr_shared *shared = qsbr->shared;
238243

239244
assert(qsbr->seq == 0 && "thread state must be detached");
240-
241-
PyMutex_Lock(&shared->mutex);
242245
assert(qsbr->allocated && qsbr->tstate == (PyThreadState *)tstate);
246+
243247
tstate->qsbr = NULL;
244248
qsbr->tstate = NULL;
245249
qsbr->allocated = false;

0 commit comments

Comments
 (0)