diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2017-01-12 17:42:20 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2017-01-12 17:42:20 (GMT) |
commit | 617c7753ce010617b45ae3bfa53a90c07b51510a (patch) | |
tree | 974d15dcc99f3504be149746e9b4069e5a2db6cc /Objects/dictobject.c | |
parent | 798ad2742b6523250e5477557e3cc2588d6e6475 (diff) | |
parent | 42e1ea9a10aa6c3df40af3b7561d6251c8e2ac9c (diff) | |
download | cpython-617c7753ce010617b45ae3bfa53a90c07b51510a.zip cpython-617c7753ce010617b45ae3bfa53a90c07b51510a.tar.gz cpython-617c7753ce010617b45ae3bfa53a90c07b51510a.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/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 baef589..9950f50 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1817,9 +1817,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; @@ -1836,12 +1835,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, &old_value, &hashpos); if (ix == DKIX_ERROR) return NULL; @@ -1878,6 +1871,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) |