[PATCH 3 of 3 fyi] hack: more lock validation, checking opener usage

Mads Kiilerich mads at kiilerich.com
Sun Nov 17 11:53:59 CST 2013


# HG changeset patch
# User Mads Kiilerich <mads at kiilerich.com>
# Date 1326756353 -3600
#      Tue Jan 17 00:25:53 2012 +0100
# Branch stable
# Node ID cc7c104ed113b1a221ab4898ef1a7b7fe294f881
# Parent  ca1828f0c90d81978daa555fdcdbe841d4fe70b3
hack: more lock validation, checking opener usage

This revealed too many problems and was thus put in a separate patch so they
could be ignored.

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -162,13 +162,19 @@ class localrepository(object):
         return self.requirements[:]
 
     def __init__(self, baseui, path=None, create=False):
-        self.wvfs = scmutil.vfs(path, expandpath=True, realpath=True)
+        def lockverify(fn):
+            #print repr(fn)
+            if '/store/' in fn or '/journal.' in fn:
+                self.checklock(skip=3)
+            else:
+                self.checkwlock(skip=3)
+        self.wvfs = scmutil.vfs(path, expandpath=True, realpath=True, lockverify=lambda dirname: self.checkwlock(skip=3))
         self.wopener = self.wvfs
         self.root = self.wvfs.base
         self.path = self.wvfs.join(".hg")
         self.origroot = path
         self.auditor = scmutil.pathauditor(self.root, self._checknested)
-        self.vfs = scmutil.vfs(self.path)
+        self.vfs = scmutil.vfs(self.path, lockverify=lockverify)
         self.opener = self.vfs
         self.baseui = baseui
         self.ui = baseui.copy()
@@ -192,6 +198,8 @@ class localrepository(object):
         else:
             self.supported = self._basesupported
 
+        self._transref = self._lockref = self._wlockref = None
+
         if not self.vfs.isdir():
             if create:
                 if not self.wvfs.exists():
@@ -205,7 +213,7 @@ class localrepository(object):
                         requirements.append("fncache")
                         if self.ui.configbool('format', 'dotencode', True):
                             requirements.append('dotencode')
-                    # create an invalid changelog
+                    # create an invalid changelog WITHOUT LOCKING!
                     self.vfs.append(
                         "00changelog.i",
                         '\0\0\0\2' # represents revlogv2
@@ -249,7 +257,6 @@ class localrepository(object):
         self._branchcaches = {}
         self.filterpats = {}
         self._datafilters = {}
-        self._transref = self._lockref = self._wlockref = None
 
         # A cache for various files under .hg/ that tracks file changes,
         # (used by the filecache decorator)
@@ -268,7 +275,11 @@ class localrepository(object):
 
         self._applyrequirements(requirements)
         if create:
-            self._writerequirements()
+            try:
+                wlock = self.wlock()
+                self._writerequirements()
+            finally:
+                wlock.release()
 
     def close(self):
         pass
@@ -1075,6 +1086,7 @@ class localrepository(object):
                 ui.warnstack('trying to unlock wlock with lock held',
                     skip=1)
 
+            self.checkwlock()
             self.dirstate.write()
             self._filecache['dirstate'].refresh()
 
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -293,11 +293,12 @@ class vfs(abstractvfs):
     This class is used to hide the details of COW semantics and
     remote file access from higher level code.
     '''
-    def __init__(self, base, audit=True, expandpath=False, realpath=False):
+    def __init__(self, base, audit=True, expandpath=False, realpath=False, lockverify=None):
         if expandpath:
             base = util.expandpath(base)
         if realpath:
             base = os.path.realpath(base)
+        self.lockverify = lockverify
         self.base = base
         self._setmustaudit(audit)
         self.createmode = None
@@ -341,6 +342,8 @@ class vfs(abstractvfs):
 
         nlink = -1
         if mode not in ('r', 'rb'):
+            if self.lockverify:
+                self.lockverify(f)
             dirname, basename = util.split(f)
             # If basename is empty, then the path is malformed because it points
             # to a directory. Let the posixfile() call below raise IOError.
diff --git a/mercurial/tags.py b/mercurial/tags.py
--- a/mercurial/tags.py
+++ b/mercurial/tags.py
@@ -15,6 +15,7 @@ from i18n import _
 import encoding
 import error
 import errno
+import lock as lockmod
 
 def findglobaltags(ui, repo, alltags, tagtypes):
     '''Find global tags in repo by reading .hgtags from every head that
@@ -256,6 +257,10 @@ def _readtagcache(ui, repo):
     return (repoheads, cachefnode, None, True)
 
 def _writetagcache(ui, repo, heads, tagfnode, cachetags):
+  wlock = lock = None
+  try:
+    wlock = repo.wlock()
+    lock = repo.lock()
 
     try:
         cachefile = repo.opener('cache/tags', 'w', atomictemp=True)
@@ -298,3 +303,6 @@ def _writetagcache(ui, repo, heads, tagf
         cachefile.close()
     except (OSError, IOError):
         pass
+
+  finally:
+    lockmod.release(lock, wlock)


More information about the Mercurial-devel mailing list