Skip to content

Commit

Permalink
gh-115103: Fix unregistering of QSBR state (#116480)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
colesbury authored Mar 8, 2024
1 parent 7cee276 commit cca3023
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions Python/qsbr.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,17 @@ _Py_qsbr_register(_PyThreadStateImpl *tstate, PyInterpreterState *interp,
void
_Py_qsbr_unregister(_PyThreadStateImpl *tstate)
{
struct _qsbr_shared *shared = tstate->qsbr->shared;

PyMutex_Lock(&shared->mutex);
// NOTE: we must load (or reload) the thread state's qbsr inside the mutex
// because the array may have been resized (changing tstate->qsbr) while
// we waited to acquire the mutex.
struct _qsbr_thread_state *qsbr = tstate->qsbr;
struct _qsbr_shared *shared = qsbr->shared;

assert(qsbr->seq == 0 && "thread state must be detached");

PyMutex_Lock(&shared->mutex);
assert(qsbr->allocated && qsbr->tstate == (PyThreadState *)tstate);

tstate->qsbr = NULL;
qsbr->tstate = NULL;
qsbr->allocated = false;
Expand Down

0 comments on commit cca3023

Please sign in to comment.