[PATCH] lock: fixed race condition in trylock/testlock (issue3506)

Tomasz Kleczek tkleczek at fb.com
Fri Sep 28 15:39:25 CDT 2012

# HG changeset patch
# User Tomasz Kleczek <tomasz.kleczek at fb.com>
# Date 1348781883 25200
# Node ID 61465b9b8bea0badde5c965a94a1b2326a327e14
# Parent  d42cc3c880b69d0ba769082dc28fd642568df7e1
lock: fixed race condition in trylock/testlock (issue3506)

Suppose the following scenario:

1. Process A takes the lock (e.g. on commit).
2. Process B wants to grab the lock. Since lock file exists
   the exception is raised. In the catch block the testlock
   function is called.
3. Process A releases the lock.
4. Process B tries to read the lock file as a part of testlock
   function. This results in OSError (ENOENT) and since we're
   not inside the exception handler function this is propagated
   and aborts the whole operation.

To fix this we now check in testlock function whether lock file
actually exists and if not (i.e. if readlock fails) we just return.

diff --git a/mercurial/lock.py b/mercurial/lock.py
--- a/mercurial/lock.py
+++ b/mercurial/lock.py
@@ -97,7 +97,12 @@
         The lock file is only deleted when None is returned.
-        locker = util.readlock(self.f)
+        try:
+            locker = util.readlock(self.f)
+        except OSError, why:
+            if why.errno == errno.ENOENT:
+                return None
+            raise
             host, pid = locker.split(":", 1)
         except ValueError:

More information about the Mercurial-devel mailing list