Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH v2] SpawnProcess: re-check cgroup.procs until empty (bug 566420)
Date: Sun, 22 Nov 2015 00:00:53
Message-Id: 1448150431-22661-1-git-send-email-zmedico@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH] SpawnProcess: re-check cgroup.procs until empty (bug 566420) by Zac Medico
1 For subshell die support (bug 465008), re-check cgroup.procs until it's
2 empty, in case any of the listed processes fork before we've had a chance
3 to kill them.
4
5 X-Gentoo-Bug: 566420
6 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=566420
7 ---
8 [PATCH v2] limits the cleanup loop to 8 iterations, and logs an eerror
9 message if there are any lingering pids.
10
11 pym/_emerge/SpawnProcess.py | 31 ++++++++++++++++++++++++++++---
12 1 file changed, 28 insertions(+), 3 deletions(-)
13
14 diff --git a/pym/_emerge/SpawnProcess.py b/pym/_emerge/SpawnProcess.py
15 index 5ab2e67..4ab646d 100644
16 --- a/pym/_emerge/SpawnProcess.py
17 +++ b/pym/_emerge/SpawnProcess.py
18 @@ -16,6 +16,8 @@ from _emerge.SubProcess import SubProcess
19 import portage
20 from portage import os
21 from portage.const import BASH_BINARY
22 +from portage.localization import _
23 +from portage.output import EOutput
24 from portage.util import writemsg_level
25 from portage.util._async.PipeLogger import PipeLogger
26
27 @@ -35,6 +37,10 @@ class SpawnProcess(SubProcess):
28 __slots__ = ("args",) + \
29 _spawn_kwarg_names + ("_pipe_logger", "_selinux_type",)
30
31 + # Max number of attempts to kill the processes listed in cgroup.procs,
32 + # given that processes may fork before they can be killed.
33 + _CGROUP_CLEANUP_RETRY_MAX = 8
34 +
35 def _start(self):
36
37 if self.fd_pipes is None:
38 @@ -203,10 +209,24 @@ class SpawnProcess(SubProcess):
39 elif e.errno != errno.ESRCH:
40 raise
41
42 - # step 1: kill all orphans
43 - pids = get_pids(self.cgroup)
44 + # step 1: kill all orphans (loop in case of new forks)
45 + remaining = self._CGROUP_CLEANUP_RETRY_MAX
46 + while remaining:
47 + remaining -= 1
48 + pids = get_pids(self.cgroup)
49 + if pids:
50 + kill_all(pids, signal.SIGKILL)
51 + else:
52 + break
53 +
54 if pids:
55 - kill_all(pids, signal.SIGKILL)
56 + msg = []
57 + msg.append(
58 + _("Failed to kill pid(s) in '%(cgroup)s': %(pids)s") % dict(
59 + cgroup=os.path.join(self.cgroup, 'cgroup.procs'),
60 + pids=' '.join(str(pid) for pid in pids)))
61 +
62 + self._elog('eerror', msg)
63
64 # step 2: remove the cgroup
65 try:
66 @@ -215,3 +235,8 @@ class SpawnProcess(SubProcess):
67 # it may be removed already, or busy
68 # we can't do anything good about it
69 pass
70 +
71 + def _elog(self, elog_funcname, lines):
72 + elog_func = getattr(EOutput(), elog_funcname)
73 + for line in lines:
74 + elog_func(line)
75 --
76 2.4.9

Replies