Home | History | Annotate | Download | only in desktopui_HangDetector
      1 # Copyright (c) 2012 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 
      5 import logging, os, signal, time
      6 
      7 import common
      8 from autotest_lib.client.bin import test, utils
      9 from autotest_lib.client.common_lib import error
     10 from autotest_lib.client.cros import constants, cros_logging, cros_ui, login
     11 
     12 class desktopui_HangDetector(test.test):
     13     """
     14     This class enables browser process hang detection, simulates a hang
     15     by sending a SIGSTOP to the browser, and then checks to see that it
     16     got killed and restarted successfully -- without the UI getting bounced.
     17     """
     18     version = 1
     19 
     20 
     21     def initialize(self):
     22         self._pauser = cros_logging.LogRotationPauser()
     23         self._pauser.begin()
     24 
     25 
     26     def _get_oldest_pid_by_name(self, name):
     27         try:
     28             pid = utils.get_oldest_pid_by_name(name)
     29             logging.debug('Found %d for %s', pid, name)
     30         except error.CmdError as e:
     31             raise error.TestError('Could not find pid of %s: %r' % (name, e))
     32         except ValueError as e:
     33             raise error.TestError('Got bad pid looking up %s: %r' % (name, e))
     34         if not pid:
     35             raise error.TestError('Got no pid looking up %s' % name)
     36         return pid
     37 
     38 
     39     def run_once(self):
     40         # Create magic file to enable browser liveness checking and
     41         # bounce the session manager to pick up the flag file.
     42         cros_ui.stop()
     43         os.mknod(constants.ENABLE_BROWSER_HANG_DETECTION_FILE)
     44         cros_ui.start()
     45 
     46         browser_pid = self._get_oldest_pid_by_name(constants.BROWSER)
     47         sm_pid = self._get_oldest_pid_by_name(constants.SESSION_MANAGER)
     48 
     49         # Reading the log is the best way to watch for the hang detector.
     50         reader = cros_logging.LogReader()
     51         reader.set_start_by_current()
     52 
     53         # To simulate a hang, STOP the browser and wait for it to get
     54         # hit by the session manager.  It won't actually exit until it gets
     55         # a SIGCONT, though.
     56         try:
     57             os.kill(browser_pid, signal.SIGSTOP)  # Simulate hang.
     58         except OSError as e:
     59             raise error.TestError('Cannot STOP browser: %r' % e)
     60 
     61         # Watch for hang detection.
     62         utils.poll_for_condition(
     63             condition=lambda: reader.can_find('Aborting browser process.'),
     64             exception=utils.TimeoutError('Waiting for hang detector.'),
     65             sleep_interval=5,
     66             timeout=60)
     67 
     68         try:
     69             os.kill(browser_pid, signal.SIGCONT)  # Allow browser to die.
     70         except OSError as e:
     71             raise error.TestError('Cannot CONT browser: %r' % e)
     72 
     73         # Wait for old browser process to be gone.
     74         utils.poll_for_condition(
     75             condition= lambda: utils.pid_is_alive(browser_pid),
     76             exception=utils.TimeoutError(
     77                 'Browser does not seem to have restarted!'),
     78             timeout=60)
     79 
     80         # Wait for new browser to come up.
     81         login.wait_for_browser()
     82         if sm_pid != self._get_oldest_pid_by_name(constants.SESSION_MANAGER):
     83             raise error.TestFail('session_manager seems to have restarted')
     84 
     85 
     86     def cleanup(self):
     87         if os.path.exists(constants.ENABLE_BROWSER_HANG_DETECTION_FILE):
     88             os.remove(constants.ENABLE_BROWSER_HANG_DETECTION_FILE)
     89         self._pauser.end()
     90