Skip to content

Commit 1692854

Browse files
gh-149816: fix dict.clear() race on split-table dict with non-embedded values (#149914)
1 parent 14af19e commit 1692854

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

Lib/test/test_free_threading/test_dict.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,34 @@ def watcher():
268268
finally:
269269
_testcapi.clear_dict_watcher(wid)
270270

271+
def test_racing_split_dict_clear_and_lookup(self):
272+
class C:
273+
pass
274+
275+
keys = [f"a{i}" for i in range(16)]
276+
277+
def make_split_nonembedded():
278+
inst = C()
279+
for key in keys:
280+
setattr(inst, key, keys.index(key))
281+
# dict.copy() of a split instance dict yields a split table
282+
# with non-embedded values
283+
return inst.__dict__.copy()
284+
285+
d = make_split_nonembedded()
286+
287+
def clearer():
288+
for _ in range(1000):
289+
d.clear()
290+
d.update(make_split_nonembedded())
291+
292+
def reader():
293+
for _ in range(1000):
294+
for k in keys:
295+
d.get(k)
296+
297+
threading_helper.run_concurrently([clearer, reader, reader])
298+
271299
def test_racing_dict_update_and_method_lookup(self):
272300
# gh-144295: test race between dict modifications and method lookups.
273301
# Uses BytesIO because the race requires a type without Py_TPFLAGS_INLINE_VALUES

Objects/dictobject.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,10 +3083,12 @@ clear_lock_held(PyObject *op)
30833083
set_keys(mp, Py_EMPTY_KEYS);
30843084
n = oldkeys->dk_nentries;
30853085
for (i = 0; i < n; i++) {
3086-
Py_CLEAR(oldvalues->values[i]);
3086+
PyObject *tmp = oldvalues->values[i];
3087+
FT_ATOMIC_STORE_PTR_RELEASE(oldvalues->values[i], NULL);
3088+
Py_XDECREF(tmp);
30873089
}
30883090
free_values(oldvalues, IS_DICT_SHARED(mp));
3089-
dictkeys_decref(oldkeys, false);
3091+
dictkeys_decref(oldkeys, IS_DICT_SHARED(mp));
30903092
}
30913093
ASSERT_CONSISTENT(mp);
30923094
}

0 commit comments

Comments
 (0)