Skip to content

Commit ea71ae9

Browse files
committed
fix: use a re-entrant lock to avoid self-deadlocking #1310
1 parent e6a8102 commit ea71ae9

File tree

2 files changed

+7
-1
lines changed

2 files changed

+7
-1
lines changed

coverage/sqldata.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def __init__(self, basename=None, suffix=None, no_disk=False, warn=None, debug=N
215215
self._dbs = {}
216216
self._pid = os.getpid()
217217
# Synchronize the operations used during collection.
218-
self._lock = threading.Lock()
218+
self._lock = threading.RLock()
219219

220220
# Are we in sync with the data file?
221221
self._have_used = False
@@ -231,7 +231,11 @@ def _locked(method): # pylint: disable=no-self-argument
231231
"""A decorator for methods that should hold self._lock."""
232232
@functools.wraps(method)
233233
def _wrapped(self, *args, **kwargs):
234+
if self._debug.should("lock"):
235+
self._debug.write(f"Locking {self._lock!r} for {method.__name__}")
234236
with self._lock:
237+
if self._debug.should("lock"):
238+
self._debug.write(f"Locked {self._lock!r} for {method.__name__}")
235239
# pylint: disable=not-callable
236240
return method(self, *args, **kwargs)
237241
return _wrapped

doc/cmd.rst

+2
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,8 @@ of operation to log:
969969

970970
* ``dataop``: log when data is added to the CoverageData object.
971971

972+
* ``lock``: log operations acquiring locks in the data layer.
973+
972974
* ``multiproc``: log the start and stop of multiprocessing processes.
973975

974976
* ``pid``: annotate all warnings and debug output with the process and thread

0 commit comments

Comments
 (0)