]> granicus.if.org Git - python/commitdiff
Issue #28969: Fixed race condition in C implementation of functools.lru_cache.
authorSerhiy Storchaka <storchaka@gmail.com>
Thu, 12 Jan 2017 17:42:20 +0000 (19:42 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Thu, 12 Jan 2017 17:42:20 +0000 (19:42 +0200)
KeyError could be raised when cached function with full cache was
simultaneously called from differen threads with the same uncached arguments.

1  2 
Include/dictobject.h
Lib/test/test_functools.py
Misc/NEWS
Modules/_functoolsmodule.c
Objects/dictobject.c

Simple merge
index eeb3a227a2e364e1dd6c07a7afd7a8cfd8c18709,824549b80342ed8f72483208a4baa892c8b6c715..63fe83e5dbd6028ecb4d68bbf74a4f43deac14e9
@@@ -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 db9243fa3c2be41c5b561f17fa9350df49fabeb1,3b84dd7791031fc9bc14a471dec97f148b311674..892471291ebded529f9107cd5e506d35f53d612b
+++ 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.
Simple merge
index baef58942798f231e34245709301a76049cf96a4,a7b403bcecc5da2f76df4dc6bbfb9be6ce04dae0..9950f50896a6f49a4055a9ad79356a6d17ed3e7f
@@@ -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;