Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
Description
Bug report
Bug description:
First of all, I'm not a threading expert and my understanding of the memory-ordering model may be wrong. So, if I'm wrong I will be happy to fix my knowledge lacoons.
I saw some inconsistency (from my sight) of loading and writing of managed dict pointer.
Non-atomic loads:
PyObject_VisitManagedDict
Line 7202 in9ad0c7b
Py_VISIT(_PyObject_ManagedDictPointer(obj)->dict); PyObject_ClearManagedDict
Line 7462 in9ad0c7b
Py_CLEAR(_PyObject_ManagedDictPointer(obj)->dict); _PyObject_GetDictPtr
Line 1541 in9ad0c7b
return (PyObject**)&_PyObject_ManagedDictPointer(obj)->dict;
Non-atomic stores:
_PyObject_InitInlineValues
Lines 6787 to 6791 in9ad0c7b
for (size_ti=0;i<size;i++) { values->values[i]=NULL; } _PyObject_ManagedDictPointer(obj)->dict=NULL; }
IIUC mixing of non-atomic loads/stores with atomic ones may lead to data races.
memory_order_acquire
loads:
_PyObject_GetManagedDict
cpython/Include/internal/pycore_object.h
Lines 932 to 936 in9ad0c7b
_PyObject_GetManagedDict(PyObject*obj) { PyManagedDictPointer*dorv=_PyObject_ManagedDictPointer(obj); return (PyDictObject*)FT_ATOMIC_LOAD_PTR_ACQUIRE(dorv->dict); }
memory_order_release
stores:
_PyObject_MaterializeManagedDict_LockHeld
Lines 6827 to 6829 in9ad0c7b
FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict, dict); returndict; store_instance_attr_lock_held
Lines 6925 to 6927 in9ad0c7b
FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict, (PyDictObject*)dict); return0; ensure_managed_dict
Lines 7494 to 7495 in9ad0c7b
FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict, (PyDictObject*)dict);
memory_order_seq_cst
stores:
set_dict_inline_values
Line 7225 in9ad0c7b
FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict,new_dict); try_set_dict_inline_only_or_other_dict
Lines 7252 to 7253 in9ad0c7b
FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict, (PyDictObject*)Py_XNewRef(new_dict)); replace_dict_probably_inline_materialized
Lines 7287 to 7289 in9ad0c7b
FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict, (PyDictObject*)Py_XNewRef(new_dict)); return0;
IIUC mixing acquire/release with seq_cst may break total order of seq_cst operations.
Mixing withmemory_order_seq_cst
stores
_PyObject_SetManagedDict
Lines 7356 to 7365 in9ad0c7b
PyDictObject*dict=_PyObject_GetManagedDict(obj); if (dict==NULL) { set_dict_inline_values(obj, (PyDictObject*)new_dict); return0; } if (_PyDict_DetachFromObject(dict,obj)==0) { _PyObject_ManagedDictPointer(obj)->dict= (PyDictObject*)Py_XNewRef(new_dict); Py_DECREF(dict); return0; }
_PyObject_SetManagedDict
uses non-atomic load but stores withseq_cst
mode so it is OK (IIUC), but following store without fence may lead to data race.
Are my findings valid or am I completely wrong?
CPython versions tested on:
CPython main branch
Operating systems tested on:
No response