diff options
author | Zac Medico <zmedico@gentoo.org> | 2012-10-08 08:43:21 -0700 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2012-10-08 08:43:21 -0700 |
commit | 8cab14fe47b3f2d31a193c200644c32c0d403ec7 (patch) | |
tree | 91e179249cb50668d1055d38d3dabc8d6601ecaf | |
parent | 56fbe3fe63adf4e7c5b47400182cd857d145d5b0 (diff) | |
download | portage-8cab14fe47b3f2d31a193c200644c32c0d403ec7.tar.gz portage-8cab14fe47b3f2d31a193c200644c32c0d403ec7.tar.bz2 portage-8cab14fe47b3f2d31a193c200644c32c0d403ec7.zip |
spawn: setup _exit finally block before fork
This is the most reliable way to handle the race condition.
-rw-r--r-- | pym/portage/process.py | 43 |
1 files 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): |