mirror of
https://github.com/python/cpython.git
synced 2026-06-28 20:00:46 +00:00
gh-151593: Fix dead lock in PyDict insert_split_key() (#152200)
Do not hold LOCK_KEYS() lock when calling PyType_Modified() to avoid a deadlock. Co-authored-by: Neil Schemenauer <nas-github@arctrix.com>
This commit is contained in:
parent
7c8163719c
commit
bef5706222
1 changed files with 18 additions and 1 deletions
|
|
@ -214,6 +214,15 @@ set_values(PyDictObject *mp, PyDictValues *values)
|
|||
_Py_atomic_store_ptr_release(&mp->ma_values, values);
|
||||
}
|
||||
|
||||
// gh-151593: The _Py_LOCK_DONT_DETACH flag ensures that the outer critical
|
||||
// section is not dropped if there is some contention on the keys lock.
|
||||
// It also means that it will be important that LOCK_KEYS() is essentially the
|
||||
// "inner-most" code and that we don't call Py_DECREF() or similar while
|
||||
// holding the keys lock.
|
||||
//
|
||||
// We are not allowed to acquire other locks within LOCK_KEYS(). For example,
|
||||
// PyType_Modified() must not be called within LOCK_KEYS() since it acquires
|
||||
// the type lock.
|
||||
#define LOCK_KEYS(keys) PyMutex_LockFlags(&keys->dk_mutex, _Py_LOCK_DONT_DETACH)
|
||||
#define UNLOCK_KEYS(keys) PyMutex_Unlock(&keys->dk_mutex)
|
||||
|
||||
|
|
@ -1923,12 +1932,13 @@ insert_split_key(PyDictKeysObject *keys, PyObject *key, Py_hash_t hash)
|
|||
}
|
||||
#endif
|
||||
|
||||
bool inserted = false;
|
||||
LOCK_KEYS(keys);
|
||||
ix = unicodekeys_lookup_unicode(keys, key, hash);
|
||||
if (ix == DKIX_EMPTY && keys->dk_usable > 0) {
|
||||
// Insert into new slot
|
||||
inserted = true;
|
||||
FT_ATOMIC_STORE_UINT32_RELAXED(keys->dk_version, 0);
|
||||
_PyDict_SplitKeysInvalidated(keys);
|
||||
Py_ssize_t hashpos = find_empty_slot(keys, hash);
|
||||
ix = keys->dk_nentries;
|
||||
dictkeys_set_index(keys, hashpos, ix);
|
||||
|
|
@ -1938,6 +1948,13 @@ insert_split_key(PyDictKeysObject *keys, PyObject *key, Py_hash_t hash)
|
|||
}
|
||||
assert (ix < SHARED_KEYS_MAX_SIZE);
|
||||
UNLOCK_KEYS(keys);
|
||||
|
||||
if (inserted) {
|
||||
// gh-151593: Calling PyType_Modified() with LOCK_KEYS() creates a
|
||||
// deadlock. So only call the function after UNLOCK_KEYS().
|
||||
_PyDict_SplitKeysInvalidated(keys);
|
||||
}
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue