diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2017-01-12 16:34:33 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2017-01-12 16:34:33 (GMT) |
commit | 67796521dd22b3008788a75108b45f33d06f85dd (patch) | |
tree | f737a3560e40ee17de082ff471687956cb4a8904 /Objects | |
parent | 9b8dcc6b1c18d5539735b61004d2e84b3e26cc8f (diff) | |
download | cpython-67796521dd22b3008788a75108b45f33d06f85dd.zip cpython-67796521dd22b3008788a75108b45f33d06f85dd.tar.gz cpython-67796521dd22b3008788a75108b45f33d06f85dd.tar.bz2 |
Issue #28969: Fixed race condition in C implementation of functools.lru_cache.
KeyError could be raised when cached function with full cache was
simultaneously called from differen threads with the same uncached arguments.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/dictobject.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 747d218..11c086f 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1475,9 +1475,8 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, /* Internal version of dict.pop(). */ PyObject * -_PyDict_Pop(PyDictObject *mp, PyObject *key, PyObject *deflt) +_PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *deflt) { - Py_hash_t hash; PyObject *old_value, *old_key; PyDictKeyEntry *ep; PyObject **value_addr; @@ -1490,12 +1489,6 @@ _PyDict_Pop(PyDictObject *mp, PyObject *key, PyObject *deflt) _PyErr_SetKeyError(key); return NULL; } - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return NULL; - } ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); if (ep == NULL) return NULL; @@ -1520,6 +1513,28 @@ _PyDict_Pop(PyDictObject *mp, PyObject *key, PyObject *deflt) return old_value; } +PyObject * +_PyDict_Pop(PyDictObject *mp, PyObject *key, PyObject *deflt) +{ + Py_hash_t hash; + + if (mp->ma_used == 0) { + if (deflt) { + Py_INCREF(deflt); + return deflt; + } + _PyErr_SetKeyError(key); + return NULL; + } + if (!PyUnicode_CheckExact(key) || + (hash = ((PyASCIIObject *) key)->hash) == -1) { + hash = PyObject_Hash(key); + if (hash == -1) + return NULL; + } + return _PyDict_Pop_KnownHash(mp, key, hash, deflt); +} + /* Internal version of dict.from_keys(). It is subclass-friendly. */ PyObject * _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) |