Mercurial > hg
view mercurial/pushkey.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 | 59c14bf5a48c |
children | a2c7ae21e8f4 |
line wrap: on
line source
# pushkey.py - dispatching for pushing and pulling keys # # Copyright 2010 Matt Mackall <mpm@selenic.com> # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. import bookmarks, phases, obsolete def _nslist(repo): n = {} for k in _namespaces: n[k] = "" if not obsolete._enabled: n.pop('obsolete') return n _namespaces = {"namespaces": (lambda *x: False, _nslist), "bookmarks": (bookmarks.pushbookmark, bookmarks.listbookmarks), "phases": (phases.pushphase, phases.listphases), "obsolete": (obsolete.pushmarker, obsolete.listmarkers), } def register(namespace, pushkey, listkeys): _namespaces[namespace] = (pushkey, listkeys) def _get(namespace): return _namespaces.get(namespace, (lambda *x: False, lambda *x: {})) def push(repo, namespace, key, old, new): '''should succeed iff value was old''' pk = _get(namespace)[0] return pk(repo, key, old, new) def list(repo, namespace): '''return a dict''' lk = _get(namespace)[1] return lk(repo)