afterlock: add the callback to the top level lock (
issue4608)
If 'wlock' is taken, we should add 'afterlock' callback to the 'wlock' instead.
Otherwise, running post transaction hook after 'lock' is release but 'wlock' is
still taken lead to a deadlock (eg: 'hg update' during a hook).
This situation is much more common since:
5dc5cd7abbf5
push: acquire local 'wlock' if "pushback" is expected (BC) (
issue4596)
--- a/mercurial/localrepo.py Mon Apr 20 16:05:32 2015 +0200
+++ b/mercurial/localrepo.py Mon Apr 20 15:27:55 2015 +0200
@@ -1194,13 +1194,16 @@
return l
def _afterlock(self, callback):
- """add a callback to the current repository lock.
+ """add a callback to be run when the repository is fully unlocked
- The callback will be executed on lock release."""
- l = self._lockref and self._lockref()
- if l:
- l.postrelease.append(callback)
- else:
+ The callback will be executed when the outermost lock is released
+ (with wlock being higher level than 'lock')."""
+ for ref in (self._wlockref, self._lockref):
+ l = ref and ref()
+ if l and l.held:
+ l.postrelease.append(callback)
+ break
+ else: # no lock have been found.
callback()
def lock(self, wait=True):
--- a/tests/test-hook.t Mon Apr 20 16:05:32 2015 +0200
+++ b/tests/test-hook.t Mon Apr 20 15:27:55 2015 +0200
@@ -1,4 +1,5 @@
commit hooks can see env vars
+(and post-transaction one are run unlocked)
$ hg init a
$ cd a
@@ -16,6 +17,7 @@
> pretxnclose = sh -c "HG_LOCAL= HG_TAG= python \"$TESTDIR/printenv.py\" pretxnclose"
> txnclose = sh -c "HG_LOCAL= HG_TAG= python \"$TESTDIR/printenv.py\" txnclose"
> txnabort = sh -c "HG_LOCAL= HG_TAG= python \"$TESTDIR/printenv.py\" txnabort"
+ > txnclose.checklock = hg debuglock > /dev/null
> EOF
$ echo a > a
$ hg add a