blob: fbd6ebfab1ff352ec414c7a5009dafe006d322cf [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 common, logging, os, time
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import constants
# Log messages used to signal when we're restarting UI. Used to detect
# crashes by cros_ui_test.UITest.
UI_RESTART_ATTEMPT_MSG = ' Attempting StopSession...'
UI_RESTART_COMPLETE_MSG = ' StopSession complete.'
RESTART_UI_TIMEOUT = 90 # longer because we may be crash dumping now.
def get_login_prompt_state(host=None):
"""Return the "state" of the most recent login.
The returned value will change each time Chrome restarts and
displays the login screen. The change in the value can be used
to detect a successful Chrome startup.
host: If not None, a host object on which to test Chrome
state, rather than running commands on the local host.
if host:
def wait_for_chrome_ready(old_state, host=None, timeout=RESTART_UI_TIMEOUT):
"""Wait until a new Chrome login prompt is on screen and ready.
The standard formula to check whether the prompt has appeared yet
is with a pattern like the following:
state = get_login_prompt_state()
old_state: state of the login prompt prior to restarting
host: If not None, a host object on which to test Chrome
state, rather than running commands on the local host.
timeout: float number of seconds to wait
TimeoutError: Login prompt didn't get up before timeout
condition=lambda: old_state != get_login_prompt_state(host),
exception=utils.TimeoutError('Timed out waiting for login prompt'),
timeout=timeout, sleep_interval=1.0)
def stop_and_wait_for_chrome_to_exit(timeout_secs=40):
"""Stops the UI and waits for chrome to exit.
Stops the UI and waits for all chrome processes to exit or until
timeout_secs is reached.
timeout_secs: float number of seconds to wait.
True upon successfully stopping the UI and all chrome processes exiting.
False otherwise.
status = stop(allow_fail=True)
if status:
logging.error('stop ui returned non-zero status: %s', status)
return False
start_time = time.time()
while time.time() - start_time < timeout_secs:
status = utils.system('pgrep chrome', ignore_status=True)
if status == 1: return True
logging.error('stop ui failed to stop chrome within %s seconds',
return False
def stop(allow_fail=False):
return utils.system("stop ui", ignore_status=allow_fail)
def start(allow_fail=False, wait_for_login_prompt=True):
"""Start the login manager and wait for the prompt to show up."""
state = get_login_prompt_state()
result = utils.system("start ui", ignore_status=allow_fail)
# If allow_fail is set, the caller might be calling us when the UI job
# is already running. In that case, the above command fails.
if result == 0 and wait_for_login_prompt:
return result
def restart(report_stop_failure=False):
"""Restart the session manager.
- If the user is logged in, the session will be terminated.
- If the UI is currently down, just go ahead and bring it up unless the
caller has requested that a failure to stop be reported.
- To ensure all processes are up and ready, this function will wait
for the login prompt to show up and be marked as visible.
@param report_stop_failure: False by default, set to True if you care about
the UI being up at the time of call and
successfully torn down by this call.
state = get_login_prompt_state()
# Log what we're about to do to /var/log/messages. Used to log crashes later
# in cleanup by cros_ui_test.UITest.
utils.system('logger "%s"' % UI_RESTART_ATTEMPT_MSG)
if stop(allow_fail=not report_stop_failure) != 0:
raise error.TestError('Could not stop session')
# Wait for login prompt to appear to indicate that all processes are
# up and running again.
utils.system('logger "%s"' % UI_RESTART_COMPLETE_MSG)
def nuke():
"""Nuke the login manager, waiting for it to restart."""
restart(lambda: utils.nuke_process_by_name(constants.SESSION_MANAGER))
def is_up():
"""Return True if the UI is up, False if not."""
return 'start/running' in utils.system_output('initctl status ui')
def clear_respawn_state():
"""Removes bookkeeping related to respawning crashed UI."""
for filename in [constants.UI_RESPAWN_TIMESTAMPS_FILE,
except OSError:
pass # It's already gone.