blob: bac73686665d0aed305244d2ab0243263542f4c6 [file] [log] [blame]
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging, os, signal, time
import common
from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import constants, cros_logging, cros_ui, login
class desktopui_HangDetector(test.test):
"""
This class enables browser process hang detection, simulates a hang
by sending a SIGSTOP to the browser, and then checks to see that it
got killed and restarted successfully -- without the UI getting bounced.
"""
version = 1
def initialize(self):
self._pauser = cros_logging.LogRotationPauser()
self._pauser.begin()
def _get_oldest_pid_by_name(self, name):
try:
pid = utils.get_oldest_pid_by_name(name)
logging.debug('Found %d for %s', pid, name)
except error.CmdError as e:
raise error.TestError('Could not find pid of %s: %r' % (name, e))
except ValueError as e:
raise error.TestError('Got bad pid looking up %s: %r' % (name, e))
if not pid:
raise error.TestError('Got no pid looking up %s' % name)
return pid
def run_once(self):
# Create magic file to enable browser liveness checking and
# bounce the session manager to pick up the flag file.
cros_ui.stop()
os.mknod(constants.ENABLE_BROWSER_HANG_DETECTION_FILE)
cros_ui.start()
browser_pid = self._get_oldest_pid_by_name(constants.BROWSER)
sm_pid = self._get_oldest_pid_by_name(constants.SESSION_MANAGER)
# Reading the log is the best way to watch for the hang detector.
reader = cros_logging.LogReader()
reader.set_start_by_current()
# To simulate a hang, STOP the browser and wait for it to get
# hit by the session manager. It won't actually exit until it gets
# a SIGCONT, though.
try:
os.kill(browser_pid, signal.SIGSTOP) # Simulate hang.
except OSError as e:
raise error.TestError('Cannot STOP browser: %r' % e)
# Watch for hang detection.
utils.poll_for_condition(
condition=lambda: reader.can_find('Aborting browser process.'),
exception=utils.TimeoutError('Waiting for hang detector.'),
sleep_interval=5,
timeout=60)
try:
os.kill(browser_pid, signal.SIGCONT) # Allow browser to die.
except OSError as e:
raise error.TestError('Cannot CONT browser: %r' % e)
# Wait for old browser process to be gone.
utils.poll_for_condition(
condition= lambda: utils.pid_is_alive(browser_pid),
exception=utils.TimeoutError(
'Browser does not seem to have restarted!'),
timeout=60)
# Wait for new browser to come up.
login.wait_for_browser()
if sm_pid != self._get_oldest_pid_by_name(constants.SESSION_MANAGER):
raise error.TestFail('session_manager seems to have restarted')
def cleanup(self):
if os.path.exists(constants.ENABLE_BROWSER_HANG_DETECTION_FILE):
os.remove(constants.ENABLE_BROWSER_HANG_DETECTION_FILE)
self._pauser.end()