diff options
author | Zac Medico <zmedico@gentoo.org> | 2012-10-08 09:03:24 -0700 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2012-10-08 09:03:24 -0700 |
commit | dd81d7cd798d223f559a4fb885f8cc52e2881c81 (patch) | |
tree | 1f9cc3b49f90efa3101020451e7d3c4d880246f3 /pym/portage/util | |
parent | 8cab14fe47b3f2d31a193c200644c32c0d403ec7 (diff) | |
download | portage-dd81d7cd798d223f559a4fb885f8cc52e2881c81.tar.gz portage-dd81d7cd798d223f559a4fb885f8cc52e2881c81.tar.bz2 portage-dd81d7cd798d223f559a4fb885f8cc52e2881c81.zip |
ForkProcess: set _exit finally block before fork
This is the most reliable way to handle the race condition.
Diffstat (limited to 'pym/portage/util')
-rw-r--r-- | pym/portage/util/_async/ForkProcess.py | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/pym/portage/util/_async/ForkProcess.py b/pym/portage/util/_async/ForkProcess.py index 96ce3d98a..17be02a6e 100644 --- a/pym/portage/util/_async/ForkProcess.py +++ b/pym/portage/util/_async/ForkProcess.py @@ -17,36 +17,47 @@ class ForkProcess(SpawnProcess): Fork a subprocess, apply local settings, and call fetch(). """ - pid = os.fork() - if pid != 0: - if not isinstance(pid, int): - raise AssertionError( - "fork returned non-integer: %s" % (repr(pid),)) - portage.process.spawned_pids.append(pid) - return [pid] - - rval = 1 + parent_pid = os.getpid() + pid = None try: + pid = os.fork() + + if pid != 0: + if not isinstance(pid, int): + raise AssertionError( + "fork returned non-integer: %s" % (repr(pid),)) + portage.process.spawned_pids.append(pid) + return [pid] + + rval = 1 + try: + + # Use default signal handlers in order to avoid problems + # killing subprocesses as reported in bug #353239. + signal.signal(signal.SIGINT, signal.SIG_DFL) + signal.signal(signal.SIGTERM, signal.SIG_DFL) + + portage.locks._close_fds() + # We don't exec, so use close_fds=False + # (see _setup_pipes docstring). + portage.process._setup_pipes(fd_pipes, close_fds=False) + + rval = self._run() + except SystemExit: + raise + except: + traceback.print_exc() + finally: + os._exit(rval) - # Use default signal handlers in order to avoid problems - # killing subprocesses as reported in bug #353239. - signal.signal(signal.SIGINT, signal.SIG_DFL) - signal.signal(signal.SIGTERM, signal.SIG_DFL) - - portage.locks._close_fds() - # We don't exec, so use close_fds=False - # (see _setup_pipes docstring). - portage.process._setup_pipes(fd_pipes, close_fds=False) - - rval = self._run() - except SystemExit: - raise - except: - traceback.print_exc() finally: - # Call os._exit() from finally block, in order to suppress any - # finally blocks from earlier in the call stack. See bug #345289. - os._exit(rval) + 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) def _run(self): raise NotImplementedError(self) |