changeset 29744:0d588332ad2c

branchmap: acquires lock before writting the rev branch cache We now attempt to acquire a lock and write the branch cache within that lock. This would prevent cache corruption when multiple processes try to write the cache at the same time.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Fri, 05 Aug 2016 14:57:16 +0200
parents 9f3c49ee4486
children 3b184adfb5be
files mercurial/branchmap.py tests/test-branches.t
diffstat 2 files changed, 22 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/branchmap.py	Fri Aug 05 14:54:46 2016 +0200
+++ b/mercurial/branchmap.py	Fri Aug 05 14:57:16 2016 +0200
@@ -470,8 +470,10 @@
     def write(self, tr=None):
         """Save branch cache if it is dirty."""
         repo = self._repo
-        if True:
+        wlock = None
+        try:
             if self._rbcnamescount < len(self._names):
+                wlock = repo.wlock(wait=False)
                 try:
                     if self._rbcnamescount != 0:
                         f = repo.vfs.open(_rbcnames, 'ab')
@@ -501,6 +503,8 @@
 
             start = self._rbcrevslen * _rbcrecsize
             if start != len(self._rbcrevs):
+                if wlock is None:
+                    wlock = repo.wlock(wait=False)
                 revs = min(len(repo.changelog),
                            len(self._rbcrevs) // _rbcrecsize)
                 try:
@@ -521,3 +525,8 @@
                                   inst)
                     return
                 self._rbcrevslen = revs
+        except error.LockError as inst:
+            repo.ui.debug("couldn't write revision branch cache: %s\n" % inst)
+        finally:
+            if wlock is not None:
+                wlock.release()
--- a/tests/test-branches.t	Fri Aug 05 14:54:46 2016 +0200
+++ b/tests/test-branches.t	Fri Aug 05 14:57:16 2016 +0200
@@ -554,6 +554,18 @@
   $ rmdir .hg/cache/rbc-revs-v1
   $ mv .hg/cache/rbc-revs-v1_ .hg/cache/rbc-revs-v1
 
+no errors when wlock cannot be acquired
+
+#if unix-permissions
+  $ mv .hg/cache/rbc-revs-v1 .hg/cache/rbc-revs-v1_
+  $ rm -f .hg/cache/branch*
+  $ chmod 555 .hg
+  $ hg head a -T '{rev}\n'
+  5
+  $ chmod 755 .hg
+  $ mv .hg/cache/rbc-revs-v1_ .hg/cache/rbc-revs-v1
+#endif
+
 recovery from invalid cache revs file with trailing data
   $ echo >> .hg/cache/rbc-revs-v1
   $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug