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] pid-ns-init: fix child process signal disposition (bug 675828)
Date: Sun, 20 Jan 2019 04:51:38
Message-Id: 20190120044900.5745-1-zmedico@gentoo.org
1 Use subprocess.Popen to correctly configure the signal disposition
2 of the child process, since os.fork leaves the signal disposition
3 in a state which may be inappropriate for various signals including
4 SIGPIPE, SIGQUIT, SIGTERM, and SIGINT. For python implementations
5 other that CPython >= 3, use preexec_fn to manually configure the
6 signal disposition (I have found that this is necessary for CPython
7 2.7 and all PyPy versions tested, including PyPy3).
8
9 Bug: https://bugs.gentoo.org/675828
10 Signed-off-by: Zac Medico <zmedico@g.o>
11 ---
12 bin/pid-ns-init | 31 ++++++++++++++++++++++++++++---
13 1 file changed, 28 insertions(+), 3 deletions(-)
14
15 diff --git a/bin/pid-ns-init b/bin/pid-ns-init
16 index 182d00a43..86029f983 100644
17 --- a/bin/pid-ns-init
18 +++ b/bin/pid-ns-init
19 @@ -2,18 +2,37 @@
20 # Copyright 2018-2019 Gentoo Authors
21 # Distributed under the terms of the GNU General Public License v2
22
23 +import errno
24 import functools
25 import os
26 +import platform
27 import signal
28 +import subprocess
29 import sys
30
31
32 +if sys.version_info.major < 3 or platform.python_implementation() != 'CPython':
33 + def signal_disposition_preexec():
34 + for signum in (
35 + signal.SIGHUP,
36 + signal.SIGINT,
37 + signal.SIGPIPE,
38 + signal.SIGQUIT,
39 + signal.SIGTERM,
40 + ):
41 + signal.signal(signum, signal.SIG_DFL)
42 +else:
43 + # CPython >= 3 subprocess.Popen handles this internally.
44 + signal_disposition_preexec = None
45 +
46 +
47 KILL_SIGNALS = (
48 signal.SIGINT,
49 signal.SIGTERM,
50 signal.SIGHUP,
51 )
52
53 +
54 def forward_kill_signal(main_child_pid, signum, frame):
55 os.kill(main_child_pid, signum)
56
57 @@ -28,14 +47,15 @@ def main(argv):
58 # (forwarding signals to init and forwarding exit status to the parent
59 # process).
60 main_child_pid = int(argv[1])
61 + proc = None
62 else:
63 # The current process is init (pid 1) in a child pid namespace.
64 binary = argv[1]
65 args = argv[2:]
66
67 - main_child_pid = os.fork()
68 - if main_child_pid == 0:
69 - os.execv(binary, args)
70 + proc = subprocess.Popen(args, executable=binary,
71 + preexec_fn=signal_disposition_preexec)
72 + main_child_pid = proc.pid
73
74 sig_handler = functools.partial(forward_kill_signal, main_child_pid)
75 for signum in KILL_SIGNALS:
76 @@ -50,6 +70,11 @@ def main(argv):
77 continue
78 raise
79 if pid == main_child_pid:
80 + if proc is not None:
81 + # Suppress warning messages like this:
82 + # ResourceWarning: subprocess 1234 is still running
83 + proc.returncode = 0
84 +
85 if os.WIFEXITED(status):
86 return os.WEXITSTATUS(status)
87 elif os.WIFSIGNALED(status):
88 --
89 2.18.1

Replies