diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2017-01-12 19:12:21 +0200 |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2017-01-12 19:12:21 +0200 |
commit | 42e1ea9a10aa6c3df40af3b7561d6251c8e2ac9c (patch) | |
tree | d54140f730a38805fa55a7a5cc90b0e894d91318 /Objects/dictobject.c | |
parent | 12c4aba1a0fbd934a66d6b97c29c36d7de14e755 (diff) | |
parent | 67796521dd22b3008788a75108b45f33d06f85dd (diff) | |
download | cpython-git-42e1ea9a10aa6c3df40af3b7561d6251c8e2ac9c.tar.gz |
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/dictobject.c')
-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 64941937e7..a7b403bcec 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1829,9 +1829,8 @@ PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) /* Internal version of dict.pop(). */ PyObject * -_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *deflt) +_PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *deflt) { - Py_hash_t hash; Py_ssize_t ix, hashpos; PyObject *old_value, *old_key; PyDictKeyEntry *ep; @@ -1849,12 +1848,6 @@ _PyDict_Pop(PyObject *dict, 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; - } ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, &hashpos); if (ix == DKIX_ERROR) return NULL; @@ -1892,6 +1885,28 @@ _PyDict_Pop(PyObject *dict, PyObject *key, PyObject *deflt) return old_value; } +PyObject * +_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *deflt) +{ + Py_hash_t hash; + + if (((PyDictObject *)dict)->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(dict, key, hash, deflt); +} + /* Internal version of dict.from_keys(). It is subclass-friendly. */ PyObject * _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) |