summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2012-10-08 08:43:21 -0700
committerZac Medico <zmedico@gentoo.org>2012-10-08 08:43:21 -0700
commit8cab14fe47b3f2d31a193c200644c32c0d403ec7 (patch)
tree91e179249cb50668d1055d38d3dabc8d6601ecaf
parent56fbe3fe63adf4e7c5b47400182cd857d145d5b0 (diff)
downloadportage-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.py43
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):