Skip to content

Commit 2943bd5

Browse files
committed
systemd: use cgroup.events notification instead of sleep + check
wait for cgroup to empty, not disappear, because sometimes it may remain. #229
1 parent 9280189 commit 2943bd5

1 file changed

Lines changed: 32 additions & 15 deletions

File tree

lilac2/systemd.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -215,26 +215,43 @@ def poll_rusage(
215215
subprocess.run(['systemctl', '--user', 'stop', '--quiet', name])
216216
if cgroup:
217217
# if we actually got the cgroup (i.e. service was started when we looked)
218-
wait_cgroup_disappear(cgroup, name)
218+
wait_cgroup_empty(cgroup, name)
219219

220220
p = subprocess.run(['systemctl', '--user', 'is-failed', '--quiet', name])
221221
if p.returncode == 0:
222222
subprocess.run(['systemctl', '--user', 'reset-failed', '--quiet', name])
223223
return RUsage(nsec / 1_000_000_000, mem_max), timedout
224224

225-
def wait_cgroup_disappear(cgroup: str, name: str) -> None:
226-
d = f'/sys/fs/cgroup/{cgroup}'
227-
if not os.path.exists(d):
225+
def wait_cgroup_empty(cgroup: str, name: str) -> None:
226+
try:
227+
f = open(f'/sys/fs/cgroup/{cgroup}/cgroup.events')
228+
f.read()
229+
except FileNotFoundError:
228230
return
229231

230-
count = 0
231-
while os.path.exists(d):
232-
logger.warning('waiting %s to disappear...', cgroup)
233-
time.sleep(1)
234-
count += 1
235-
if count == 10:
236-
logger.warning('killing %s.', name)
237-
subprocess.run(['systemctl', '--user', 'kill', name])
238-
elif count == 30:
239-
logger.warning('killing %s with SIGKILL.', name)
240-
subprocess.run(['systemctl', '--user', 'kill', '--signal=KILL', name])
232+
poll = select.poll()
233+
poll.register(f, select.POLLPRI)
234+
235+
timeout = 10
236+
killed = False
237+
while True:
238+
logger.warning('waiting %s to become empty...', cgroup)
239+
if not poll.poll(timeout * 1000):
240+
if not killed:
241+
logger.warning('killing %s.', name)
242+
subprocess.run(['systemctl', '--user', 'kill', name])
243+
timeout = 20
244+
killed = True
245+
else:
246+
logger.warning('killing %s with SIGKILL.', name)
247+
subprocess.run(['systemctl', '--user', 'kill', '--signal=KILL', name])
248+
try:
249+
f.seek(0)
250+
for line in f:
251+
if f == 'populated 0':
252+
f.close()
253+
return
254+
except OSError: # no such device
255+
f.close()
256+
return
257+

0 commit comments

Comments
 (0)