summaryrefslogtreecommitdiffstats
path: root/pym/_emerge
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2010-08-13 07:05:12 -0700
committerZac Medico <zmedico@gentoo.org>2010-08-13 07:05:12 -0700
commit12cbc8821476dcbac38464a41f7cb336da7ac0c9 (patch)
treec985564961b89af1f3ccb72f4347e41e0dd91a90 /pym/_emerge
parent9839ae93b13fd66503b1e4f3dd33193b3a92e838 (diff)
downloadportage-12cbc8821476dcbac38464a41f7cb336da7ac0c9.tar.gz
portage-12cbc8821476dcbac38464a41f7cb336da7ac0c9.tar.bz2
portage-12cbc8821476dcbac38464a41f7cb336da7ac0c9.zip
Use EbuildIpcDaemon to replace the functionality of
EBUILD_EXIT_STATUS_FILE.
Diffstat (limited to 'pym/_emerge')
-rw-r--r--pym/_emerge/AbstractEbuildProcess.py97
1 files changed, 86 insertions, 11 deletions
diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py
index f4a87f68b..913a32d12 100644
--- a/pym/_emerge/AbstractEbuildProcess.py
+++ b/pym/_emerge/AbstractEbuildProcess.py
@@ -1,19 +1,65 @@
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
+import textwrap
from _emerge.SpawnProcess import SpawnProcess
-import portage
-portage.proxy.lazyimport.lazyimport(globals(),
- 'portage.package.ebuild.doebuild:_doebuild_exit_status_check_and_log'
-)
+from _emerge.EbuildIpcDaemon import EbuildIpcDaemon
+from portage.elog.messages import eerror
+from portage.localization import _
+from portage.package.ebuild._ipc.ExitCommand import ExitCommand
from portage import os
from portage.util._pty import _create_pty_or_pipe
class AbstractEbuildProcess(SpawnProcess):
- __slots__ = ('settings',)
+ __slots__ = ('settings',) + \
+ ('_ipc_daemon', '_exit_command',)
_phases_without_builddir = ('clean', 'cleanrm', 'depend', 'help',)
+ def _get_phase(self):
+ phase = getattr(self, 'phase', None)
+ if not phase:
+ phase = self.settings.get("EBUILD_PHASE")
+ if not phase:
+ phase = 'other'
+ return phase
+
+ def _start(self):
+
+ if self._get_phase() not in self._phases_without_builddir:
+ envs = [self.settings]
+ if self.env is not None:
+ envs.append(self.env)
+ for env in envs:
+ env['PORTAGE_IPC_DAEMON'] = "1"
+ self._exit_command = ExitCommand()
+ self._exit_command.reply_hook = self._exit_command_callback
+ input_fifo = os.path.join(
+ self.settings['PORTAGE_BUILDDIR'], '.ipc_in')
+ output_fifo = os.path.join(
+ self.settings['PORTAGE_BUILDDIR'], '.ipc_out')
+ commands = {'exit' : self._exit_command}
+ self._ipc_daemon = EbuildIpcDaemon(commands=commands,
+ input_fifo=input_fifo,
+ output_fifo=output_fifo,
+ scheduler=self.scheduler)
+ self._ipc_daemon.start()
+
+ SpawnProcess._start(self)
+
+ def _exit_command_callback(self):
+ if self._registered:
+ # Let the process exit naturally, if possible. This
+ # doesn't really do any harm since it can return
+ # long before the timeout expires.
+ self.scheduler.schedule(self._reg_id, timeout=1000)
+ if self._registered:
+ # If it doesn't exit naturally in a reasonable amount
+ # of time, kill it (solves bug #278895). We try to avoid
+ # this when possible since it makes sandbox complain about
+ # being killed by a signal.
+ self.cancel()
+
def _pipe(self, fd_pipes):
stdout_pipe = fd_pipes.get(1)
got_pty, master_fd, slave_fd = \
@@ -27,11 +73,40 @@ class AbstractEbuildProcess(SpawnProcess):
return not ('sesandbox' in self.settings.features \
and self.settings.selinux_enabled()) or os.isatty(slave_fd)
+ def _unexpected_exit(self):
+
+ phase = self._get_phase()
+
+ msg = _("The ebuild phase '%s' has exited "
+ "unexpectedly. This type of behavior "
+ "is known to be triggered "
+ "by things such as failed variable "
+ "assignments (bug #190128) or bad substitution "
+ "errors (bug #200313). Normally, before exiting, bash should "
+ "have displayed an error message above. If bash did not "
+ "produce an error message above, it's possible "
+ "that the ebuild has called `exit` when it "
+ "should have called `die` instead. This behavior may also "
+ "be triggered by a corrupt bash binary or a hardware "
+ "problem such as memory or cpu malfunction. If the problem is not "
+ "reproducible or it appears to occur randomly, then it is likely "
+ "to be triggered by a hardware problem. "
+ "If you suspect a hardware problem then you should "
+ "try some basic hardware diagnostics such as memtest. "
+ "Please do not report this as a bug unless it is consistently "
+ "reproducible and you are sure that your bash binary and hardware "
+ "are functioning properly.") % phase
+
+ for l in textwrap.wrap(msg, 72):
+ eerror(l, phase=phase, key=self.settings.mycpv)
+
def _set_returncode(self, wait_retval):
SpawnProcess._set_returncode(self, wait_retval)
- phase = self.settings.get("EBUILD_PHASE")
- if not phase:
- phase = 'other'
- if phase not in self._phases_without_builddir:
- self.returncode = _doebuild_exit_status_check_and_log(
- self.settings, phase, self.returncode)
+
+ if self._ipc_daemon is not None:
+ self._ipc_daemon.cancel()
+ if self._exit_command.exitcode is not None:
+ self.returncode = self._exit_command.exitcode
+ else:
+ self.returncode = 1
+ self._unexpected_exit()