diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2022-01-30 08:03:11 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2022-01-30 11:48:59 -0500 |
commit | ea71ae9a65b14e20c982c818e3c10e50af9ae677 (patch) | |
tree | 1f1828e21bbaecdff74ea83cbd1eeb71bceeaef7 | |
parent | e6a810246f0316f6518d54148b3303c9b2f47f57 (diff) | |
download | python-coveragepy-git-ea71ae9a65b14e20c982c818e3c10e50af9ae677.tar.gz |
fix: use a re-entrant lock to avoid self-deadlocking #1310
-rw-r--r-- | coverage/sqldata.py | 6 | ||||
-rw-r--r-- | doc/cmd.rst | 2 |
2 files changed, 7 insertions, 1 deletions
diff --git a/coverage/sqldata.py b/coverage/sqldata.py index 5e27cd85..2bec3c96 100644 --- a/coverage/sqldata.py +++ b/coverage/sqldata.py @@ -215,7 +215,7 @@ class CoverageData(SimpleReprMixin): self._dbs = {} self._pid = os.getpid() # Synchronize the operations used during collection. - self._lock = threading.Lock() + self._lock = threading.RLock() # Are we in sync with the data file? self._have_used = False @@ -231,7 +231,11 @@ class CoverageData(SimpleReprMixin): """A decorator for methods that should hold self._lock.""" @functools.wraps(method) def _wrapped(self, *args, **kwargs): + if self._debug.should("lock"): + self._debug.write(f"Locking {self._lock!r} for {method.__name__}") with self._lock: + if self._debug.should("lock"): + self._debug.write(f"Locked {self._lock!r} for {method.__name__}") # pylint: disable=not-callable return method(self, *args, **kwargs) return _wrapped diff --git a/doc/cmd.rst b/doc/cmd.rst index 46d21575..afc9c27a 100644 --- a/doc/cmd.rst +++ b/doc/cmd.rst @@ -969,6 +969,8 @@ of operation to log: * ``dataop``: log when data is added to the CoverageData object. +* ``lock``: log operations acquiring locks in the data layer. + * ``multiproc``: log the start and stop of multiprocessing processes. * ``pid``: annotate all warnings and debug output with the process and thread |