diff options
author | Dino Viehland <dinoviehland@meta.com> | 2024-07-30 16:13:31 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-30 16:13:31 (GMT) |
commit | 11292ab93561e1759c9a992949e3ceae5447411c (patch) | |
tree | 795e8fa31aa6accbd27cca9086880c01d737f420 | |
parent | 0d6324c6b3a9f6aa25ec9228d24d9e23294afcc9 (diff) | |
download | cpython-11292ab93561e1759c9a992949e3ceae5447411c.zip cpython-11292ab93561e1759c9a992949e3ceae5447411c.tar.gz cpython-11292ab93561e1759c9a992949e3ceae5447411c.tar.bz2 |
[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
-rw-r--r-- | Misc/NEWS.d/next/Core_and_Builtins/2024-07-26-21-26-33.gh-issue-122208.z8KHsY.rst | 1 | ||||
-rw-r--r-- | Objects/dictobject.c | 19 |
2 files changed, 9 insertions, 11 deletions
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-07-26-21-26-33.gh-issue-122208.z8KHsY.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-07-26-21-26-33.gh-issue-122208.z8KHsY.rst new file mode 100644 index 0000000..e4a89d1 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-07-26-21-26-33.gh-issue-122208.z8KHsY.rst @@ -0,0 +1 @@ +Dictionary watchers now only deliver the PyDict_EVENT_ADDED event when the insertion is in a known good state to succeed. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index e9861d4..dedcd23 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1686,6 +1686,10 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp, } } + uint64_t new_version = _PyDict_NotifyEvent( + interp, PyDict_EVENT_ADDED, mp, key, value); + mp->ma_keys->dk_version = 0; + Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash); dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries); @@ -1702,6 +1706,7 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp, STORE_VALUE(ep, value); STORE_HASH(ep, hash); } + mp->ma_version_tag = new_version; STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - 1); STORE_KEYS_NENTRIES(mp->ma_keys, mp->ma_keys->dk_nentries + 1); assert(mp->ma_keys->dk_usable >= 0); @@ -1805,15 +1810,11 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp, if (ix == DKIX_EMPTY) { assert(!_PyDict_HasSplitTable(mp)); - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_ADDED, mp, key, value); /* Insert into new slot. */ - mp->ma_keys->dk_version = 0; assert(old_value == NULL); if (insert_combined_dict(interp, mp, hash, key, value) < 0) { goto Fail; } - mp->ma_version_tag = new_version; STORE_USED(mp, mp->ma_used + 1); ASSERT_CONSISTENT(mp); return 0; @@ -1854,9 +1855,6 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp, assert(mp->ma_keys == Py_EMPTY_KEYS); ASSERT_DICT_LOCKED(mp); - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_ADDED, mp, key, value); - int unicode = PyUnicode_CheckExact(key); PyDictKeysObject *newkeys = new_keys_object( interp, PyDict_LOG_MINSIZE, unicode); @@ -1865,6 +1863,9 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp, Py_DECREF(value); return -1; } + uint64_t new_version = _PyDict_NotifyEvent( + interp, PyDict_EVENT_ADDED, mp, key, value); + /* We don't decref Py_EMPTY_KEYS here because it is immortal. */ assert(mp->ma_values == NULL); @@ -4264,9 +4265,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu if (ix == DKIX_EMPTY) { assert(!_PyDict_HasSplitTable(mp)); - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_ADDED, mp, key, default_value); - mp->ma_keys->dk_version = 0; value = default_value; 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 MAINTAIN_TRACKING(mp, key, value); STORE_USED(mp, mp->ma_used + 1); - mp->ma_version_tag = new_version; assert(mp->ma_keys->dk_usable >= 0); ASSERT_CONSISTENT(mp); if (result) { |