1# Copyright Martin J. Bligh, Andy Whitcroft, 2006 2# 3# Shell class for a test, inherited by all individual tests 4# 5# Methods: 6# __init__ initialise 7# initialize run once for each job 8# setup run once for each new version of the test installed 9# run run the test (wrapped by job.run_test()) 10# 11# Data: 12# job backreference to the job this test instance is part of 13# outputdir eg. results/<job>/<testname.tag> 14# resultsdir eg. results/<job>/<testname.tag>/results 15# profdir eg. results/<job>/<testname.tag>/profiling 16# debugdir eg. results/<job>/<testname.tag>/debug 17# bindir eg. tests/<test> 18# src eg. tests/<test>/src 19# tmpdir eg. tmp/<testname.tag> 20 21import os, logging, resource, glob 22 23from autotest_lib.client.common_lib import utils 24from autotest_lib.client.common_lib import test as common_test 25from autotest_lib.client.bin import os_dep 26 27 28class test(common_test.base_test): 29 # Segmentation fault handling is something that is desirable only for 30 # client side tests. 31 def configure_crash_handler(self): 32 """ 33 Configure the crash handler by: 34 * Setting up core size to unlimited 35 * Putting an appropriate crash handler on /proc/sys/kernel/core_pattern 36 * Create files that the crash handler will use to figure which tests 37 are active at a given moment 38 39 The crash handler will pick up the core file and write it to 40 self.debugdir, and perform analysis on it to generate a report. The 41 program also outputs some results to syslog. 42 43 If multiple tests are running, an attempt to verify if we still have 44 the old PID on the system process table to determine whether it is a 45 parent of the current test execution. If we can't determine it, the 46 core file and the report file will be copied to all test debug dirs. 47 """ 48 self.crash_handling_enabled = False 49 50 # make sure this script will run with a new enough python to work 51 cmd = ("python -c 'import sys; " 52 "print sys.version_info[0], sys.version_info[1]'") 53 result = utils.run(cmd, ignore_status=True) 54 if result.exit_status != 0: 55 logging.warning('System python is too old, crash handling disabled') 56 return 57 major, minor = [int(x) for x in result.stdout.strip().split()] 58 if (major, minor) < (2, 4): 59 logging.warning('System python is too old, crash handling disabled') 60 return 61 62 self.pattern_file = '/proc/sys/kernel/core_pattern' 63 try: 64 # Enable core dumps 65 resource.setrlimit(resource.RLIMIT_CORE, (-1, -1)) 66 # Trying to backup core pattern and register our script 67 self.core_pattern_backup = open(self.pattern_file, 'r').read() 68 pattern_file = open(self.pattern_file, 'w') 69 tools_dir = os.path.join(self.autodir, 'tools') 70 crash_handler_path = os.path.join(tools_dir, 'crash_handler.py') 71 pattern_file.write('|' + crash_handler_path + ' %p %t %u %s %h %e') 72 # Writing the files that the crash handler is going to use 73 self.debugdir_tmp_file = ('/tmp/autotest_results_dir.%s' % 74 os.getpid()) 75 utils.open_write_close(self.debugdir_tmp_file, self.debugdir + "\n") 76 except Exception, e: 77 logging.warning('Crash handling disabled: %s', e) 78 else: 79 self.crash_handling_enabled = True 80 try: 81 os_dep.command('gdb') 82 except ValueError: 83 logging.warning('Could not find GDB installed. Crash handling ' 84 'will operate with limited functionality') 85 logging.debug('Crash handling enabled') 86 87 88 def crash_handler_report(self): 89 """ 90 If core dumps are found on the debugdir after the execution of the 91 test, let the user know. 92 """ 93 if self.crash_handling_enabled: 94 # Remove the debugdir info file 95 os.unlink(self.debugdir_tmp_file) 96 # Restore the core pattern backup 97 try: 98 utils.open_write_close(self.pattern_file, 99 self.core_pattern_backup) 100 except EnvironmentError: 101 pass 102 # Let the user know if core dumps were generated during the test 103 core_dirs = glob.glob('%s/crash.*' % self.debugdir) 104 if core_dirs: 105 logging.warning('Programs crashed during test execution') 106 for dir in core_dirs: 107 logging.warning('Please verify %s for more info', dir) 108 109 110def runtest(job, url, tag, args, dargs): 111 # Leave some autotest bread crumbs in the system logs. 112 utils.system('logger "autotest runtest %s"' % url, ignore_status=True) 113 common_test.runtest(job, url, tag, args, dargs, locals(), globals(), 114 job.sysinfo.log_before_each_test, 115 job.sysinfo.log_after_each_test, 116 job.sysinfo.log_before_each_iteration, 117 job.sysinfo.log_after_each_iteration) 118