Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 33d2019

Browse filesBrowse files
authored
gh-117657: Fix QSBR race condition (#118843)
`_Py_qsbr_unregister` is called when the PyThreadState is already detached, so the access to `tstate->qsbr` isn't safe without locking the shared mutex. Grab the `struct _qsbr_shared` from the interpreter instead.
1 parent 22d5185 commit 33d2019
Copy full SHA for 33d2019

File tree

4 files changed

+8
-8
lines changed
Filter options

4 files changed

+8
-8
lines changed

‎Include/internal/pycore_qsbr.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_qsbr.h
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ _Py_qsbr_register(struct _PyThreadStateImpl *tstate,
140140

141141
// Disassociates a PyThreadState from the QSBR state and frees the QSBR state.
142142
extern void
143-
_Py_qsbr_unregister(struct _PyThreadStateImpl *tstate);
143+
_Py_qsbr_unregister(PyThreadState *tstate);
144144

145145
extern void
146146
_Py_qsbr_fini(PyInterpreterState *interp);

‎Python/pystate.c

Copy file name to clipboardExpand all lines: Python/pystate.c
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1794,7 +1794,7 @@ tstate_delete_common(PyThreadState *tstate)
17941794
HEAD_UNLOCK(runtime);
17951795

17961796
#ifdef Py_GIL_DISABLED
1797-
_Py_qsbr_unregister((_PyThreadStateImpl *)tstate);
1797+
_Py_qsbr_unregister(tstate);
17981798
#endif
17991799

18001800
// XXX Unbind in PyThreadState_Clear(), or earlier

‎Python/qsbr.c

Copy file name to clipboardExpand all lines: Python/qsbr.c
+6-5Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,20 +231,21 @@ _Py_qsbr_register(_PyThreadStateImpl *tstate, PyInterpreterState *interp,
231231
}
232232

233233
void
234-
_Py_qsbr_unregister(_PyThreadStateImpl *tstate)
234+
_Py_qsbr_unregister(PyThreadState *tstate)
235235
{
236-
struct _qsbr_shared *shared = tstate->qsbr->shared;
236+
struct _qsbr_shared *shared = &tstate->interp->qsbr;
237+
struct _PyThreadStateImpl *tstate_imp = (_PyThreadStateImpl*) tstate;
237238

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

244245
assert(qsbr->seq == 0 && "thread state must be detached");
245-
assert(qsbr->allocated && qsbr->tstate == (PyThreadState *)tstate);
246+
assert(qsbr->allocated && qsbr->tstate == tstate);
246247

247-
tstate->qsbr = NULL;
248+
tstate_imp->qsbr = NULL;
248249
qsbr->tstate = NULL;
249250
qsbr->allocated = false;
250251
qsbr->freelist_next = shared->freelist;

‎Tools/tsan/suppressions_free_threading.txt

Copy file name to clipboardExpand all lines: Tools/tsan/suppressions_free_threading.txt
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ race_top:_PyParkingLot_Park
3838
race_top:_PyType_HasFeature
3939
race_top:assign_version_tag
4040
race_top:gc_restore_tid
41-
race_top:initialize_new_array
4241
race_top:insertdict
4342
race_top:lookup_tp_dict
4443
race_top:mi_heap_visit_pages

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.