Skip to content

Commit f0d16f7

Browse files
[3.13] gh-117657: Fix TSAN races in setobject.c (GH-121511) (#121541)
The `used` field must be written using atomic stores because `set_len` and iterators may access the field concurrently without holding the per-object lock. (cherry picked from commit 9c08f40) Co-authored-by: Sam Gross <colesbury@gmail.com>
1 parent 8d473d8 commit f0d16f7

File tree

2 files changed

+10
-11
lines changed

2 files changed

+10
-11
lines changed

Objects/setobject.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,14 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
184184
found_unused_or_dummy:
185185
if (freeslot == NULL)
186186
goto found_unused;
187-
so->used++;
187+
FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
188188
freeslot->key = key;
189189
freeslot->hash = hash;
190190
return 0;
191191

192192
found_unused:
193193
so->fill++;
194-
so->used++;
194+
FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
195195
entry->key = key;
196196
entry->hash = hash;
197197
if ((size_t)so->fill*5 < mask*3)
@@ -357,7 +357,7 @@ set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
357357
old_key = entry->key;
358358
entry->key = dummy;
359359
entry->hash = -1;
360-
so->used--;
360+
FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
361361
Py_DECREF(old_key);
362362
return DISCARD_FOUND;
363363
}
@@ -397,7 +397,7 @@ set_empty_to_minsize(PySetObject *so)
397397
{
398398
memset(so->smalltable, 0, sizeof(so->smalltable));
399399
so->fill = 0;
400-
so->used = 0;
400+
FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
401401
so->mask = PySet_MINSIZE - 1;
402402
so->table = so->smalltable;
403403
so->hash = -1;
@@ -615,7 +615,7 @@ set_merge_lock_held(PySetObject *so, PyObject *otherset)
615615
}
616616
}
617617
so->fill = other->fill;
618-
so->used = other->used;
618+
FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
619619
return 0;
620620
}
621621

@@ -624,7 +624,7 @@ set_merge_lock_held(PySetObject *so, PyObject *otherset)
624624
setentry *newtable = so->table;
625625
size_t newmask = (size_t)so->mask;
626626
so->fill = other->used;
627-
so->used = other->used;
627+
FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
628628
for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
629629
key = other_entry->key;
630630
if (key != NULL && key != dummy) {
@@ -678,7 +678,7 @@ set_pop_impl(PySetObject *so)
678678
key = entry->key;
679679
entry->key = dummy;
680680
entry->hash = -1;
681-
so->used--;
681+
FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
682682
so->finger = entry - so->table + 1; /* next place to start */
683683
return key;
684684
}
@@ -1173,7 +1173,9 @@ set_swap_bodies(PySetObject *a, PySetObject *b)
11731173
Py_hash_t h;
11741174

11751175
t = a->fill; a->fill = b->fill; b->fill = t;
1176-
t = a->used; a->used = b->used; b->used = t;
1176+
t = a->used;
1177+
FT_ATOMIC_STORE_SSIZE_RELAXED(a->used, b->used);
1178+
FT_ATOMIC_STORE_SSIZE_RELAXED(b->used, t);
11771179
t = a->mask; a->mask = b->mask; b->mask = t;
11781180

11791181
u = a->table;

Tools/tsan/suppressions_free_threading.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ race_top:assign_version_tag
3030
race_top:insertdict
3131
race_top:lookup_tp_dict
3232
race_top:new_reference
33-
# https://gist.github.com/colesbury/d13d033f413b4ad07929d044bed86c35
34-
race_top:set_discard_entry
3533
race_top:_PyDict_CheckConsistency
3634
race_top:_Py_dict_lookup_threadsafe
3735
race_top:_multiprocessing_SemLock_acquire_impl
@@ -41,7 +39,6 @@ race_top:insert_to_emptydict
4139
race_top:insertdict
4240
race_top:list_get_item_ref
4341
race_top:make_pending_calls
44-
race_top:set_add_entry
4542
race_top:_Py_slot_tp_getattr_hook
4643
race_top:add_threadstate
4744
race_top:dump_traceback

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy