From 8cab14fe47b3f2d31a193c200644c32c0d403ec7 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 8 Oct 2012 08:43:21 -0700 Subject: spawn: setup _exit finally block before fork This is the most reliable way to handle the race condition. --- pym/portage/process.py | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/pym/portage/process.py b/pym/portage/process.py index a3461f474..fbfbde049 100644 --- a/pym/portage/process.py +++ b/pym/portage/process.py @@ -256,24 +256,33 @@ def spawn(mycommand, env={}, opt_name=None, fd_pipes=None, returnpid=False, fd_pipes[1] = pw fd_pipes[2] = pw - pid = os.fork() + parent_pid = os.getpid() + pid = None + try: + pid = os.fork() - if pid == 0: - try: - _exec(binary, mycommand, opt_name, fd_pipes, - env, gid, groups, uid, umask, pre_exec) - except SystemExit: - raise - except Exception as e: - # We need to catch _any_ exception so that it doesn't - # propagate out of this function and cause exiting - # with anything other than os._exit() - writemsg("%s:\n %s\n" % (e, " ".join(mycommand)), noiselevel=-1) - traceback.print_exc() - sys.stderr.flush() - finally: - # Call os._exit() from finally block, in order to suppress any - # finally blocks from earlier in the call stack. See bug #345289. + if pid == 0: + try: + _exec(binary, mycommand, opt_name, fd_pipes, + env, gid, groups, uid, umask, pre_exec) + except SystemExit: + raise + except Exception as e: + # We need to catch _any_ exception so that it doesn't + # propagate out of this function and cause exiting + # with anything other than os._exit() + writemsg("%s:\n %s\n" % (e, " ".join(mycommand)), + noiselevel=-1) + traceback.print_exc() + sys.stderr.flush() + + finally: + if pid == 0 or (pid is None and os.getpid() != parent_pid): + # Call os._exit() from a finally block in order + # to suppress any finally blocks from earlier + # in the call stack (see bug #345289). This + # finally block has to be setup before the fork + # in order to avoid a race condition. os._exit(1) if not isinstance(pid, int): -- cgit v1.2.3-1-g7c22