[PATCH] localrepo: Add locking to _branchtags around _writebrancache
Mads
mads at kiilerich.com
Fri May 25 06:46:02 CDT 2012
On 24/05/12 16:50, Joshua Redstone wrote:
> # HG changeset patch
> # User Joshua Redstone<joshua.redstone at fb.com>
> # Date 1336812429 25200
> # Node ID b3bb1d7360c481b847431fc0d264111b1d93f993
> # Parent 2ac08d8b21aa7b6e0a062afed5a3f357ccef67f9
> localrepo: Add locking to _branchtags around _writebrancache
minor typo
> Read code paths such as via localrepo.branchmap() may end up calling
> _writebranchcache without having acquire a repo lock, potentially leading to
> races with other repo mutations. This fix acquires the repo lock if not yet
> held before calling _writebranchcache.
>
> diff -r 2ac08d8b21aa -r b3bb1d7360c4 mercurial/localrepo.py
> --- a/mercurial/localrepo.py Tue May 22 14:37:20 2012 -0500
> +++ b/mercurial/localrepo.py Sat May 12 01:47:09 2012 -0700
> @@ -481,8 +481,18 @@
> if lrev != tiprev:
> ctxgen = (self[r] for r in xrange(lrev + 1, tiprev + 1))
> self._updatebranchcache(partial, ctxgen)
> - self._writebranchcache(partial, self.changelog.tip(), tiprev)
> -
> + # Read code paths (e.g., from branchmap()) do not have the lock
> + # yet. Lock acquisition may fail if we do not have write-access
> + # to the directory.
> + try:
> + wlock = self.wlock(wait=False)
> + try:
> + self._writebranchcache(partial, self.changelog.tip(),
> + tiprev)
> + finally:
> + wlock.release()
> + except error.LockError:
> + pass
> return partial
>
> def updatebranchcache(self):
> diff -r 2ac08d8b21aa -r b3bb1d7360c4 mercurial/statichttprepo.py
lock might have been taking before we take wlock here. That is the wrong
order ... but I guess that is ok and doesn't cause any other problems
than breaking the rules and being spotted by lock validation ;-)
But I guess the branch cache is a pure function of the repo in store, so
shouldn't the cache be in store too and be protected by lock instead of
wlock? The comments indicate that your intent was to use lock instead of
wlock.
But ... what is the purpose of this lock around _writebranchcache?
_writebranchcache will use atomictemp anyway and will thus either update
the cache or leave it untouched.
The bigger problem is that it (apparently) will write something based on
information it read before taking the lock. Ideally _readbranchcache
should be inside the locked region as well ... and there is not much
point in locking as long as it isn't.
> diff -r 2ac08d8b21aa -r b3bb1d7360c4 tests/test-bheads.t
> --- a/tests/test-bheads.t Tue May 22 14:37:20 2012 -0500
> +++ b/tests/test-bheads.t Sat May 12 01:47:09 2012 -0700
> @@ -31,6 +31,14 @@
>
> =======
>
> +Not being able to update the branchheads cache should not make read ops fail
> + $ echo "junk"> $TESTTMP/a/.hg/cache/branchheads
> + $ chmod -R u-w $TESTTMP/a/.hg
> + $ heads
> + 1: Adding a branch (a)
> + 0: Adding root node ()
> + $ chmod -R u+w $TESTTMP/a/.hg
That test will fail on windows - it should use hghave unix-permissions.
/Mads
More information about the Mercurial-devel
mailing list