From: Serhiy Storchaka Date: Thu, 12 Jan 2017 17:42:20 +0000 (+0200) Subject: Issue #28969: Fixed race condition in C implementation of functools.lru_cache. X-Git-Tag: v3.7.0a1~1576 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=617c7753ce010617b45ae3bfa53a90c07b51510a;p=python 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. --- 617c7753ce010617b45ae3bfa53a90c07b51510a diff --cc Lib/test/test_functools.py index eeb3a227a2,824549b803..63fe83e5db --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@@ -7,8 -7,8 +7,9 @@@ import pickl from random import choice import sys from test import support + import time import unittest +import unittest.mock from weakref import proxy import contextlib try: diff --cc Misc/NEWS index db9243fa3c,3b84dd7791..892471291e --- a/Misc/NEWS +++ b/Misc/NEWS @@@ -212,9 -44,10 +212,13 @@@ Core and Builtin Library ------- + - 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. + +- Issue #20804: The unittest.mock.sentinel attributes now preserve their + identity when they are copied or pickled. + - Issue #29142: In urllib.request, suffixes in no_proxy environment variable with leading dots could match related hostnames again (e.g. .b.c matches a.b.c). Patch by Milan Oberkirch. diff --cc Objects/dictobject.c index baef589427,a7b403bcec..9950f50896 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@@ -1836,16 -1848,10 +1835,10 @@@ _PyDict_Pop_KnownHash(PyObject *dict, P _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); + ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &old_value, &hashpos); if (ix == DKIX_ERROR) return NULL; - if (ix == DKIX_EMPTY || *value_addr == NULL) { + if (ix == DKIX_EMPTY || old_value == NULL) { if (deflt) { Py_INCREF(deflt); return deflt;