Skip to content

Commit b6c62c7

Browse files
authored
gh-117657: Fix data races in the method cache in free-threaded builds (#117954)
Fix data races in the method cache in free-threaded builds These are technically data races, but I think they're benign (to the extent that that is actually possible). We update cache entries non-atomically but read them atomically from another thread, and there's nothing that establishes a happens-before relationship between the reads and writes that I can see.
1 parent deaecb8 commit b6c62c7

File tree

2 files changed

+5
-4
lines changed

2 files changed

+5
-4
lines changed

Objects/typeobject.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -4974,13 +4974,15 @@ is_dunder_name(PyObject *name)
49744974
static void
49754975
update_cache(struct type_cache_entry *entry, PyObject *name, unsigned int version_tag, PyObject *value)
49764976
{
4977-
entry->version = version_tag;
4978-
entry->value = value; /* borrowed */
4977+
_Py_atomic_store_uint32_relaxed(&entry->version, version_tag);
4978+
_Py_atomic_store_ptr_relaxed(&entry->value, value); /* borrowed */
49794979
assert(_PyASCIIObject_CAST(name)->hash != -1);
49804980
OBJECT_STAT_INC_COND(type_cache_collisions, entry->name != Py_None && entry->name != name);
49814981
// We're releasing this under the lock for simplicity sake because it's always a
49824982
// exact unicode object or Py_None so it's safe to do so.
4983-
Py_SETREF(entry->name, Py_NewRef(name));
4983+
PyObject *old_name = entry->name;
4984+
_Py_atomic_store_ptr_relaxed(&entry->name, Py_NewRef(name));
4985+
Py_DECREF(old_name);
49844986
}
49854987

49864988
#if Py_GIL_DISABLED

Tools/tsan/suppressions_free_threading.txt

-1
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,4 @@ race:set_inheritable
4747
race:start_the_world
4848
race:tstate_set_detached
4949
race:unicode_hash
50-
race:update_cache
5150
race:update_cache_gil_disabled

0 commit comments

Comments
 (0)