mbligh | a250805 | 2006-05-28 21:29:53 +0000 | [diff] [blame] | 1 | # Copyright Martin J. Bligh, Andy Whitcroft, 2006 |
| 2 | # |
| 3 | # Shell class for a test, inherited by all individual tests |
| 4 | # |
| 5 | # Methods: |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 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()) |
mbligh | a250805 | 2006-05-28 21:29:53 +0000 | [diff] [blame] | 10 | # |
| 11 | # Data: |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 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> |
mbligh | a250805 | 2006-05-28 21:29:53 +0000 | [diff] [blame] | 20 | |
Ilja H. Friedel | 7aded90 | 2016-03-11 23:20:31 -0800 | [diff] [blame] | 21 | import os, logging, resource, glob |
mbligh | ea397bb | 2008-02-02 19:17:51 +0000 | [diff] [blame] | 22 | |
Ilja H. Friedel | 7aded90 | 2016-03-11 23:20:31 -0800 | [diff] [blame] | 23 | from autotest_lib.client.common_lib import utils |
mbligh | beb4b42 | 2008-06-03 18:20:33 +0000 | [diff] [blame] | 24 | from autotest_lib.client.common_lib import test as common_test |
Ilja H. Friedel | 7aded90 | 2016-03-11 23:20:31 -0800 | [diff] [blame] | 25 | from autotest_lib.client.bin import os_dep |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 26 | |
apw | 9b63458 | 2006-04-22 12:40:39 +0000 | [diff] [blame] | 27 | |
mbligh | beb4b42 | 2008-06-03 18:20:33 +0000 | [diff] [blame] | 28 | class test(common_test.base_test): |
lmr | fb11887 | 2009-10-13 19:41:48 +0000 | [diff] [blame] | 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 | """ |
lmr | 3ee5f57 | 2010-06-08 18:31:33 +0000 | [diff] [blame] | 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: |
lmr | 96c1dda | 2010-06-08 20:56:29 +0000 | [diff] [blame] | 55 | logging.warning('System python is too old, crash handling disabled') |
lmr | 3ee5f57 | 2010-06-08 18:31:33 +0000 | [diff] [blame] | 56 | return |
| 57 | major, minor = [int(x) for x in result.stdout.strip().split()] |
| 58 | if (major, minor) < (2, 4): |
lmr | 96c1dda | 2010-06-08 20:56:29 +0000 | [diff] [blame] | 59 | logging.warning('System python is too old, crash handling disabled') |
lmr | 3ee5f57 | 2010-06-08 18:31:33 +0000 | [diff] [blame] | 60 | return |
| 61 | |
lmr | fb11887 | 2009-10-13 19:41:48 +0000 | [diff] [blame] | 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: |
lmr | 96c1dda | 2010-06-08 20:56:29 +0000 | [diff] [blame] | 77 | logging.warning('Crash handling disabled: %s', e) |
lmr | fb11887 | 2009-10-13 19:41:48 +0000 | [diff] [blame] | 78 | else: |
| 79 | self.crash_handling_enabled = True |
lmr | 96c1dda | 2010-06-08 20:56:29 +0000 | [diff] [blame] | 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') |
lmr | fb11887 | 2009-10-13 19:41:48 +0000 | [diff] [blame] | 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: |
lmr | fb11887 | 2009-10-13 19:41:48 +0000 | [diff] [blame] | 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 |
lmr | 7695f4c | 2010-07-22 22:41:44 +0000 | [diff] [blame] | 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) |
mbligh | 971178e | 2008-01-03 02:40:35 +0000 | [diff] [blame] | 108 | |
| 109 | |
mbligh | 53c4150 | 2007-10-23 20:45:04 +0000 | [diff] [blame] | 110 | def runtest(job, url, tag, args, dargs): |
Ilja H. Friedel | 7aded90 | 2016-03-11 23:20:31 -0800 | [diff] [blame] | 111 | # Leave some autotest bread crumbs in the system logs. |
Ilja H. Friedel | d08a4d3 | 2016-03-12 21:06:19 -0800 | [diff] [blame] | 112 | utils.system('logger "autotest runtest %s"' % url, ignore_status=True) |
jadmanski | cefe265 | 2008-10-08 21:02:27 +0000 | [diff] [blame] | 113 | common_test.runtest(job, url, tag, args, dargs, locals(), globals(), |
| 114 | job.sysinfo.log_before_each_test, |
mbligh | 4395bbd | 2009-03-25 19:34:17 +0000 | [diff] [blame] | 115 | job.sysinfo.log_after_each_test, |
| 116 | job.sysinfo.log_before_each_iteration, |
| 117 | job.sysinfo.log_after_each_iteration) |