# 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)