| # Copyright Martin J. Bligh, Andy Whitcroft, 2006 |
| # |
| # Shell class for a test, inherited by all individual tests |
| # |
| # Methods: |
| # __init__ initialise |
| # initialize run once for each job |
| # setup run once for each new version of the test installed |
| # run run the test (wrapped by job.run_test()) |
| # |
| # Data: |
| # job backreference to the job this test instance is part of |
| # outputdir eg. results/<job>/<testname.tag> |
| # resultsdir eg. results/<job>/<testname.tag>/results |
| # profdir eg. results/<job>/<testname.tag>/profiling |
| # debugdir eg. results/<job>/<testname.tag>/debug |
| # bindir eg. tests/<test> |
| # src eg. tests/<test>/src |
| # tmpdir eg. tmp/<testname.tag> |
| |
| import os, logging, resource, glob |
| |
| from autotest_lib.client.common_lib import utils |
| from autotest_lib.client.common_lib import test as common_test |
| from autotest_lib.client.bin import os_dep |
| |
| |
| class test(common_test.base_test): |
| # Segmentation fault handling is something that is desirable only for |
| # client side tests. |
| def configure_crash_handler(self): |
| """ |
| Configure the crash handler by: |
| * Setting up core size to unlimited |
| * Putting an appropriate crash handler on /proc/sys/kernel/core_pattern |
| * Create files that the crash handler will use to figure which tests |
| are active at a given moment |
| |
| The crash handler will pick up the core file and write it to |
| self.debugdir, and perform analysis on it to generate a report. The |
| program also outputs some results to syslog. |
| |
| If multiple tests are running, an attempt to verify if we still have |
| the old PID on the system process table to determine whether it is a |
| parent of the current test execution. If we can't determine it, the |
| core file and the report file will be copied to all test debug dirs. |
| """ |
| self.crash_handling_enabled = False |
| |
| # make sure this script will run with a new enough python to work |
| cmd = ("python -c 'import sys; " |
| "print sys.version_info[0], sys.version_info[1]'") |
| result = utils.run(cmd, ignore_status=True) |
| if result.exit_status != 0: |
| logging.warning('System python is too old, crash handling disabled') |
| return |
| major, minor = [int(x) for x in result.stdout.strip().split()] |
| if (major, minor) < (2, 4): |
| logging.warning('System python is too old, crash handling disabled') |
| return |
| |
| self.pattern_file = '/proc/sys/kernel/core_pattern' |
| try: |
| # Enable core dumps |
| resource.setrlimit(resource.RLIMIT_CORE, (-1, -1)) |
| # Trying to backup core pattern and register our script |
| self.core_pattern_backup = open(self.pattern_file, 'r').read() |
| pattern_file = open(self.pattern_file, 'w') |
| tools_dir = os.path.join(self.autodir, 'tools') |
| crash_handler_path = os.path.join(tools_dir, 'crash_handler.py') |
| pattern_file.write('|' + crash_handler_path + ' %p %t %u %s %h %e') |
| # Writing the files that the crash handler is going to use |
| self.debugdir_tmp_file = ('/tmp/autotest_results_dir.%s' % |
| os.getpid()) |
| utils.open_write_close(self.debugdir_tmp_file, self.debugdir + "\n") |
| except Exception, e: |
| logging.warning('Crash handling disabled: %s', e) |
| else: |
| self.crash_handling_enabled = True |
| try: |
| os_dep.command('gdb') |
| except ValueError: |
| logging.warning('Could not find GDB installed. Crash handling ' |
| 'will operate with limited functionality') |
| logging.debug('Crash handling enabled') |
| |
| |
| def crash_handler_report(self): |
| """ |
| If core dumps are found on the debugdir after the execution of the |
| test, let the user know. |
| """ |
| if self.crash_handling_enabled: |
| # Remove the debugdir info file |
| os.unlink(self.debugdir_tmp_file) |
| # Restore the core pattern backup |
| try: |
| utils.open_write_close(self.pattern_file, |
| self.core_pattern_backup) |
| except EnvironmentError: |
| pass |
| # Let the user know if core dumps were generated during the test |
| core_dirs = glob.glob('%s/crash.*' % self.debugdir) |
| if core_dirs: |
| logging.warning('Programs crashed during test execution') |
| for dir in core_dirs: |
| logging.warning('Please verify %s for more info', dir) |
| |
| |
| def runtest(job, url, tag, args, dargs): |
| # Leave some autotest bread crumbs in the system logs. |
| utils.system('logger "autotest runtest %s"' % url, ignore_status=True) |
| common_test.runtest(job, url, tag, args, dargs, locals(), globals(), |
| job.sysinfo.log_before_each_test, |
| job.sysinfo.log_after_each_test, |
| job.sysinfo.log_before_each_iteration, |
| job.sysinfo.log_after_each_iteration) |