Skip to content

Commit c8f5ca6

Browse files
authored
[3.12] gh-122208: Don't delivery PyDict_EVENT_ADDED until it can't fail (#122327)
Don't delivery PyDict_EVENT_ADDED until it can't fail
1 parent ca22750 commit c8f5ca6

File tree

2 files changed

+12
-10
lines changed

2 files changed

+12
-10
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

+11-10
Original file line numberDiff line numberDiff line change
@@ -1251,17 +1251,18 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
12511251
MAINTAIN_TRACKING(mp, key, value);
12521252

12531253
if (ix == DKIX_EMPTY) {
1254-
uint64_t new_version = _PyDict_NotifyEvent(
1255-
interp, PyDict_EVENT_ADDED, mp, key, value);
1256-
/* Insert into new slot. */
1257-
mp->ma_keys->dk_version = 0;
12581254
assert(old_value == NULL);
12591255
if (mp->ma_keys->dk_usable <= 0) {
12601256
/* Need to resize. */
12611257
if (insertion_resize(interp, mp, 1) < 0)
12621258
goto Fail;
12631259
}
12641260

1261+
uint64_t new_version = _PyDict_NotifyEvent(
1262+
interp, PyDict_EVENT_ADDED, mp, key, value);
1263+
/* Insert into new slot. */
1264+
mp->ma_keys->dk_version = 0;
1265+
12651266
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
12661267
dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
12671268

@@ -1335,9 +1336,6 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
13351336
{
13361337
assert(mp->ma_keys == Py_EMPTY_KEYS);
13371338

1338-
uint64_t new_version = _PyDict_NotifyEvent(
1339-
interp, PyDict_EVENT_ADDED, mp, key, value);
1340-
13411339
int unicode = PyUnicode_CheckExact(key);
13421340
PyDictKeysObject *newkeys = new_keys_object(
13431341
interp, PyDict_LOG_MINSIZE, unicode);
@@ -1346,6 +1344,9 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
13461344
Py_DECREF(value);
13471345
return -1;
13481346
}
1347+
uint64_t new_version = _PyDict_NotifyEvent(
1348+
interp, PyDict_EVENT_ADDED, mp, key, value);
1349+
13491350
/* We don't decref Py_EMPTY_KEYS here because it is immortal. */
13501351
mp->ma_keys = newkeys;
13511352
mp->ma_values = NULL;
@@ -3324,15 +3325,15 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
33243325
return NULL;
33253326

33263327
if (ix == DKIX_EMPTY) {
3327-
uint64_t new_version = _PyDict_NotifyEvent(
3328-
interp, PyDict_EVENT_ADDED, mp, key, defaultobj);
3329-
mp->ma_keys->dk_version = 0;
33303328
value = defaultobj;
33313329
if (mp->ma_keys->dk_usable <= 0) {
33323330
if (insertion_resize(interp, mp, 1) < 0) {
33333331
return NULL;
33343332
}
33353333
}
3334+
uint64_t new_version = _PyDict_NotifyEvent(
3335+
interp, PyDict_EVENT_ADDED, mp, key, defaultobj);
3336+
mp->ma_keys->dk_version = 0;
33363337
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
33373338
dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
33383339
if (DK_IS_UNICODE(mp->ma_keys)) {

0 commit comments

Comments
 (0)