1 |
commit: 007236f06506744fdb67910af5d7fb69783dbfe1 |
2 |
Author: Zac Medico <zmedico <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sat Nov 21 19:41:07 2015 +0000 |
4 |
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> |
5 |
CommitDate: Mon Nov 23 16:28:55 2015 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=007236f0 |
7 |
|
8 |
SpawnProcess: re-check cgroup.procs until empty (bug 566420) |
9 |
|
10 |
For subshell die support (bug 465008), re-check cgroup.procs until it's |
11 |
empty, in case any of the listed processes fork before we've had a chance |
12 |
to kill them. |
13 |
|
14 |
X-Gentoo-Bug: 566420 |
15 |
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=566420 |
16 |
Acked-by: Alexander Berntsen <bernalex <AT> gentoo.org> |
17 |
|
18 |
pym/_emerge/SpawnProcess.py | 31 ++++++++++++++++++++++++++++--- |
19 |
1 file changed, 28 insertions(+), 3 deletions(-) |
20 |
|
21 |
diff --git a/pym/_emerge/SpawnProcess.py b/pym/_emerge/SpawnProcess.py |
22 |
index b4b4b5b..e046640 100644 |
23 |
--- a/pym/_emerge/SpawnProcess.py |
24 |
+++ b/pym/_emerge/SpawnProcess.py |
25 |
@@ -16,6 +16,8 @@ from _emerge.SubProcess import SubProcess |
26 |
import portage |
27 |
from portage import os |
28 |
from portage.const import BASH_BINARY |
29 |
+from portage.localization import _ |
30 |
+from portage.output import EOutput |
31 |
from portage.util import writemsg_level |
32 |
from portage.util._async.PipeLogger import PipeLogger |
33 |
|
34 |
@@ -35,6 +37,10 @@ class SpawnProcess(SubProcess): |
35 |
__slots__ = ("args",) + \ |
36 |
_spawn_kwarg_names + ("_pipe_logger", "_selinux_type",) |
37 |
|
38 |
+ # Max number of attempts to kill the processes listed in cgroup.procs, |
39 |
+ # given that processes may fork before they can be killed. |
40 |
+ _CGROUP_CLEANUP_RETRY_MAX = 8 |
41 |
+ |
42 |
def _start(self): |
43 |
|
44 |
if self.fd_pipes is None: |
45 |
@@ -209,10 +215,24 @@ class SpawnProcess(SubProcess): |
46 |
elif e.errno != errno.ESRCH: |
47 |
raise |
48 |
|
49 |
- # step 1: kill all orphans |
50 |
- pids = get_pids(self.cgroup) |
51 |
+ # step 1: kill all orphans (loop in case of new forks) |
52 |
+ remaining = self._CGROUP_CLEANUP_RETRY_MAX |
53 |
+ while remaining: |
54 |
+ remaining -= 1 |
55 |
+ pids = get_pids(self.cgroup) |
56 |
+ if pids: |
57 |
+ kill_all(pids, signal.SIGKILL) |
58 |
+ else: |
59 |
+ break |
60 |
+ |
61 |
if pids: |
62 |
- kill_all(pids, signal.SIGKILL) |
63 |
+ msg = [] |
64 |
+ msg.append( |
65 |
+ _("Failed to kill pid(s) in '%(cgroup)s': %(pids)s") % dict( |
66 |
+ cgroup=os.path.join(self.cgroup, 'cgroup.procs'), |
67 |
+ pids=' '.join(str(pid) for pid in pids))) |
68 |
+ |
69 |
+ self._elog('eerror', msg) |
70 |
|
71 |
# step 2: remove the cgroup |
72 |
try: |
73 |
@@ -221,3 +241,8 @@ class SpawnProcess(SubProcess): |
74 |
# it may be removed already, or busy |
75 |
# we can't do anything good about it |
76 |
pass |
77 |
+ |
78 |
+ def _elog(self, elog_funcname, lines): |
79 |
+ elog_func = getattr(EOutput(), elog_funcname) |
80 |
+ for line in lines: |
81 |
+ elog_func(line) |