Skip to content

Commit 5592399

Browse files
authored
gh-122208: Don't delivery PyDict_EVENT_ADDED until it can't fail (#122207)
Don't delivery PyDict_EVENT_ADDED until it can't fail
1 parent 9ac6060 commit 5592399

File tree

2 files changed

+9
-11
lines changed

2 files changed

+9
-11
lines changed
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

+8-11
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,10 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
16271627
}
16281628
}
16291629

1630+
uint64_t new_version = _PyDict_NotifyEvent(
1631+
interp, PyDict_EVENT_ADDED, mp, key, value);
1632+
mp->ma_keys->dk_version = 0;
1633+
16301634
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
16311635
dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
16321636

@@ -1643,6 +1647,7 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
16431647
STORE_VALUE(ep, value);
16441648
STORE_HASH(ep, hash);
16451649
}
1650+
mp->ma_version_tag = new_version;
16461651
STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - 1);
16471652
STORE_KEYS_NENTRIES(mp->ma_keys, mp->ma_keys->dk_nentries + 1);
16481653
assert(mp->ma_keys->dk_usable >= 0);
@@ -1746,15 +1751,11 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
17461751

17471752
if (ix == DKIX_EMPTY) {
17481753
assert(!_PyDict_HasSplitTable(mp));
1749-
uint64_t new_version = _PyDict_NotifyEvent(
1750-
interp, PyDict_EVENT_ADDED, mp, key, value);
17511754
/* Insert into new slot. */
1752-
mp->ma_keys->dk_version = 0;
17531755
assert(old_value == NULL);
17541756
if (insert_combined_dict(interp, mp, hash, key, value) < 0) {
17551757
goto Fail;
17561758
}
1757-
mp->ma_version_tag = new_version;
17581759
STORE_USED(mp, mp->ma_used + 1);
17591760
ASSERT_CONSISTENT(mp);
17601761
return 0;
@@ -1795,9 +1796,6 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
17951796
assert(mp->ma_keys == Py_EMPTY_KEYS);
17961797
ASSERT_DICT_LOCKED(mp);
17971798

1798-
uint64_t new_version = _PyDict_NotifyEvent(
1799-
interp, PyDict_EVENT_ADDED, mp, key, value);
1800-
18011799
int unicode = PyUnicode_CheckExact(key);
18021800
PyDictKeysObject *newkeys = new_keys_object(
18031801
interp, PyDict_LOG_MINSIZE, unicode);
@@ -1806,6 +1804,9 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
18061804
Py_DECREF(value);
18071805
return -1;
18081806
}
1807+
uint64_t new_version = _PyDict_NotifyEvent(
1808+
interp, PyDict_EVENT_ADDED, mp, key, value);
1809+
18091810
/* We don't decref Py_EMPTY_KEYS here because it is immortal. */
18101811
assert(mp->ma_values == NULL);
18111812

@@ -4199,9 +4200,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
41994200

42004201
if (ix == DKIX_EMPTY) {
42014202
assert(!_PyDict_HasSplitTable(mp));
4202-
uint64_t new_version = _PyDict_NotifyEvent(
4203-
interp, PyDict_EVENT_ADDED, mp, key, default_value);
4204-
mp->ma_keys->dk_version = 0;
42054203
value = default_value;
42064204

42074205
if (insert_combined_dict(interp, mp, hash, Py_NewRef(key), Py_NewRef(value)) < 0) {
@@ -4214,7 +4212,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
42144212

42154213
MAINTAIN_TRACKING(mp, key, value);
42164214
STORE_USED(mp, mp->ma_used + 1);
4217-
mp->ma_version_tag = new_version;
42184215
assert(mp->ma_keys->dk_usable >= 0);
42194216
ASSERT_CONSISTENT(mp);
42204217
if (result) {

0 commit comments

Comments
 (0)