blob: c4b27e7d7e53b3851e63301c84b8d0c3afe98433 [file] [log] [blame]
# Copyright (c) 2013 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
from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import constants, cros_ui
class UIStopped(Exception):
"""Raised when the UI seems to have stopped respawning."""
pass
class desktopui_CrashyReboot(test.test):
"""Drive device to handle a too-crashy UI.
Run by desktopui_CrashyRebootServer.
"""
version = 1
UNREASONABLY_HIGH_RESPAWN_COUNT=90
def _nuke_browser_with_prejudice_and_check_for_ui_stop(self):
"""Nuke the browser with prejudice, check to see if the UI is down."""
try:
utils.nuke_process_by_name(constants.BROWSER, with_prejudice=True)
except error.AutoservPidAlreadyDeadError:
pass
return not cros_ui.is_up()
def _nuke_browser_until_ui_goes_down(self):
"""Nuke the browser continuously until it stops respawning.
@raises utils.TimeoutError if the ui doesn't stop respawning.
"""
utils.poll_for_condition(
condition=self._nuke_browser_with_prejudice_and_check_for_ui_stop,
timeout=60,
desc='ui to stop respawning, or the device to reboot')
def run_once(self, expect_reboot=False):
# Ensure the UI is running.
logging.debug('Restarting UI to ensure that it\'s running.')
cros_ui.stop(allow_fail=True)
cros_ui.start(wait_for_login_prompt=True)
# Since there is no 100% reliable way to determine that the
# browser process we're interested in is gone, we need to use
# a polling interval to continuously send KILL signals. This
# puts the test code in an unavoidable race with the UI
# respawning logic being tested. If the UI is down at the
# instant we check, it could mean that the UI is done
# respawning, the UI is about to respawn, or the device could
# already be rebooting. In all likelihood, the UI is coming
# back and we'll need to kill it all over again. This is why
# the code below polls the UI status for a number of seconds:
# to be more confident that the UI went down and is staying down.
try:
while True:
utils.poll_for_condition(condition=cros_ui.is_up,
timeout=5,
exception=UIStopped('As expected'))
self._nuke_browser_until_ui_goes_down()
except UIStopped:
pass
except utils.TimeoutError as te:
raise error.TestFail(te)
if expect_reboot:
raise error.TestFail('UI stopped respawning instead of rebooting.')
def cleanup(self):
# If the UI is already up, we want to tolerate that.
cros_ui.start(allow_fail=True)