##// END OF EJS Templates
lock: fix race in lock-breaking code...
lock: fix race in lock-breaking code With low frequency, I see hg pulls fail with output like: abort: no such file or directory: .hg/store/lock I think what happens is, in lock.py, in: def _testlock(self, locker): if not self._lockshouldbebroken(locker): return locker # if locker dead, break lock. must do this with another lock # held, or can race and break valid lock. try: with lock(self.vfs, self.f + b'.break', timeout=0): self.vfs.unlink(self.f) except error.LockError: return locker if a lock is breakable on disk, and two hg processes concurrently get to the "if locker dead" comment, a possible interleaving is: process1 finishes executing the function and then process2 finishes executing the function. If that happens, process2 will either get ENOENT in self.vfs.unlink (resulting in the spurious failure above), or break a valid lock and potentially cause repository corruption. The fix is simple enough: make sure the lock is breakable _inside_ the critical section, because only then can we know that no other process can invalidate our knowledge on the lock on disk. I don't think there are tests for this. I've tested this manually with: diff --git a/mercurial/lock.py b/mercurial/lock.py --- a/mercurial/lock.py +++ b/mercurial/lock.py @@ -351,6 +351,8 @@ class lock(object): if not self._lockshouldbebroken(locker): return locker + import random + time.sleep(1. + random.random()) # if locker dead, break lock. must do this with another lock # held, or can race and break valid lock. try: @@ -358,6 +360,7 @@ class lock(object): self.vfs.unlink(self.f) except error.LockError: return locker + time.sleep(1) def testlock(self): """return id of locker if lock is valid, else None. and I see this change of behavior before/after this commit: $ $hg init repo $ cd repo $ ln -s $HOSTNAME/effffffc:987654321 .hg/wlock $ touch a $ $hg commit -Am_ & $hg commit -Am _; wait -abort: No such file or directory: '/tmp/repo/.hg/wlock' adding a +warning: ignoring unknown working parent 679a8959a8ca! +nothing changed Differential Revision: https://phab.mercurial-scm.org/D7199

File last commit:

r44031:2e017696 default
r44108:039fbd14 default
Show More
pager.txt
43 lines | 1.4 KiB | text/plain | TextLexer
Some Mercurial commands can produce a lot of output, and Mercurial will
attempt to use a pager to make those commands more pleasant.
To set the pager that should be used, set the application variable::
[pager]
pager = less -FRX
If no pager is set in the user or repository configuration, Mercurial uses the
environment variable $PAGER. If $PAGER is not set, pager.pager from the default
or system configuration is used. If none of these are set, a default pager will
be used, typically `less` on Unix and `more` on Windows.
.. container:: windows
On Windows, `more` is not color aware, so using it effectively disables color.
MSYS and Cygwin shells provide `less` as a pager, which can be configured to
support ANSI color codes. See :hg:`help config.color.pagermode` to configure
the color mode when invoking a pager.
You can disable the pager for certain commands by adding them to the
pager.ignore list::
[pager]
ignore = version, help, update
To ignore global commands like :hg:`version` or :hg:`help`, you have
to specify them in your user configuration file.
To control whether the pager is used at all for an individual command,
you can use --pager=<value>:
- use as needed: `auto`.
- require the pager: `yes` or `on`.
- suppress the pager: `no` or `off` (any unrecognized value
will also work).
To globally turn off all attempts to use a pager, set::
[ui]
paginate = never
which will prevent the pager from running.