Gentoo Archives: gentoo-catalyst

From: Matt Turner <mattst88@g.o>
To: gentoo-catalyst@l.g.o
Cc: Matt Turner <mattst88@g.o>
Subject: [gentoo-catalyst] [PATCH 2/2] catalyst: Replace snakeoil's locks with fasteners
Date: Thu, 10 Jun 2021 03:28:50
Message-Id: 20210610032840.466809-2-mattst88@gentoo.org
In Reply to: [gentoo-catalyst] [PATCH 1/2] catalyst: Remove clear_dir's never used clear_nondir parameter by Matt Turner
1 To no great surprise, the existing locking was broken. For example,
2 clear_chroot() releases the lock. It is called by unpack(), which is
3 part of prepare_sequence. The result is that the whole build could be
4 done without holding the lock.
5
6 Just lock around run(). It's not apparent that finer-grained locking
7 does anything for us.
8
9 Signed-off-by: Matt Turner <mattst88@g.o>
10 ---
11 catalyst/base/clearbase.py | 2 --
12 catalyst/base/stagebase.py | 10 +++----
13 catalyst/lock.py | 58 ------------------------------------
14 catalyst/targets/snapshot.py | 6 ++--
15 4 files changed, 7 insertions(+), 69 deletions(-)
16 delete mode 100644 catalyst/lock.py
17
18 diff --git a/catalyst/base/clearbase.py b/catalyst/base/clearbase.py
19 index dcf6c523..6218330e 100644
20 --- a/catalyst/base/clearbase.py
21 +++ b/catalyst/base/clearbase.py
22 @@ -27,12 +27,10 @@ class ClearBase():
23 self.resume.clear_all(remove=True)
24
25 def clear_chroot(self):
26 - self.chroot_lock.unlock()
27 log.notice('Clearing the chroot path ...')
28 clear_dir(self.settings["chroot_path"], mode=0o755)
29
30 def remove_chroot(self):
31 - self.chroot_lock.unlock()
32 log.notice('Removing the chroot path ...')
33 clear_dir(self.settings["chroot_path"], mode=0o755, remove=True)
34
35 diff --git a/catalyst/base/stagebase.py b/catalyst/base/stagebase.py
36 index 448d6265..10cffd4c 100644
37 --- a/catalyst/base/stagebase.py
38 +++ b/catalyst/base/stagebase.py
39 @@ -8,6 +8,7 @@ import sys
40
41 from pathlib import Path
42
43 +import fasteners
44 import libmount
45 import toml
46
47 @@ -25,7 +26,6 @@ from catalyst.support import (CatalystError, file_locate, normpath,
48 from catalyst.base.targetbase import TargetBase
49 from catalyst.base.clearbase import ClearBase
50 from catalyst.base.genbase import GenBase
51 -from catalyst.lock import LockDir, LockInUse
52 from catalyst.fileops import ensure_dirs, clear_dir, clear_path
53 from catalyst.base.resume import AutoResume
54
55 @@ -36,9 +36,6 @@ def run_sequence(sequence):
56 sys.stdout.flush()
57 try:
58 func()
59 - except LockInUse:
60 - log.error('Unable to aquire the lock...')
61 - return False
62 except Exception:
63 log.error('Exception running action sequence %s',
64 func.__name__, exc_info=True)
65 @@ -478,7 +475,6 @@ class StageBase(TargetBase, ClearBase, GenBase):
66 """
67 self.settings["chroot_path"] = normpath(self.settings["storedir"] +
68 "/tmp/" + self.settings["target_subpath"].rstrip('/'))
69 - self.chroot_lock = LockDir(self.settings["chroot_path"])
70
71 def set_autoresume_path(self):
72 self.settings["autoresume_path"] = normpath(pjoin(
73 @@ -1366,8 +1362,10 @@ class StageBase(TargetBase, ClearBase, GenBase):
74 pass
75
76 def run(self):
77 - self.chroot_lock.write_lock()
78 + with fasteners.InterProcessLock(self.settings["chroot_path"] + '.lock'):
79 + return self._run()
80
81 + def _run(self):
82 if "clear-autoresume" in self.settings["options"]:
83 self.clear_autoresume()
84
85 diff --git a/catalyst/lock.py b/catalyst/lock.py
86 deleted file mode 100644
87 index e31745b2..00000000
88 --- a/catalyst/lock.py
89 +++ /dev/null
90 @@ -1,58 +0,0 @@
91 -
92 -import os
93 -
94 -from contextlib import contextmanager
95 -
96 -from snakeoil import fileutils
97 -from snakeoil import osutils
98 -from catalyst.fileops import ensure_dirs
99 -
100 -
101 -LockInUse = osutils.LockException
102 -
103 -class Lock:
104 - """
105 - A fnctl-based filesystem lock
106 - """
107 - def __init__(self, lockfile):
108 - fileutils.touch(lockfile, mode=0o664)
109 - os.chown(lockfile, uid=-1, gid=250)
110 - self.lock = osutils.FsLock(lockfile)
111 -
112 - def read_lock(self):
113 - self.lock.acquire_read_lock()
114 -
115 - def write_lock(self):
116 - self.lock.acquire_write_lock()
117 -
118 - def unlock(self):
119 - # Releasing a write lock is the same as a read lock.
120 - self.lock.release_write_lock()
121 -
122 -class LockDir(Lock):
123 - """
124 - A fnctl-based filesystem lock in a directory
125 - """
126 - def __init__(self, lockdir):
127 - ensure_dirs(lockdir)
128 - lockfile = os.path.join(lockdir, '.catalyst_lock')
129 -
130 - Lock.__init__(self, lockfile)
131 -
132 -@contextmanager
133 -def read_lock(filename):
134 - lock = Lock(filename)
135 - lock.read_lock()
136 - try:
137 - yield
138 - finally:
139 - lock.unlock()
140 -
141 -@contextmanager
142 -def write_lock(filename):
143 - lock = Lock(filename)
144 - lock.write_lock()
145 - try:
146 - yield
147 - finally:
148 - lock.unlock()
149 diff --git a/catalyst/targets/snapshot.py b/catalyst/targets/snapshot.py
150 index b494575a..ef68765d 100644
151 --- a/catalyst/targets/snapshot.py
152 +++ b/catalyst/targets/snapshot.py
153 @@ -5,11 +5,12 @@ Snapshot target
154 import subprocess
155 import sys
156
157 +import fasteners
158 +
159 from pathlib import Path
160
161 from catalyst import log
162 from catalyst.base.targetbase import TargetBase
163 -from catalyst.lock import write_lock
164 from catalyst.support import CatalystError, command
165
166 class snapshot(TargetBase):
167 @@ -93,8 +94,7 @@ class snapshot(TargetBase):
168 log.notice('>>> ' + ' '.join([*git_cmd, '|']))
169 log.notice(' ' + ' '.join(tar2sqfs_cmd))
170
171 - lockfile = self.snapshot.with_suffix('.lock')
172 - with write_lock(lockfile):
173 + with fasteners.InterProcessLock(self.snapshot.with_suffix('.lock')):
174 git = subprocess.Popen(git_cmd,
175 stdout=subprocess.PIPE,
176 stderr=sys.stderr,
177 --
178 2.31.1