From 12d2ff4f018c826c750896e8085cd53a589a8521 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Fri, 3 Sep 2010 14:17:12 -0700 Subject: [PATCH] Bug #335777 - Add a 40 second timeout in ebuild-ipc.py, so that if an orphan is left for any reason then it will exit with an error message instead of hanging indefinitely. --- bin/ebuild-ipc.py | 21 ++++++++++++++++++++- pym/portage/exception.py | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/bin/ebuild-ipc.py b/bin/ebuild-ipc.py index 52fb08226..b4a1f7767 100755 --- a/bin/ebuild-ipc.py +++ b/bin/ebuild-ipc.py @@ -5,11 +5,13 @@ # This is a helper which ebuild processes can use # to communicate with portage's main python process. +import logging import os import pickle import select import signal import sys +import time def debug_signal(signum, frame): import pdb @@ -30,6 +32,8 @@ import portage class EbuildIpc(object): + _COMMUNICATE_TIMEOUT_SECONDS = 40 + def __init__(self): self.fifo_dir = os.environ['PORTAGE_BUILDDIR'] self.ipc_in_fifo = os.path.join(self.fifo_dir, '.ipc_in') @@ -37,13 +41,28 @@ class EbuildIpc(object): self.ipc_lock_file = os.path.join(self.fifo_dir, '.ipc_lock') def communicate(self, args): + # Make locks quiet since unintended locking messages displayed on # stdout could corrupt the intended output of this program. portage.locks._quiet = True lock_obj = portage.locks.lockfile(self.ipc_lock_file, unlinkfile=True) + start_time = time.time() + try: - return self._communicate(args) + signal.signal(signal.SIGALRM, portage.exception.AlarmSignal.signal_handler) + signal.alarm(self._COMMUNICATE_TIMEOUT_SECONDS) + returncode = self._communicate(args) + signal.alarm(0) + return returncode + except portage.exception.AlarmSignal: + time_elapsed = time.time() - start_time + portage.util.writemsg_level( + ('ebuild-ipc timed out after %d seconds\n') % \ + (time_elapsed,), + level=logging.ERROR, noiselevel=-1) + return 1 finally: + signal.alarm(0) portage.locks.unlockfile(lock_obj) def _communicate(self, args): diff --git a/pym/portage/exception.py b/pym/portage/exception.py index 9564af98a..b0f9ad8eb 100644 --- a/pym/portage/exception.py +++ b/pym/portage/exception.py @@ -80,6 +80,20 @@ class TryAgain(PortageException): from errno import EAGAIN as errno """Try again""" +class TimeoutException(PortageException): + from errno import ETIME as errno + +class AlarmSignal(TimeoutException): + def __init__(self, value, signum=None, frame=None): + TimeoutException.__init__(self, value) + self.signum = signum + self.frame = frame + + @classmethod + def signal_handler(cls, signum, frame): + raise AlarmSignal("alarm signal", + signum=signum, frame=frame) + class ReadOnlyFileSystem(PortageException): """Read-only file system""" -- 2.26.2