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