Skip to content

Commit 11292ab

Browse files
authored
[3.13] gh-122208: Don't delivery PyDict_EVENT_ADDED until it can't fail (#122326)
Don't delivery PyDict_EVENT_ADDED until it can't fail
1 parent 0d6324c commit 11292ab

File tree

2 files changed

+9
-11
lines changed

2 files changed

+9
-11
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Dictionary watchers now only deliver the PyDict_EVENT_ADDED event when the insertion is in a known good state to succeed.

Objects/dictobject.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,10 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
16861686
}
16871687
}
16881688

1689+
uint64_t new_version = _PyDict_NotifyEvent(
1690+
interp, PyDict_EVENT_ADDED, mp, key, value);
1691+
mp->ma_keys->dk_version = 0;
1692+
16891693
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
16901694
dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
16911695

@@ -1702,6 +1706,7 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
17021706
STORE_VALUE(ep, value);
17031707
STORE_HASH(ep, hash);
17041708
}
1709+
mp->ma_version_tag = new_version;
17051710
STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - 1);
17061711
STORE_KEYS_NENTRIES(mp->ma_keys, mp->ma_keys->dk_nentries + 1);
17071712
assert(mp->ma_keys->dk_usable >= 0);
@@ -1805,15 +1810,11 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
18051810

18061811
if (ix == DKIX_EMPTY) {
18071812
assert(!_PyDict_HasSplitTable(mp));
1808-
uint64_t new_version = _PyDict_NotifyEvent(
1809-
interp, PyDict_EVENT_ADDED, mp, key, value);
18101813
/* Insert into new slot. */
1811-
mp->ma_keys->dk_version = 0;
18121814
assert(old_value == NULL);
18131815
if (insert_combined_dict(interp, mp, hash, key, value) < 0) {
18141816
goto Fail;
18151817
}
1816-
mp->ma_version_tag = new_version;
18171818
STORE_USED(mp, mp->ma_used + 1);
18181819
ASSERT_CONSISTENT(mp);
18191820
return 0;
@@ -1854,9 +1855,6 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
18541855
assert(mp->ma_keys == Py_EMPTY_KEYS);
18551856
ASSERT_DICT_LOCKED(mp);
18561857

1857-
uint64_t new_version = _PyDict_NotifyEvent(
1858-
interp, PyDict_EVENT_ADDED, mp, key, value);
1859-
18601858
int unicode = PyUnicode_CheckExact(key);
18611859
PyDictKeysObject *newkeys = new_keys_object(
18621860
interp, PyDict_LOG_MINSIZE, unicode);
@@ -1865,6 +1863,9 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
18651863
Py_DECREF(value);
18661864
return -1;
18671865
}
1866+
uint64_t new_version = _PyDict_NotifyEvent(
1867+
interp, PyDict_EVENT_ADDED, mp, key, value);
1868+
18681869
/* We don't decref Py_EMPTY_KEYS here because it is immortal. */
18691870
assert(mp->ma_values == NULL);
18701871

@@ -4264,9 +4265,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
42644265

42654266
if (ix == DKIX_EMPTY) {
42664267
assert(!_PyDict_HasSplitTable(mp));
4267-
uint64_t new_version = _PyDict_NotifyEvent(
4268-
interp, PyDict_EVENT_ADDED, mp, key, default_value);
4269-
mp->ma_keys->dk_version = 0;
42704268
value = default_value;
42714269

42724270
if (insert_combined_dict(interp, mp, hash, Py_NewRef(key), Py_NewRef(value)) < 0) {
@@ -4279,7 +4277,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
42794277

42804278
MAINTAIN_TRACKING(mp, key, value);
42814279
STORE_USED(mp, mp->ma_used + 1);
4282-
mp->ma_version_tag = new_version;
42834280
assert(mp->ma_keys->dk_usable >= 0);
42844281
ASSERT_CONSISTENT(mp);
42854282
if (result) {

0 commit comments

Comments
 (0)