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 |