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

Skip to content

Commit a59ebf7

Browse files
committed
Fix race in constructing dict for instance
1 parent 5a1618a commit a59ebf7

File tree

3 files changed

+25
-24
lines changed

3 files changed

+25
-24
lines changed

Include/internal/pycore_dict.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ 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);
109108
extern int _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value);
110109
extern int _PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject **result);
111110
extern int _PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result);
111+
extern int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr, PyObject *name, PyObject *value);
112112

113113
extern int _PyDict_Pop_KnownHash(
114114
PyDictObject *dict,

Objects/dictobject.c

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7240,7 +7240,7 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
72407240
}
72417241

72427242
int
7243-
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
7243+
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr,
72447244
PyObject *key, PyObject *value)
72457245
{
72467246
PyObject *dict;
@@ -7249,39 +7249,40 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
72497249
PyInterpreterState *interp = _PyInterpreterState_GET();
72507250

72517251
assert(dictptr != NULL);
7252-
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
7253-
assert(dictptr != NULL);
7252+
dict = *dictptr;
7253+
if (dict == NULL) {
7254+
#ifdef Py_GIL_DISABLED
7255+
Py_BEGIN_CRITICAL_SECTION(obj);
72547256
dict = *dictptr;
7255-
if (dict == NULL) {
7257+
if (dict != NULL) {
7258+
goto done;
7259+
}
7260+
#endif
7261+
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
72567262
assert(!_PyType_HasFeature(tp, Py_TPFLAGS_INLINE_VALUES));
72577263
dictkeys_incref(cached);
72587264
dict = new_dict_with_shared_keys(interp, cached);
7259-
if (dict == NULL)
7260-
return -1;
7261-
*dictptr = dict;
7262-
}
7263-
if (value == NULL) {
7264-
res = PyDict_DelItem(dict, key);
7265+
if (dict == NULL) {
7266+
dictkeys_decref(interp, cached, false);
7267+
}
72657268
}
72667269
else {
7267-
res = PyDict_SetItem(dict, key, value);
7268-
}
7269-
} else {
7270-
dict = *dictptr;
7271-
if (dict == NULL) {
72727270
dict = PyDict_New();
7273-
if (dict == NULL)
7274-
return -1;
7275-
*dictptr = dict;
72767271
}
7277-
if (value == NULL) {
7278-
res = PyDict_DelItem(dict, key);
7279-
} else {
7280-
res = PyDict_SetItem(dict, key, value);
7272+
*dictptr = dict;
7273+
#ifdef Py_GIL_DISABLED
7274+
done:
7275+
Py_END_CRITICAL_SECTION();
7276+
#endif
7277+
if (dict == NULL) {
7278+
return -1;
72817279
}
72827280
}
72837281

7282+
Py_BEGIN_CRITICAL_SECTION(dict);
7283+
res = _PyDict_SetItem_LockHeld((PyDictObject *)dict, key, value);
72847284
ASSERT_CONSISTENT(dict);
7285+
Py_END_CRITICAL_SECTION();
72857286
return res;
72867287
}
72877288

Objects/object.c

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

0 commit comments

Comments
 (0)
0