summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-05-24-21-04-00.gh-issue-119525.zLFLf1.rst2
-rw-r--r--Objects/typeobject.c11
2 files changed, 9 insertions, 4 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-24-21-04-00.gh-issue-119525.zLFLf1.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-24-21-04-00.gh-issue-119525.zLFLf1.rst
new file mode 100644
index 0000000..83c29a1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-05-24-21-04-00.gh-issue-119525.zLFLf1.rst
@@ -0,0 +1,2 @@
+Fix deadlock involving ``_PyType_Lookup()`` cache in the free-threaded build
+when the GIL is dynamically enabled at runtime.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 9d849d8..290306c 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -5169,7 +5169,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);
@@ -5180,7 +5180,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
@@ -5200,10 +5200,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
@@ -5315,7 +5317,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;