]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-142651: use `NonCallableMock._lock` for thread safety of `call_count` ...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 10 Mar 2026 12:34:37 +0000 (13:34 +0100)
committerGitHub <noreply@github.com>
Tue, 10 Mar 2026 12:34:37 +0000 (12:34 +0000)
gh-142651: use `NonCallableMock._lock` for thread safety of `call_count` (GH-142922)
(cherry picked from commit 728e4a075e3dae7e04edf90ad137a35073deb141)

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Lib/unittest/mock.py

index 1dd7735d150ebebe7a73172b1f4e1364de0032e9..b6dd1c27fee169f8cbb9bc9116608414c4d32abb 100644 (file)
@@ -1178,10 +1178,16 @@ class CallableMixin(Base):
         # handle call_args
         # needs to be set here so assertions on call arguments pass before
         # execution in the case of awaited calls
-        _call = _Call((args, kwargs), two=True)
-        self.call_args = _call
-        self.call_args_list.append(_call)
-        self.call_count = len(self.call_args_list)
+        with NonCallableMock._lock:
+            # Lock is used here so that call_args_list and call_count are
+            # set atomically otherwise it is possible that by the time call_count
+            # is set another thread may have appended to call_args_list.
+            # The rest of this function relies on list.append being atomic and
+            # skips locking.
+            _call = _Call((args, kwargs), two=True)
+            self.call_args = _call
+            self.call_args_list.append(_call)
+            self.call_count = len(self.call_args_list)
 
         # initial stuff for method_calls:
         do_method_calls = self._mock_parent is not None