diff --git a/mercurial/lock.py b/mercurial/lock.py index 3a4ce9f37d..67bd3dd98a 100644 --- a/mercurial/lock.py +++ b/mercurial/lock.py @@ -139,12 +139,14 @@ class lock(object): if os.getpid() != self.pid: # we forked, and are not the parent return - if self.releasefn: - self.releasefn() try: - self.vfs.unlink(self.f) - except OSError: - pass + if self.releasefn: + self.releasefn() + finally: + try: + self.vfs.unlink(self.f) + except OSError: + pass for callback in self.postrelease: callback() diff --git a/tests/test-lock-badness.t b/tests/test-lock-badness.t index 1d19ac4cb8..459016fbff 100644 --- a/tests/test-lock-badness.t +++ b/tests/test-lock-badness.t @@ -11,6 +11,42 @@ Prepare updating to branch default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved +Test that raising an exception in the release function doesn't cause the lock to choke + + $ cat > testlock.py << EOF + > from mercurial import cmdutil, error, util + > + > cmdtable = {} + > command = cmdutil.command(cmdtable) + > + > def acquiretestlock(repo, releaseexc): + > def unlock(): + > if releaseexc: + > raise util.Abort('expected release exception') + > l = repo._lock(repo.vfs, 'testlock', False, unlock, None, 'test lock') + > return l + > + > @command('testlockexc') + > def testlockexc(ui, repo): + > testlock = acquiretestlock(repo, True) + > try: + > testlock.release() + > finally: + > try: + > testlock = acquiretestlock(repo, False) + > except error.LockHeld: + > raise util.Abort('lockfile on disk even after releasing!') + > testlock.release() + > EOF + $ cat >> $HGRCPATH << EOF + > [extensions] + > testlock=$TESTTMP/testlock.py + > EOF + + $ hg -R b testlockexc + abort: expected release exception + [255] + One process waiting for another $ cat > hooks.py << EOF