Mercurial > hg
comparison mercurial/lock.py @ 17682:829919ef894a stable
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.
author | Tomasz Kleczek <tomasz.kleczek@fb.com> |
---|---|
date | Thu, 27 Sep 2012 14:38:03 -0700 |
parents | cc24e4ed3e0c |
children | 6d7db5794e8c |
comparison
equal
deleted
inserted
replaced
17678:07d577dae285 | 17682:829919ef894a |
---|---|
95 not alive, we can safely break lock. | 95 not alive, we can safely break lock. |
96 | 96 |
97 The lock file is only deleted when None is returned. | 97 The lock file is only deleted when None is returned. |
98 | 98 |
99 """ | 99 """ |
100 locker = util.readlock(self.f) | 100 try: |
101 locker = util.readlock(self.f) | |
102 except OSError, why: | |
103 if why.errno == errno.ENOENT: | |
104 return None | |
105 raise | |
101 try: | 106 try: |
102 host, pid = locker.split(":", 1) | 107 host, pid = locker.split(":", 1) |
103 except ValueError: | 108 except ValueError: |
104 return locker | 109 return locker |
105 if host != lock._host: | 110 if host != lock._host: |