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 5import os, os.path, logging 6from autotest_lib.client.bin import test, utils 7from autotest_lib.client.common_lib import error 8from autotest_lib.client.common_lib.cros import chrome 9from autotest_lib.client.cros.crash.crash_test import CrashTest 10 11 12# TODO(b/185707445): port this test to Tast. 13class logging_CrashServices(test.test): 14 """Verifies crash collection for system services.""" 15 version = 3 16 17 process_list = { 18 '/usr/sbin/cryptohomed' : ['.core', '.dmp', '.meta'], 19 '/usr/bin/metrics_daemon' : ['.core', '.dmp', '.meta'], 20 '/usr/bin/powerd' : ['.core', '.dmp', '.meta', '.log'], 21 # Removing rsyslogd until crbug.com/611786 is fixed. 22 # '/usr/sbin/rsyslogd': ['.core', '.dmp', '.meta'], 23 # Removing tcsd crash with reference to crbug.com/380359 24 # '/usr/sbin/tcsd' : ['.core', '.dmp', '.meta'], 25 '/usr/bin/tlsdated' : ['.core', '.dmp', '.meta'], 26 '/usr/bin/shill' : ['.core', '.dmp', '.meta'], 27 '/usr/sbin/update_engine' : ['.core', '.dmp', '.meta', '.log'], 28 '/usr/sbin/wpa_supplicant' : ['.core', '.dmp', '.meta'], 29 '/sbin/session_manager' : ['.core', '.dmp', '.meta'] 30 } 31 32 def _kill_processes(self, name): 33 """Kills the process passed as the parameter 34 35 @param name: Name of the process to be killed. 36 37 @returns: exit status of the kill command. 38 39 """ 40 return utils.system("killall -w -s SEGV %s" % name, ignore_status=True) 41 42 43 def _find_crash_files(self, process_name, extension): 44 """Find if the crash dumps with appropriate extensions are created. 45 46 @param process_name: Name of the process killed. 47 @param extension: Extension of the dump files to be created. 48 49 @returns: Returns the name of the dump file. 50 51 """ 52 return self._find_file_in_path(CrashTest._SYSTEM_CRASH_DIR, 53 process_name, extension) 54 55 56 def _find_file_in_path(self, path, process_name, filetype): 57 """Checks the creation of the the dump files with appropriate extensions. 58 Also check for the file size of the dumps created. 59 60 @param path: Directory path where the dump files are expected. 61 @param process_name: Name of the process. 62 @param filetype: Extension of the dump file. 63 64 @returns: Name of the dump file. 65 66 """ 67 try: 68 entries = os.listdir(path) 69 except OSError: 70 return None 71 72 for entry in entries: 73 (filename, ext) = os.path.splitext(entry) 74 if ext == filetype and filename.startswith(process_name): 75 file_path = path + '/' + entry 76 logging.info('the path is %s', file_path) 77 if os.path.getsize(file_path) > 0: 78 return entry 79 return None 80 81 def _remove_crash_file(self, path, process_name): 82 """Remove crash dumps to prevent unnecessary crash reporting. 83 84 @param path: Directory path where the dump files are expected. 85 @param process_name: Name of the process. 86 87 """ 88 try: 89 # sort by name so that we can find latest crash first 90 entries = sorted(os.listdir(path), reverse=True) 91 except OSError: 92 return 93 94 crash_name = None 95 for entry in entries: 96 (filename, _) = os.path.splitext(entry) 97 if filename.startswith(process_name): 98 crash_name = filename 99 break 100 if crash_name is None: 101 return 102 103 for entry in entries: 104 if entry.startswith(crash_name): 105 os.remove(path + '/' + entry) 106 107 def _test_process(self, process_path, crash_extensions): 108 """Calls a function to kill the process and then wait 109 for the creation of the dump files. 110 111 @param process_path: Path of the process to be killed. 112 @param crash_extensions: Extension of the dump file expected. 113 114 """ 115 if self._kill_processes(process_path): 116 raise error.TestFail("Failed to kill process %s" % process_path) 117 118 process_name = os.path.basename(process_path) 119 120 for crash_ext in crash_extensions: 121 # wait for appropriate dump files in a crash directory. 122 utils.poll_for_condition( 123 condition=lambda: self._find_crash_files(process_name, 124 crash_ext), 125 desc="Waiting for %s for %s" % (crash_ext, process_path)) 126 127 self._remove_crash_file(CrashTest._SYSTEM_CRASH_DIR, process_name) 128 # tlsdated generates two groups of crash files for some unknown reason, 129 # so we need to remove both of them. 130 if process_name == "tlsdated": 131 self._remove_crash_file(CrashTest._SYSTEM_CRASH_DIR, process_name) 132 133 def run_once(self, process_path=None, crash_extensions=None): 134 if process_path: 135 self._test_process(process_path,crash_extensions) 136 return 137 138 with chrome.Chrome(): 139 for process_path in self.process_list.keys(): 140 self.job.run_test("logging_CrashServices", 141 process_path=process_path, 142 crash_extensions=self.process_list.get(process_path), 143 tag=os.path.basename(process_path)) 144