summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-05-29 19:47:47 (GMT)
committerGitHub <noreply@github.com>2024-05-29 19:47:47 (GMT)
commitdcfbd3be9f1e0ba7aa32214e8f5f7f2ea4375a28 (patch)
treec18442ddd58bc4e2b883e7a52343be4abb55f47c /Objects
parent40a024c9835cddd85f14bab4b1e8f6545a621208 (diff)
downloadcpython-dcfbd3be9f1e0ba7aa32214e8f5f7f2ea4375a28.zip
cpython-dcfbd3be9f1e0ba7aa32214e8f5f7f2ea4375a28.tar.gz
cpython-dcfbd3be9f1e0ba7aa32214e8f5f7f2ea4375a28.tar.bz2
[3.13] gh-119525: Fix deadlock with `_PyType_Lookup` and the GIL (GH-119527) (#119746)
The deadlock only affected the free-threaded build and only occurred when the GIL was enabled at runtime. The `Py_DECREF(old_name)` call might temporarily release the GIL while holding the type seqlock. Another thread may spin trying to acquire the seqlock while holding the GIL. The deadlock occurred roughly 1 in ~1,000 runs of `pool_in_threads.py` from `test_multiprocessing_pool_circular_import`. (cherry picked from commit c22323cd1c200ca1b22c47af95f67c4b2d661fe7) Co-authored-by: Sam Gross <colesbury@gmail.com>
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index f588992..14c43a7 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -5062,7 +5062,7 @@ is_dunder_name(PyObject *name)
return 0;
}
-static void
+static PyObject *
update_cache(struct type_cache_entry *entry, PyObject *name, unsigned int version_tag, PyObject *value)
{
_Py_atomic_store_uint32_relaxed(&entry->version, version_tag);
@@ -5073,7 +5073,7 @@ update_cache(struct type_cache_entry *entry, PyObject *name, unsigned int versio
// exact unicode object or Py_None so it's safe to do so.
PyObject *old_name = entry->name;
_Py_atomic_store_ptr_relaxed(&entry->name, Py_NewRef(name));
- Py_DECREF(old_name);
+ return old_name;
}
#if Py_GIL_DISABLED
@@ -5093,10 +5093,12 @@ update_cache_gil_disabled(struct type_cache_entry *entry, PyObject *name,
return;
}
- update_cache(entry, name, version_tag, value);
+ PyObject *old_value = update_cache(entry, name, version_tag, value);
// Then update sequence to the next valid value
_PySeqLock_UnlockWrite(&entry->sequence);
+
+ Py_DECREF(old_value);
}
#endif
@@ -5208,7 +5210,8 @@ _PyType_LookupRef(PyTypeObject *type, PyObject *name)
#if Py_GIL_DISABLED
update_cache_gil_disabled(entry, name, version, res);
#else
- update_cache(entry, name, version, res);
+ PyObject *old_value = update_cache(entry, name, version, res);
+ Py_DECREF(old_value);
#endif
}
return res;