• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6from autotest_lib.client.bin import test, utils
7from autotest_lib.client.common_lib import error
8from autotest_lib.client.cros import constants, cros_ui
9
10
11class UIStopped(Exception):
12    """Raised when the UI seems to have stopped respawning."""
13    pass
14
15
16class desktopui_CrashyReboot(test.test):
17    """Drive device to handle a too-crashy UI.
18
19    Run by desktopui_CrashyRebootServer.
20    """
21    version = 1
22
23    UNREASONABLY_HIGH_RESPAWN_COUNT=90
24
25
26    def _nuke_browser_with_prejudice_and_check_for_ui_stop(self):
27        """Nuke the browser with prejudice, check to see if the UI is down."""
28        try:
29            utils.nuke_process_by_name(constants.BROWSER, with_prejudice=True)
30        except error.AutoservPidAlreadyDeadError:
31            pass
32        return not cros_ui.is_up()
33
34
35    def _nuke_browser_until_ui_goes_down(self):
36        """Nuke the browser continuously until it stops respawning.
37
38        @raises utils.TimeoutError if the ui doesn't stop respawning.
39        """
40        utils.poll_for_condition(
41            condition=self._nuke_browser_with_prejudice_and_check_for_ui_stop,
42            timeout=60,
43            desc='ui to stop respawning, or the device to reboot')
44
45
46    def run_once(self, expect_reboot=False):
47        # Ensure the UI is running.
48        logging.debug('Restarting UI to ensure that it\'s running.')
49        cros_ui.stop(allow_fail=True)
50        cros_ui.start(wait_for_login_prompt=True)
51
52        # Since there is no 100% reliable way to determine that the
53        # browser process we're interested in is gone, we need to use
54        # a polling interval to continuously send KILL signals. This
55        # puts the test code in an unavoidable race with the UI
56        # respawning logic being tested. If the UI is down at the
57        # instant we check, it could mean that the UI is done
58        # respawning, the UI is about to respawn, or the device could
59        # already be rebooting. In all likelihood, the UI is coming
60        # back and we'll need to kill it all over again. This is why
61        # the code below polls the UI status for a number of seconds:
62        # to be more confident that the UI went down and is staying down.
63        try:
64            while True:
65                utils.poll_for_condition(condition=cros_ui.is_up,
66                                         timeout=5,
67                                         exception=UIStopped('As expected'))
68                self._nuke_browser_until_ui_goes_down()
69        except UIStopped:
70            pass
71        except utils.TimeoutError as te:
72            raise error.TestFail(te)
73
74        if expect_reboot:
75            raise error.TestFail('UI stopped respawning instead of rebooting.')
76
77
78    def cleanup(self):
79        # If the UI is already up, we want to tolerate that.
80        cros_ui.start(allow_fail=True)
81