8000 Fix race in constructing dict for instance · python/cpython@12d0685 · GitHub
[go: up one dir, main page]

Skip to content

Commit 12d0685

Browse files
committed
Fix race in constructing dict for instance
1 parent a37b093 commit 12d0685

File tree

3 files changed

+23
-24
lines changed

3 files changed

+23
-24
lines changed

Include/internal/pycore_dict.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObjec
105105

106106
/* Consumes references to key and value */
107107
PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value);
108-
extern int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value);
108+
extern int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr, PyObject *name, PyObject *value);
109109

110110
extern int _PyDict_Pop_KnownHash(
111111
PyDictObject *dict,

Objects/dictobject.c

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7213,7 +7213,7 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
72137213
}
72147214

72157215
int
7216-
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
7216+
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr,
72177217
PyObject *key, PyObject *value)
72187218
{
72197219
PyObject *dict;
@@ -7222,37 +7222,36 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
72227222
PyInterpreterState *interp = _PyInterpreterState_GET();
72237223

72247224
assert(dictptr != NULL);
7225-
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
7226-
assert(dictptr != NULL);
7225+
dict = *dictptr;
7226+
if (dict == NULL) {
7227+
#ifdef Py_GIL_DISABLED
7228+
Py_BEGIN_CRITICAL_SECTION(obj);
72277229
dict = *dictptr;
7228-
if (dict == NULL) {
7230+
if (dict != NULL) {
7231+
goto done;
7232+
}
7233+
#endif
7234+
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
72297235
assert(!_PyType_HasFeature(tp, Py_TPFLAGS_INLINE_VALUES));
72307236
dictkeys_incref(cached);
72317237
dict = new_dict_with_shared_keys(interp, cached);
7232-
if (dict == NULL)
7233-
return -1;
7234-
*dictptr = dict;
7235-
}
7236-
if (value == NULL) {
7237-
res = PyDict_DelItem(dict, key);
72387238
}
72397239
else {
7240-
res = PyDict_SetItem(dict, key, value);
7241-
}
7242-
} else {
7243-
dict = *dictptr;
7244-
if (dict == NULL) {
72457240
dict = PyDict_New();
7246-
if (dict == NULL)
7247-
return -1;
7248-
*dictptr = dict;
72497241
}
7250-
if (value == NULL) {
7251-
res = PyDict_DelItem(dict, key);
7252-
} else {
7253-
res = PyDict_SetItem(dict, key, value);
7242+
*dictptr = dict;
7243+
#ifdef Py_GIL_DISABLED
7244+
done:
7245+
Py_END_CRITICAL_SECTION();
7246+
#endif
7247+
if (dict == NULL) {
7248+
return -1;
72547249
}
72557250
}
7251+
7252+
Py_BEGIN_CRITICAL_SECTION(dict);
7253+
res = set_or_del_lock_held((PyDictObject *)dict, key, value);
7254+
Py_END_CRITICAL_SECTION();
72567255
ASSERT_CONSISTENT(dict);
72577256
return res;
72587257
}

Objects/object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1732,7 +1732,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
17321732
goto done;
17331733
}
17341734
else {
1735-
res = _PyObjectDict_SetItem(tp, dictptr, name, value);
1735+
res = _PyObjectDict_SetItem(tp, obj, dictptr, name, value);
17361736
}
17371737
}
17381738
else {

0 commit comments

Comments
 (0)
0