annotate mercurial/lock.py @ 51303:81224afd938d

lock: properly convert error to bytes Flagged by pytype when a later changeset is applied moving typing comment to annotation. We fix this ahead of the annotation change to make sure pytype remains happy after the change. We have to do fairly crazy dance for pytype to be happy. This probably comes from the fact IOError.filename probably claims to be `str` while it is actually `bytes` if the filename raising that `IOError` is bytes. At the same time, `IOError.strerror` is consistently `str` and should be passed as `str` everywhere.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 20 Dec 2023 20:13:22 +0100
parents 18c8c18993f0
children 9da3fcc5f70f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
2 #
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 45957
diff changeset
3 # Copyright 2005, 2006 Olivia Mackall <olivia@selenic.com>
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
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
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9858
diff changeset
6 # GNU General Public License version 2 or any later version.
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
7
25956
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
8
26473
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
9 import contextlib
25956
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
10 import errno
30941
1f151a33af8e lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents: 30940
diff changeset
11 import os
36724
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
12 import signal
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
51303
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
15 import typing
8113
87a1605979e4 add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 8108
diff changeset
16 import warnings
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
17
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
18 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
19
25956
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
20 from . import (
31384
d57aa655ce97 lock: encode result of gethostname into a bytestring
Augie Fackler <augie@google.com>
parents: 31363
diff changeset
21 encoding,
25956
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
22 error,
30941
1f151a33af8e lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents: 30940
diff changeset
23 pycompat,
37848
8c828beb7543 lock: add internal config to not replace signal handlers while locking
Yuya Nishihara <yuya@tcha.org>
parents: 37659
diff changeset
24 util,
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36724
diff changeset
25 )
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36724
diff changeset
26
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
27 from .utils import procutil
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
28
25956
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
29
30940
dc9f086c7691 lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents: 28959
diff changeset
30 def _getlockprefix():
dc9f086c7691 lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents: 28959
diff changeset
31 """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
32
dc9f086c7691 lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents: 28959
diff changeset
33 It's useful to detect "dead" processes and remove stale locks with
30941
1f151a33af8e lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents: 30940
diff changeset
34 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: 30940
diff changeset
35 extra Linux-specific pid namespace identifier.
30940
dc9f086c7691 lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents: 28959
diff changeset
36 """
35937
4b1c04082cdc py3: replace "if ispy3" by encoding.strtolocal()
Yuya Nishihara <yuya@tcha.org>
parents: 35219
diff changeset
37 result = encoding.strtolocal(socket.gethostname())
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
38 if pycompat.sysplatform.startswith(b'linux'):
30941
1f151a33af8e lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents: 30940
diff changeset
39 try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
40 result += b'/%x' % os.stat(b'/proc/self/ns/pid').st_ino
49318
050dc8730858 py3: catch specific OSError subclasses instead of checking errno
Manuel Jacob <me@manueljacob.de>
parents: 49314
diff changeset
41 except (FileNotFoundError, PermissionError, NotADirectoryError):
050dc8730858 py3: catch specific OSError subclasses instead of checking errno
Manuel Jacob <me@manueljacob.de>
parents: 49314
diff changeset
42 pass
30941
1f151a33af8e lock: include Linux pid namespace identifier in prefix
Jun Wu <quark@fb.com>
parents: 30940
diff changeset
43 return result
30940
dc9f086c7691 lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents: 28959
diff changeset
44
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
45
36724
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
46 @contextlib.contextmanager
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
47 def _delayedinterrupt():
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
48 """Block signal interrupt while doing something critical
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
49
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
50 This makes sure that the code block wrapped by this context manager won't
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
51 be interrupted.
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
52
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
53 For Windows developers: It appears not possible to guard time.sleep()
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
54 from CTRL_C_EVENT, so please don't use time.sleep() to test if this is
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
55 working.
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
56 """
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
57 assertedsigs = []
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
58 blocked = False
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
59 orighandlers = {}
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
60
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
61 def raiseinterrupt(num):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
62 if num == getattr(signal, 'SIGINT', None) or num == getattr(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
63 signal, 'CTRL_C_EVENT', None
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
64 ):
36724
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
65 raise KeyboardInterrupt
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
66 else:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
67 raise error.SignalInterrupt
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
68
36724
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
69 def catchterm(num, frame):
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
70 if blocked:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
71 assertedsigs.append(num)
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
72 else:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
73 raiseinterrupt(num)
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
74
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
75 try:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
76 # save handlers first so they can be restored even if a setup is
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
77 # interrupted between signal.signal() and orighandlers[] =.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
78 for name in [
50618
5586076b8030 safehasattr: pass attribute name as string instead of bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49318
diff changeset
79 'CTRL_C_EVENT',
5586076b8030 safehasattr: pass attribute name as string instead of bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49318
diff changeset
80 'SIGINT',
5586076b8030 safehasattr: pass attribute name as string instead of bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49318
diff changeset
81 'SIGBREAK',
5586076b8030 safehasattr: pass attribute name as string instead of bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49318
diff changeset
82 'SIGHUP',
5586076b8030 safehasattr: pass attribute name as string instead of bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49318
diff changeset
83 'SIGTERM',
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
84 ]:
36724
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
85 num = getattr(signal, name, None)
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
86 if num and num not in orighandlers:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
87 orighandlers[num] = signal.getsignal(num)
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
88 try:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
89 for num in orighandlers:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
90 signal.signal(num, catchterm)
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
91 except ValueError:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
92 pass # in a thread? no luck
36724
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
93
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
94 blocked = True
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
95 yield
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
96 finally:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
97 # no simple way to reliably restore all signal handlers because
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
98 # any loops, recursive function calls, except blocks, etc. can be
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
99 # interrupted. so instead, make catchterm() raise interrupt.
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
100 blocked = False
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
101 try:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
102 for num, handler in orighandlers.items():
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
103 signal.signal(num, handler)
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
104 except ValueError:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
105 pass # in a thread?
36724
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
106
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
107 # re-raise interrupt exception if any, which may be shadowed by a new
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
108 # interrupt occurred while re-raising the first one
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
109 if assertedsigs:
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
110 raiseinterrupt(assertedsigs[0])
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
111
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
112
35219
9153871d50e0 lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents: 35218
diff changeset
113 def trylock(ui, vfs, lockname, timeout, warntimeout, *args, **kwargs):
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
114 """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
115
35219
9153871d50e0 lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents: 35218
diff changeset
116 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: 35218
diff changeset
117 the held lock while trying to acquires it."""
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
118
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
119 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
120 """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
121 # show more details for new-style locks
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
122 if b':' in locker:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
123 host, pid = locker.split(b":", 1)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
124 msg = _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
125 b"waiting for lock on %s held by process %r on host %r\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
126 ) % (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
127 pycompat.bytestr(l.desc),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
128 pycompat.bytestr(pid),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
129 pycompat.bytestr(host),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
130 )
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
131 else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
132 msg = _(b"waiting for lock on %s held by %r\n") % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
133 l.desc,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
134 pycompat.bytestr(locker),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
135 )
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
136 printer(msg)
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
137
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
138 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
139
35219
9153871d50e0 lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents: 35218
diff changeset
140 debugidx = 0 if (warntimeout and timeout) else -1
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
141 warningidx = 0
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
142 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
143 warningidx = -1
35219
9153871d50e0 lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents: 35218
diff changeset
144 elif warntimeout:
9153871d50e0 lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents: 35218
diff changeset
145 warningidx = warntimeout
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
146
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
147 delay = 0
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
148 while True:
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
149 try:
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
150 l._trylock()
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
151 break
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
152 except error.LockHeld as inst:
35219
9153871d50e0 lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents: 35218
diff changeset
153 if delay == debugidx:
9153871d50e0 lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents: 35218
diff changeset
154 printwarning(ui.debug, inst.locker)
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
155 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
156 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
157 if timeout <= delay:
51303
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
158 assert isinstance(inst.filename, bytes)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
159 raise error.LockHeld(
51303
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
160 errno.ETIMEDOUT,
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
161 typing.cast(bytes, inst.filename),
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
162 l.desc,
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
163 inst.locker,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
164 )
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
165 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
166 delay += 1
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
167
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
168 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
169 if l.delay:
35219
9153871d50e0 lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents: 35218
diff changeset
170 if 0 <= warningidx <= l.delay:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
171 ui.warn(_(b"got lock after %d seconds\n") % l.delay)
35219
9153871d50e0 lock: allow to configure when the lock messages are displayed
Boris Feld <boris.feld@octobus.net>
parents: 35218
diff changeset
172 else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
173 ui.debug(b"got lock after %d seconds\n" % l.delay)
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
174 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
175 l.acquirefn()
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
176 return l
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
177
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
178
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
179 class lock:
45957
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45527
diff changeset
180 """An advisory lock held by one process to control access to a set
9309
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
181 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
182 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
183 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
184
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
185 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
186 store (.hg/store/) or localrepository.wlock() to lock everything
45957
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45527
diff changeset
187 else under .hg/."""
9309
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
188
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
189 # 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
190
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
191 # 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
192 # 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
193
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
194 # 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
195 # 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
196
4947
3e25a6eb5c9a lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents: 3877
diff changeset
197 _host = None
3e25a6eb5c9a lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents: 3877
diff changeset
198
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
199 def __init__(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
200 self,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
201 vfs,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
202 fname,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
203 timeout=-1,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
204 releasefn=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
205 acquirefn=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
206 desc=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
207 signalsafe=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
208 dolock=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
209 ):
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
210 self.vfs = vfs
37659
575f59cdd8a1 lock: don't use 'file' as a variable name
Pulkit Goyal <7895pulkit@gmail.com>
parents: 37658
diff changeset
211 self.f = fname
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
212 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
213 self.timeout = timeout
1530
abfab59fce79 add a releasefn keyword to lock.lock
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1062
diff changeset
214 self.releasefn = releasefn
26321
db4c192cb9b3 lock: move acquirefn call to inside the lock
Siddharth Agarwal <sid0@fb.com>
parents: 26291
diff changeset
215 self.acquirefn = acquirefn
2016
ff5c9a92f556 fix backtrace printed when cannot get lock.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
216 self.desc = desc
37848
8c828beb7543 lock: add internal config to not replace signal handlers while locking
Yuya Nishihara <yuya@tcha.org>
parents: 37659
diff changeset
217 if signalsafe:
8c828beb7543 lock: add internal config to not replace signal handlers while locking
Yuya Nishihara <yuya@tcha.org>
parents: 37659
diff changeset
218 self._maybedelayedinterrupt = _delayedinterrupt
8c828beb7543 lock: add internal config to not replace signal handlers while locking
Yuya Nishihara <yuya@tcha.org>
parents: 37659
diff changeset
219 else:
8c828beb7543 lock: add internal config to not replace signal handlers while locking
Yuya Nishihara <yuya@tcha.org>
parents: 37659
diff changeset
220 self._maybedelayedinterrupt = util.nullcontextmanager
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
221 self.postrelease = []
26383
0fceb34806e1 lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents: 26359
diff changeset
222 self.pid = self._getpid()
35218
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
223 if dolock:
1b758105b5c7 lock: add a trylock method handling the timeout and messaging logic
Boris Feld <boris.feld@octobus.net>
parents: 32088
diff changeset
224 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
225 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
226 self.acquirefn()
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
227
27797
054abf2377e8 lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 26498
diff changeset
228 def __enter__(self):
054abf2377e8 lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 26498
diff changeset
229 return self
054abf2377e8 lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 26498
diff changeset
230
054abf2377e8 lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 26498
diff changeset
231 def __exit__(self, exc_type, exc_value, exc_tb):
43798
888bd39ed555 lock: pass "success" boolean to _afterlock callbacks
Kyle Lippincott <spectral@google.com>
parents: 43749
diff changeset
232 success = all(a is None for a in (exc_type, exc_value, exc_tb))
888bd39ed555 lock: pass "success" boolean to _afterlock callbacks
Kyle Lippincott <spectral@google.com>
parents: 43749
diff changeset
233 self.release(success=success)
27797
054abf2377e8 lock: turn a lock into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 26498
diff changeset
234
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
235 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
236 if self.held:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
237 warnings.warn(
43551
313e3a279828 cleanup: remove pointless r-prefixes on double-quoted strings
Augie Fackler <augie@google.com>
parents: 43089
diff changeset
238 "use lock.release instead of del lock",
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
239 category=DeprecationWarning,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
240 stacklevel=2,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
241 )
8113
87a1605979e4 add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 8108
diff changeset
242
8108
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
243 # 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
244 # 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
245 self.held = 1
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
246
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
247 self.release()
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
248
26383
0fceb34806e1 lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents: 26359
diff changeset
249 def _getpid(self):
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36724
diff changeset
250 # wrapper around procutil.getpid() to make testing easier
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36724
diff changeset
251 return procutil.getpid()
26383
0fceb34806e1 lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents: 26359
diff changeset
252
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
253 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
254 timeout = self.timeout
14494
1ffeeb91c55d check-code: flag 0/1 used as constant Boolean expression
Martin Geisler <mg@lazybytes.net>
parents: 13281
diff changeset
255 while True:
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
256 try:
26082
b188f60bd955 lock: make trylock private
Matt Mackall <mpm@selenic.com>
parents: 26081
diff changeset
257 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
258 return self.timeout - timeout
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23032
diff changeset
259 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
260 if timeout != 0:
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
261 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
262 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
263 timeout -= 1
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
264 continue
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
265 raise error.LockHeld(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
266 errno.ETIMEDOUT, inst.filename, self.desc, inst.locker
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
267 )
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 503
diff changeset
268
26082
b188f60bd955 lock: make trylock private
Matt Mackall <mpm@selenic.com>
parents: 26081
diff changeset
269 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
270 if self.held:
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
271 self.held += 1
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
272 return
4947
3e25a6eb5c9a lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents: 3877
diff changeset
273 if lock._host is None:
30940
dc9f086c7691 lock: move lock._host calculation to a function
Jun Wu <quark@fb.com>
parents: 28959
diff changeset
274 lock._host = _getlockprefix()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
275 lockname = b'%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
276 retry = 5
3b6e5914edd8 lock: loop a finite number of times in trylock (issue4787)
Matt Mackall <mpm@selenic.com>
parents: 25956
diff changeset
277 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
278 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
279 try:
37848
8c828beb7543 lock: add internal config to not replace signal handlers while locking
Yuya Nishihara <yuya@tcha.org>
parents: 37659
diff changeset
280 with self._maybedelayedinterrupt():
36724
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
281 self.vfs.makelock(lockname, self.f)
d77c3b023393 lock: block signal interrupt while making a lock file
Yuya Nishihara <yuya@tcha.org>
parents: 36686
diff changeset
282 self.held = 1
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23032
diff changeset
283 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
284 if why.errno == errno.EEXIST:
26387
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
285 locker = self._readlock()
32087
e1938d6051da lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 31387
diff changeset
286 if locker is None:
e1938d6051da lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 31387
diff changeset
287 continue
e1938d6051da lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 31387
diff changeset
288
26387
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
289 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
290 if locker is not None:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
291 raise error.LockHeld(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
292 errno.EAGAIN,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
293 self.vfs.join(self.f),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
294 self.desc,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
295 locker,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
296 )
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
297 else:
51303
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
298 assert isinstance(why.filename, bytes)
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
299 assert isinstance(why.strerror, str)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
300 raise error.LockUnavailable(
51303
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
301 why.errno,
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
302 why.strerror,
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
303 typing.cast(bytes, why.filename),
81224afd938d lock: properly convert error to bytes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
304 self.desc,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
305 )
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
306
32088
0d892d820a51 lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 32087
diff changeset
307 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
308 # 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
309 # by many processes"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
310 raise error.LockHeld(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
311 errno.EAGAIN, self.vfs.join(self.f), self.desc, b""
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
312 )
32088
0d892d820a51 lock: avoid unintentional lock acquisition at failure of readlock
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 32087
diff changeset
313
26290
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
314 def _readlock(self):
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
315 """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
316
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
317 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
318 for new-style locks.
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
319 """
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
320 try:
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
321 return self.vfs.readlock(self.f)
49314
2e726c934fcd py3: catch FileNotFoundError instead of checking errno == ENOENT
Manuel Jacob <me@manueljacob.de>
parents: 49037
diff changeset
322 except FileNotFoundError:
2e726c934fcd py3: catch FileNotFoundError instead of checking errno == ENOENT
Manuel Jacob <me@manueljacob.de>
parents: 49037
diff changeset
323 return None
26290
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
324
43748
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
325 def _lockshouldbebroken(self, locker):
26290
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
326 if locker is None:
43748
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
327 return False
2579
0875cda033fd use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2016
diff changeset
328 try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
329 host, pid = locker.split(b":", 1)
2579
0875cda033fd use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2016
diff changeset
330 except ValueError:
43748
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
331 return False
4947
3e25a6eb5c9a lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents: 3877
diff changeset
332 if host != lock._host:
43748
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
333 return False
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
334 try:
2579
0875cda033fd use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2016
diff changeset
335 pid = int(pid)
9685
a820cd39d415 lock: catch specific exceptions
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9680
diff changeset
336 except ValueError:
43748
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
337 return False
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36724
diff changeset
338 if procutil.testpid(pid):
43748
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
339 return False
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
340 return True
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
341
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
342 def _testlock(self, locker):
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
343 if not self._lockshouldbebroken(locker):
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
344 return locker
43748
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
345
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
346 # 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
347 # 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
348 try:
43748
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
349 with lock(self.vfs, self.f + b'.break', timeout=0):
43749
039fbd14d4e2 lock: fix race in lock-breaking code
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43748
diff changeset
350 locker = self._readlock()
039fbd14d4e2 lock: fix race in lock-breaking code
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43748
diff changeset
351 if not self._lockshouldbebroken(locker):
039fbd14d4e2 lock: fix race in lock-breaking code
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43748
diff changeset
352 return locker
43748
cd822413b9aa lock: refactor in preparation for next commit
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43551
diff changeset
353 self.vfs.unlink(self.f)
7640
7197812e8d44 error: move lock errors
Matt Mackall <mpm@selenic.com>
parents: 4959
diff changeset
354 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
355 return locker
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
356
26291
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
357 def testlock(self):
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
358 """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
359
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
360 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
361 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
362 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
363 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
364
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
365 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
366
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
367 """
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
368 locker = self._readlock()
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
369 return self._testlock(locker)
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
370
43798
888bd39ed555 lock: pass "success" boolean to _afterlock callbacks
Kyle Lippincott <spectral@google.com>
parents: 43749
diff changeset
371 def release(self, success=True):
15583
926a06f7a353 lock: add mechanism to register post release callback
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 14494
diff changeset
372 """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
373
17537
31f32a96e1e3 Merge spelling fixes
Bryan O'Sullivan <bryano@fb.com>
parents: 17427 17510
diff changeset
374 If the lock has been acquired multiple times, the actual release is
17510
7c44b703657b spelling: release
timeless@mozdev.org
parents: 15589
diff changeset
375 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
376 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
377 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
378 elif self.held == 1:
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
379 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
380 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
381 # 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
382 return
503
c6a2e41c8c60 Fix troubles with clone and exception handling
mpm@selenic.com
parents: 429
diff changeset
383 try:
23032
f484be02bd35 lock: while releasing, unlink lockfile even if the release function throws
Siddharth Agarwal <sid0@fb.com>
parents: 20380
diff changeset
384 if self.releasefn:
f484be02bd35 lock: while releasing, unlink lockfile even if the release function throws
Siddharth Agarwal <sid0@fb.com>
parents: 20380
diff changeset
385 self.releasefn()
f484be02bd35 lock: while releasing, unlink lockfile even if the release function throws
Siddharth Agarwal <sid0@fb.com>
parents: 20380
diff changeset
386 finally:
45527
9b16bb3b2349 locking: remove support for inheriting locks in subprocess
Martin von Zweigbergk <martinvonz@google.com>
parents: 43798
diff changeset
387 try:
9b16bb3b2349 locking: remove support for inheriting locks in subprocess
Martin von Zweigbergk <martinvonz@google.com>
parents: 43798
diff changeset
388 self.vfs.unlink(self.f)
9b16bb3b2349 locking: remove support for inheriting locks in subprocess
Martin von Zweigbergk <martinvonz@google.com>
parents: 43798
diff changeset
389 except OSError:
9b16bb3b2349 locking: remove support for inheriting locks in subprocess
Martin von Zweigbergk <martinvonz@google.com>
parents: 43798
diff changeset
390 pass
26474
431094a3b21f lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26473
diff changeset
391 # 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
392 # at all.
45527
9b16bb3b2349 locking: remove support for inheriting locks in subprocess
Martin von Zweigbergk <martinvonz@google.com>
parents: 43798
diff changeset
393 for callback in self.postrelease:
9b16bb3b2349 locking: remove support for inheriting locks in subprocess
Martin von Zweigbergk <martinvonz@google.com>
parents: 43798
diff changeset
394 callback(success)
9b16bb3b2349 locking: remove support for inheriting locks in subprocess
Martin von Zweigbergk <martinvonz@google.com>
parents: 43798
diff changeset
395 # Prevent double usage and help clear cycles.
9b16bb3b2349 locking: remove support for inheriting locks in subprocess
Martin von Zweigbergk <martinvonz@google.com>
parents: 43798
diff changeset
396 self.postrelease = None
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
397
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 38251
diff changeset
398
8108
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
399 def release(*locks):
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
400 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
401 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
402 lock.release()