author | Kyle Lippincott <spectral@google.com> |
Thu, 04 Jan 2018 16:29:07 -0800 | |
changeset 36236 | 564dec70b50c |
parent 35897 | 4b1c04082cdc |
child 36319 | c303eda316be |
permissions | -rw-r--r-- |
9309
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
1 |
# lock.py - simple advisory locking scheme for mercurial |
161 | 2 |
# |
2859 | 3 |
# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> |
161 | 4 |
# |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8113
diff
changeset
|
5 |
# This software may be used and distributed according to the terms of the |
10263 | 6 |
# GNU General Public License version 2 or any later version. |
161 | 7 |
|
25956
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
8 |
from __future__ import absolute_import |
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
9 |
|
26473
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
10 |
import contextlib |
25956
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
11 |
import errno |
30921
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
12 |
import os |
25956
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
13 |
import socket |
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
14 |
import time |
8113
87a1605979e4
add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
8108
diff
changeset
|
15 |
import warnings |
161 | 16 |
|
35208
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
17 |
from .i18n import _ |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
18 |
|
25956
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
19 |
from . import ( |
31375
d57aa655ce97
lock: encode result of gethostname into a bytestring
Augie Fackler <augie@google.com>
parents:
31354
diff
changeset
|
20 |
encoding, |
25956
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
21 |
error, |
30921
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
22 |
pycompat, |
25956
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
23 |
util, |
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
24 |
) |
8cd30e9277ae
lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25660
diff
changeset
|
25 |
|
30920
dc9f086c7691
lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents:
28959
diff
changeset
|
26 |
def _getlockprefix(): |
dc9f086c7691
lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents:
28959
diff
changeset
|
27 |
"""Return a string which is used to differentiate pid namespaces |
dc9f086c7691
lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents:
28959
diff
changeset
|
28 |
|
dc9f086c7691
lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents:
28959
diff
changeset
|
29 |
It's useful to detect "dead" processes and remove stale locks with |
30921
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
30 |
confidence. Typically it's just hostname. On modern linux, we include an |
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
31 |
extra Linux-specific pid namespace identifier. |
30920
dc9f086c7691
lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents:
28959
diff
changeset
|
32 |
""" |
35897
4b1c04082cdc
py3: replace "if ispy3" by encoding.strtolocal()
Yuya Nishihara <yuya@tcha.org>
parents:
35209
diff
changeset
|
33 |
result = encoding.strtolocal(socket.gethostname()) |
30921
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
34 |
if pycompat.sysplatform.startswith('linux'): |
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
35 |
try: |
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
36 |
result += '/%x' % os.stat('/proc/self/ns/pid').st_ino |
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
37 |
except OSError as ex: |
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
38 |
if ex.errno not in (errno.ENOENT, errno.EACCES, errno.ENOTDIR): |
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
39 |
raise |
1f151a33af8e
lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents:
30920
diff
changeset
|
40 |
return result |
30920
dc9f086c7691
lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents:
28959
diff
changeset
|
41 |
|
35209
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
42 |
def trylock(ui, vfs, lockname, timeout, warntimeout, *args, **kwargs): |
35208
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
43 |
"""return an acquired lock or raise an a LockHeld exception |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
44 |
|
35209
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
45 |
This function is responsible to issue warnings and or debug messages about |
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
46 |
the held lock while trying to acquires it.""" |
35208
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
47 |
|
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
48 |
def printwarning(printer, locker): |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
49 |
"""issue the usual "waiting on lock" message through any channel""" |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
50 |
# show more details for new-style locks |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
51 |
if ':' in locker: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
52 |
host, pid = locker.split(":", 1) |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
53 |
msg = _("waiting for lock on %s held by process %r " |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
54 |
"on host %r\n") % (l.desc, pid, host) |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
55 |
else: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
56 |
msg = _("waiting for lock on %s held by %r\n") % (l.desc, locker) |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
57 |
printer(msg) |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
58 |
|
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
59 |
l = lock(vfs, lockname, 0, *args, dolock=False, **kwargs) |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
60 |
|
35209
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
61 |
debugidx = 0 if (warntimeout and timeout) else -1 |
35208
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
62 |
warningidx = 0 |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
63 |
if not timeout: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
64 |
warningidx = -1 |
35209
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
65 |
elif warntimeout: |
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
66 |
warningidx = warntimeout |
35208
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
67 |
|
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
68 |
delay = 0 |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
69 |
while True: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
70 |
try: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
71 |
l._trylock() |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
72 |
break |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
73 |
except error.LockHeld as inst: |
35209
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
74 |
if delay == debugidx: |
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
75 |
printwarning(ui.debug, inst.locker) |
35208
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
76 |
if delay == warningidx: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
77 |
printwarning(ui.warn, inst.locker) |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
78 |
if timeout <= delay: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
79 |
raise error.LockHeld(errno.ETIMEDOUT, inst.filename, |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
80 |
l.desc, inst.locker) |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
81 |
time.sleep(1) |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
82 |
delay += 1 |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
83 |
|
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
84 |
l.delay = delay |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
85 |
if l.delay: |
35209
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
86 |
if 0 <= warningidx <= l.delay: |
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
87 |
ui.warn(_("got lock after %s seconds\n") % l.delay) |
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
88 |
else: |
9153871d50e0
lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents:
35208
diff
changeset
|
89 |
ui.debug("got lock after %s seconds\n" % l.delay) |
35208
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
90 |
if l.acquirefn: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
91 |
l.acquirefn() |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
92 |
return l |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
93 |
|
1559
59b3639df0a9
Convert all classes to new-style classes by deriving them from object.
Eric Hopper <hopper@omnifarious.org>
parents:
1530
diff
changeset
|
94 |
class lock(object): |
9309
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
95 |
'''An advisory lock held by one process to control access to a set |
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
96 |
of files. Non-cooperating processes or incorrectly written scripts |
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
97 |
can ignore Mercurial's locking scheme and stomp all over the |
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
98 |
repository, so don't do that. |
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
99 |
|
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
100 |
Typically used via localrepository.lock() to lock the repository |
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
101 |
store (.hg/store/) or localrepository.wlock() to lock everything |
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
102 |
else under .hg/.''' |
cfdcb7a465af
localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents:
8312
diff
changeset
|
103 |
|
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
104 |
# lock is symlink on platforms that support it, file on others. |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
105 |
|
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
106 |
# symlink is used because create of directory entry and contents |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
107 |
# are atomic even over nfs. |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
108 |
|
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
109 |
# old-style lock: symlink to pid |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
110 |
# new-style lock: symlink to hostname:pid |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
111 |
|
4947
3e25a6eb5c9a
lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents:
3877
diff
changeset
|
112 |
_host = None |
3e25a6eb5c9a
lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents:
3877
diff
changeset
|
113 |
|
26321
db4c192cb9b3
lock: move acquirefn call to inside the lock
Siddharth Agarwal <sid0@fb.com>
parents:
26291
diff
changeset
|
114 |
def __init__(self, vfs, file, timeout=-1, releasefn=None, acquirefn=None, |
35208
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
115 |
desc=None, inheritchecker=None, parentlock=None, |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
116 |
dolock=True): |
20091
abfe6a8e619b
lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
19927
diff
changeset
|
117 |
self.vfs = vfs |
161 | 118 |
self.f = file |
119 |
self.held = 0 |
|
1787
e431344e604c
add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1753
diff
changeset
|
120 |
self.timeout = timeout |
1530
abfab59fce79
add a releasefn keyword to lock.lock
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1062
diff
changeset
|
121 |
self.releasefn = releasefn |
26321
db4c192cb9b3
lock: move acquirefn call to inside the lock
Siddharth Agarwal <sid0@fb.com>
parents:
26291
diff
changeset
|
122 |
self.acquirefn = acquirefn |
2016
ff5c9a92f556
fix backtrace printed when cannot get lock.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1877
diff
changeset
|
123 |
self.desc = desc |
26498
e8564e04382d
lock: add a way to prevent locks from being inherited
Siddharth Agarwal <sid0@fb.com>
parents:
26474
diff
changeset
|
124 |
self._inheritchecker = inheritchecker |
26356
927fa07a2ba4
lock: introduce state to keep track of inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26321
diff
changeset
|
125 |
self.parentlock = parentlock |
927fa07a2ba4
lock: introduce state to keep track of inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26321
diff
changeset
|
126 |
self._parentheld = False |
927fa07a2ba4
lock: introduce state to keep track of inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26321
diff
changeset
|
127 |
self._inherited = False |
15589
cc24e4ed3e0c
lock: change name of release chain
Matt Mackall <mpm@selenic.com>
parents:
15583
diff
changeset
|
128 |
self.postrelease = [] |
26383
0fceb34806e1
lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents:
26359
diff
changeset
|
129 |
self.pid = self._getpid() |
35208
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
130 |
if dolock: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
131 |
self.delay = self.lock() |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
132 |
if self.acquirefn: |
1b758105b5c7
lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents:
32088
diff
changeset
|
133 |
self.acquirefn() |
161 | 134 |
|
27797
054abf2377e8
lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents:
26498
diff
changeset
|
135 |
def __enter__(self): |
054abf2377e8
lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents:
26498
diff
changeset
|
136 |
return self |
054abf2377e8
lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents:
26498
diff
changeset
|
137 |
|
054abf2377e8
lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents:
26498
diff
changeset
|
138 |
def __exit__(self, exc_type, exc_value, exc_tb): |
054abf2377e8
lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents:
26498
diff
changeset
|
139 |
self.release() |
054abf2377e8
lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents:
26498
diff
changeset
|
140 |
|
161 | 141 |
def __del__(self): |
8108
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
142 |
if self.held: |
8113
87a1605979e4
add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
8108
diff
changeset
|
143 |
warnings.warn("use lock.release instead of del lock", |
87a1605979e4
add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
8108
diff
changeset
|
144 |
category=DeprecationWarning, |
87a1605979e4
add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
8108
diff
changeset
|
145 |
stacklevel=2) |
87a1605979e4
add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
8108
diff
changeset
|
146 |
|
8108
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
147 |
# ensure the lock will be removed |
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
148 |
# even if recursive locking did occur |
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
149 |
self.held = 1 |
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
150 |
|
161 | 151 |
self.release() |
152 |
||
26383
0fceb34806e1
lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents:
26359
diff
changeset
|
153 |
def _getpid(self): |
28027
14033c5dd261
util: enable getpid to be replaced
timeless <timeless@mozdev.org>
parents:
27797
diff
changeset
|
154 |
# wrapper around util.getpid() to make testing easier |
14033c5dd261
util: enable getpid to be replaced
timeless <timeless@mozdev.org>
parents:
27797
diff
changeset
|
155 |
return util.getpid() |
26383
0fceb34806e1
lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents:
26359
diff
changeset
|
156 |
|
161 | 157 |
def lock(self): |
1787
e431344e604c
add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1753
diff
changeset
|
158 |
timeout = self.timeout |
14494
1ffeeb91c55d
check-code: flag 0/1 used as constant Boolean expression
Martin Geisler <mg@lazybytes.net>
parents:
13281
diff
changeset
|
159 |
while True: |
161 | 160 |
try: |
26082
b188f60bd955
lock: make trylock private
Matt Mackall <mpm@selenic.com>
parents:
26081
diff
changeset
|
161 |
self._trylock() |
20380
c697b70f295f
localrepo: give a sigh of relief when getting lock after waiting for it
Mads Kiilerich <madski@unity3d.com>
parents:
20091
diff
changeset
|
162 |
return self.timeout - timeout |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23032
diff
changeset
|
163 |
except error.LockHeld as inst: |
1787
e431344e604c
add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1753
diff
changeset
|
164 |
if timeout != 0: |
161 | 165 |
time.sleep(1) |
1787
e431344e604c
add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1753
diff
changeset
|
166 |
if timeout > 0: |
e431344e604c
add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1753
diff
changeset
|
167 |
timeout -= 1 |
161 | 168 |
continue |
7640 | 169 |
raise error.LockHeld(errno.ETIMEDOUT, inst.filename, self.desc, |
170 |
inst.locker) |
|
515 | 171 |
|
26082
b188f60bd955
lock: make trylock private
Matt Mackall <mpm@selenic.com>
parents:
26081
diff
changeset
|
172 |
def _trylock(self): |
8108
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
173 |
if self.held: |
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
174 |
self.held += 1 |
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
175 |
return |
4947
3e25a6eb5c9a
lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents:
3877
diff
changeset
|
176 |
if lock._host is None: |
30920
dc9f086c7691
lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents:
28959
diff
changeset
|
177 |
lock._host = _getlockprefix() |
31354
e6a2b625e0d9
lock: use %d to format integer into a bytestring
Augie Fackler <augie@google.com>
parents:
30921
diff
changeset
|
178 |
lockname = '%s:%d' % (lock._host, self.pid) |
26081
3b6e5914edd8
lock: loop a finite number of times in trylock (issue4787)
Matt Mackall <mpm@selenic.com>
parents:
25956
diff
changeset
|
179 |
retry = 5 |
3b6e5914edd8
lock: loop a finite number of times in trylock (issue4787)
Matt Mackall <mpm@selenic.com>
parents:
25956
diff
changeset
|
180 |
while not self.held and retry: |
3b6e5914edd8
lock: loop a finite number of times in trylock (issue4787)
Matt Mackall <mpm@selenic.com>
parents:
25956
diff
changeset
|
181 |
retry -= 1 |
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
182 |
try: |
20091
abfe6a8e619b
lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
19927
diff
changeset
|
183 |
self.vfs.makelock(lockname, self.f) |
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
184 |
self.held = 1 |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23032
diff
changeset
|
185 |
except (OSError, IOError) as why: |
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
186 |
if why.errno == errno.EEXIST: |
26387
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
187 |
locker = self._readlock() |
32087
e1938d6051da
lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
31378
diff
changeset
|
188 |
if locker is None: |
e1938d6051da
lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
31378
diff
changeset
|
189 |
continue |
e1938d6051da
lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
31378
diff
changeset
|
190 |
|
26387
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
191 |
# special case where a parent process holds the lock -- this |
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
192 |
# is different from the pid being different because we do |
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
193 |
# want the unlock and postrelease functions to be called, |
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
194 |
# but the lockfile to not be removed. |
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
195 |
if locker == self.parentlock: |
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
196 |
self._parentheld = True |
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
197 |
self.held = 1 |
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
198 |
return |
e16f80f89a29
lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents:
26383
diff
changeset
|
199 |
locker = self._testlock(locker) |
3686
4308f4cdc07b
Don't step into an endless loop when lock file is empty.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2859
diff
changeset
|
200 |
if locker is not None: |
20091
abfe6a8e619b
lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
19927
diff
changeset
|
201 |
raise error.LockHeld(errno.EAGAIN, |
abfe6a8e619b
lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
19927
diff
changeset
|
202 |
self.vfs.join(self.f), self.desc, |
7640 | 203 |
locker) |
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
204 |
else: |
7640 | 205 |
raise error.LockUnavailable(why.errno, why.strerror, |
206 |
why.filename, self.desc) |
|
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
207 |
|
32088
0d892d820a51
lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
32087
diff
changeset
|
208 |
if not self.held: |
0d892d820a51
lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
32087
diff
changeset
|
209 |
# use empty locker to mean "busy for frequent lock/unlock |
0d892d820a51
lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
32087
diff
changeset
|
210 |
# by many processes" |
0d892d820a51
lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
32087
diff
changeset
|
211 |
raise error.LockHeld(errno.EAGAIN, |
0d892d820a51
lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
32087
diff
changeset
|
212 |
self.vfs.join(self.f), self.desc, "") |
0d892d820a51
lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
32087
diff
changeset
|
213 |
|
26290
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
214 |
def _readlock(self): |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
215 |
"""read lock and return its value |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
216 |
|
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
217 |
Returns None if no lock exists, pid for old-style locks, and host:pid |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
218 |
for new-style locks. |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
219 |
""" |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
220 |
try: |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
221 |
return self.vfs.readlock(self.f) |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
222 |
except (OSError, IOError) as why: |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
223 |
if why.errno == errno.ENOENT: |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
224 |
return None |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
225 |
raise |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
226 |
|
26291
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
227 |
def _testlock(self, locker): |
26290
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
228 |
if locker is None: |
9664d32bd6cb
lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26082
diff
changeset
|
229 |
return None |
2579
0875cda033fd
use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
2016
diff
changeset
|
230 |
try: |
0875cda033fd
use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
2016
diff
changeset
|
231 |
host, pid = locker.split(":", 1) |
0875cda033fd
use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
2016
diff
changeset
|
232 |
except ValueError: |
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
233 |
return locker |
4947
3e25a6eb5c9a
lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents:
3877
diff
changeset
|
234 |
if host != lock._host: |
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
235 |
return locker |
161 | 236 |
try: |
2579
0875cda033fd
use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
2016
diff
changeset
|
237 |
pid = int(pid) |
9685
a820cd39d415
lock: catch specific exceptions
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
9680
diff
changeset
|
238 |
except ValueError: |
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
239 |
return locker |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
240 |
if util.testpid(pid): |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
241 |
return locker |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
242 |
# if locker dead, break lock. must do this with another lock |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
243 |
# held, or can race and break valid lock. |
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
244 |
try: |
20091
abfe6a8e619b
lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
19927
diff
changeset
|
245 |
l = lock(self.vfs, self.f + '.break', timeout=0) |
abfe6a8e619b
lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
19927
diff
changeset
|
246 |
self.vfs.unlink(self.f) |
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
247 |
l.release() |
7640 | 248 |
except error.LockError: |
1877
d314a89fa4f1
change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
1836
diff
changeset
|
249 |
return locker |
161 | 250 |
|
26291
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
251 |
def testlock(self): |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
252 |
"""return id of locker if lock is valid, else None. |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
253 |
|
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
254 |
If old-style lock, we cannot tell what machine locker is on. |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
255 |
with new-style lock, if locker is on this machine, we can |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
256 |
see if locker is alive. If locker is on this machine but |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
257 |
not alive, we can safely break lock. |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
258 |
|
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
259 |
The lock file is only deleted when None is returned. |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
260 |
|
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
261 |
""" |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
262 |
locker = self._readlock() |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
263 |
return self._testlock(locker) |
1d33842c5b3e
lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents:
26290
diff
changeset
|
264 |
|
26473
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
265 |
@contextlib.contextmanager |
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
266 |
def inherit(self): |
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
267 |
"""context for the lock to be inherited by a Mercurial subprocess. |
26357
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
268 |
|
26473
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
269 |
Yields a string that will be recognized by the lock in the subprocess. |
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
270 |
Communicating this string to the subprocess needs to be done separately |
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
271 |
-- typically by an environment variable. |
26357
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
272 |
""" |
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
273 |
if not self.held: |
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
274 |
raise error.LockInheritanceContractViolation( |
26473
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
275 |
'inherit can only be called while lock is held') |
26357
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
276 |
if self._inherited: |
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
277 |
raise error.LockInheritanceContractViolation( |
26473
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
278 |
'inherit cannot be called while lock is already inherited') |
26498
e8564e04382d
lock: add a way to prevent locks from being inherited
Siddharth Agarwal <sid0@fb.com>
parents:
26474
diff
changeset
|
279 |
if self._inheritchecker is not None: |
e8564e04382d
lock: add a way to prevent locks from being inherited
Siddharth Agarwal <sid0@fb.com>
parents:
26474
diff
changeset
|
280 |
self._inheritchecker() |
26357
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
281 |
if self.releasefn: |
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
282 |
self.releasefn() |
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
283 |
if self._parentheld: |
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
284 |
lockname = self.parentlock |
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
285 |
else: |
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
286 |
lockname = '%s:%s' % (lock._host, self.pid) |
6979a1369185
lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents:
26356
diff
changeset
|
287 |
self._inherited = True |
26473
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
288 |
try: |
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
289 |
yield lockname |
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
290 |
finally: |
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
291 |
if self.acquirefn: |
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
292 |
self.acquirefn() |
5f94e64f182c
lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents:
26387
diff
changeset
|
293 |
self._inherited = False |
26358
de5a52e5eb9e
lock: add a method to reacquire the lock after subprocesses exit
Siddharth Agarwal <sid0@fb.com>
parents:
26357
diff
changeset
|
294 |
|
161 | 295 |
def release(self): |
15583
926a06f7a353
lock: add mechanism to register post release callback
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
14494
diff
changeset
|
296 |
"""release the lock and execute callback function if any |
926a06f7a353
lock: add mechanism to register post release callback
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
14494
diff
changeset
|
297 |
|
17537 | 298 |
If the lock has been acquired multiple times, the actual release is |
17510 | 299 |
delayed to the last release call.""" |
8108
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
300 |
if self.held > 1: |
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
301 |
self.held -= 1 |
9680
8cea86d73887
lock: use '==' instead of 'is' for integer equality ('is' may not work)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
9309
diff
changeset
|
302 |
elif self.held == 1: |
161 | 303 |
self.held = 0 |
26383
0fceb34806e1
lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents:
26359
diff
changeset
|
304 |
if self._getpid() != self.pid: |
18907
af9fa8d4c939
lock: if we fork, ensure that only the parent releases
Bryan O'Sullivan <bryano@fb.com>
parents:
17683
diff
changeset
|
305 |
# we forked, and are not the parent |
af9fa8d4c939
lock: if we fork, ensure that only the parent releases
Bryan O'Sullivan <bryano@fb.com>
parents:
17683
diff
changeset
|
306 |
return |
503
c6a2e41c8c60
Fix troubles with clone and exception handling
mpm@selenic.com
parents:
429
diff
changeset
|
307 |
try: |
23032
f484be02bd35
lock: while releasing, unlink lockfile even if the release function throws
Siddharth Agarwal <sid0@fb.com>
parents:
20380
diff
changeset
|
308 |
if self.releasefn: |
f484be02bd35
lock: while releasing, unlink lockfile even if the release function throws
Siddharth Agarwal <sid0@fb.com>
parents:
20380
diff
changeset
|
309 |
self.releasefn() |
f484be02bd35
lock: while releasing, unlink lockfile even if the release function throws
Siddharth Agarwal <sid0@fb.com>
parents:
20380
diff
changeset
|
310 |
finally: |
26359
c545d51c901e
lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26358
diff
changeset
|
311 |
if not self._parentheld: |
c545d51c901e
lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26358
diff
changeset
|
312 |
try: |
c545d51c901e
lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26358
diff
changeset
|
313 |
self.vfs.unlink(self.f) |
c545d51c901e
lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26358
diff
changeset
|
314 |
except OSError: |
c545d51c901e
lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26358
diff
changeset
|
315 |
pass |
26474
431094a3b21f
lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26473
diff
changeset
|
316 |
# The postrelease functions typically assume the lock is not held |
431094a3b21f
lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26473
diff
changeset
|
317 |
# at all. |
431094a3b21f
lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26473
diff
changeset
|
318 |
if not self._parentheld: |
431094a3b21f
lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26473
diff
changeset
|
319 |
for callback in self.postrelease: |
431094a3b21f
lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents:
26473
diff
changeset
|
320 |
callback() |
28959
518c3e392f75
lock: clear postrelease hooks list after usage
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28027
diff
changeset
|
321 |
# Prevent double usage and help clear cycles. |
518c3e392f75
lock: clear postrelease hooks list after usage
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28027
diff
changeset
|
322 |
self.postrelease = None |
161 | 323 |
|
8108
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
324 |
def release(*locks): |
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
325 |
for lock in locks: |
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
326 |
if lock is not None: |
a26d33749bd8
made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7640
diff
changeset
|
327 |
lock.release() |