Signed-off-by: Michał Górny <mgo...@gentoo.org>
---
 bin/pid-ns-init        | 30 ++++++++++++++++++++++++++++++
 lib/portage/process.py | 11 ++++++-----
 2 files changed, 36 insertions(+), 5 deletions(-)
 create mode 100644 bin/pid-ns-init

New in v3: pid-ns-init handles exit-by-signal properly.

diff --git a/bin/pid-ns-init b/bin/pid-ns-init
new file mode 100644
index 000000000..843257b70
--- /dev/null
+++ b/bin/pid-ns-init
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+# Copyright 2018 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import os
+import sys
+
+
+def main(argv):
+       if len(argv) < 2:
+               return 'Usage: {} <main-child-pid>'.format(argv[0])
+       main_child_pid = int(argv[1])
+
+       # wait for child processes
+       while True:
+               pid, status = os.wait()
+               if pid == main_child_pid:
+                       if os.WIFEXITED(status):
+                               return os.WEXITSTATUS(status)
+                       elif os.WIFSIGNALED(status):
+                               os.kill(os.getpid(), os.WTERMSIG(status))
+                       # go to the unreachable place
+                       break
+
+       # this should never be reached
+       return 127
+
+
+if __name__ == '__main__':
+       sys.exit(main(sys.argv))
diff --git a/lib/portage/process.py b/lib/portage/process.py
index dee126c3c..75ec299f0 100644
--- a/lib/portage/process.py
+++ b/lib/portage/process.py
@@ -544,13 +544,14 @@ def _exec(binary, mycommand, opt_name, fd_pipes, env, 
gid, groups, uid, umask,
                                        else:
                                                if unshare_pid:
                                                        # pid namespace 
requires us to become init
-                                                       # TODO: do init-ty stuff
-                                                       # therefore, fork() ASAP
                                                        fork_ret = os.fork()
                                                        if fork_ret != 0:
-                                                               pid, status = 
os.waitpid(fork_ret, 0)
-                                                               assert pid == 
fork_ret
-                                                               os._exit(status)
+                                                               
os.execv(portage._python_interpreter, [
+                                                                       
portage._python_interpreter,
+                                                                       
os.path.join(portage._bin_path,
+                                                                               
'pid-ns-init'),
+                                                                       '%s' % 
fork_ret,
+                                                                       ])
                                                if unshare_mount:
                                                        # mark the whole 
filesystem as slave to avoid
                                                        # mounts escaping the 
namespace
-- 
2.19.1


Reply via email to