[3.11] GH-100892: Fix race in clearing threading.local (GH-100922). (#100937)

(cherry picked from commit 762745a124)

Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
This commit is contained in:
Kumar Aditya 2023-01-11 21:01:48 +05:30 committed by GitHub
parent 1b2459dc64
commit e707671684
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 19 deletions

View file

@ -839,6 +839,11 @@ local_traverse(localobject *self, visitproc visit, void *arg)
return 0;
}
#define HEAD_LOCK(runtime) \
PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)
#define HEAD_UNLOCK(runtime) \
PyThread_release_lock((runtime)->interpreters.mutex)
static int
local_clear(localobject *self)
{
@ -849,18 +854,23 @@ local_clear(localobject *self)
/* Remove all strong references to dummies from the thread states */
if (self->key) {
PyInterpreterState *interp = _PyInterpreterState_GET();
_PyRuntimeState *runtime = &_PyRuntime;
HEAD_LOCK(runtime);
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
for(; tstate; tstate = PyThreadState_Next(tstate)) {
if (tstate->dict == NULL) {
continue;
}
PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
if (v != NULL) {
Py_DECREF(v);
}
else {
PyErr_Clear();
HEAD_UNLOCK(runtime);
while (tstate) {
if (tstate->dict) {
PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
if (v != NULL) {
Py_DECREF(v);
}
else {
PyErr_Clear();
}
}
HEAD_LOCK(runtime);
tstate = PyThreadState_Next(tstate);
HEAD_UNLOCK(runtime);
}
}
return 0;