def killAndGetStack(self, process, utilityPath, debuggerInfo, dump_screen=False): """ Kill the process, preferrably in a way that gets us a stack trace. Also attempts to obtain a screenshot before killing the process if specified. """ if dump_screen: self.dumpScreen(utilityPath) if mozinfo.info.get('crashreporter', True) and not debuggerInfo: if mozinfo.isWin: # We should have a "crashinject" program in our utility path crashinject = os.path.normpath( os.path.join(utilityPath, "crashinject.exe")) if os.path.exists(crashinject): status = subprocess.Popen([crashinject, str(process.pid)]).wait() printstatus(status, "crashinject") if status == 0: return else: try: process.kill(sig=signal.SIGABRT) except OSError: # https://bugzilla.mozilla.org/show_bug.cgi?id=921509 log.info( "Can't trigger Breakpad, process no longer exists") return log.info("Can't trigger Breakpad, just killing process") process.kill()
def killAndGetStack(self, process, utilityPath, debuggerInfo, dump_screen=False): """ Kill the process, preferrably in a way that gets us a stack trace. Also attempts to obtain a screenshot before killing the process if specified. """ if dump_screen: self.dumpScreen(utilityPath) if mozinfo.info.get('crashreporter', True) and not debuggerInfo: if mozinfo.isWin: # We should have a "crashinject" program in our utility path crashinject = os.path.normpath(os.path.join(utilityPath, "crashinject.exe")) if os.path.exists(crashinject): status = subprocess.Popen([crashinject, str(process.pid)]).wait() printstatus(status, "crashinject") if status == 0: return else: try: process.kill(sig=signal.SIGABRT) except OSError: # https://bugzilla.mozilla.org/show_bug.cgi?id=921509 log.info("Can't trigger Breakpad, process no longer exists") return log.info("Can't trigger Breakpad, just killing process") process.kill()
def killAndGetStackNoScreenshot(self, processPID, utilityPath, debuggerInfo): """Kill the process, preferrably in a way that gets us a stack trace.""" if self.CRASHREPORTER and not debuggerInfo: if not self.IS_WIN32: # ABRT will get picked up by Breakpad's signal handler os.kill(processPID, signal.SIGABRT) return else: # We should have a "crashinject" program in our utility path crashinject = os.path.normpath(os.path.join(utilityPath, "crashinject.exe")) if os.path.exists(crashinject): status = subprocess.Popen([crashinject, str(processPID)]).wait() automationutils.printstatus(status, "crashinject") if status == 0: return self.log.info("Can't trigger Breakpad, just killing process") self.killPid(processPID)
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath): """ Look for timeout or crashes and return the status after the process terminates """ stackFixerFunction = None didTimeout = False hitMaxTime = False if proc.stdout is None: self.log.info("TEST-INFO: Not logging stdout or stderr due to debugger connection") else: logsource = proc.stdout if self.IS_DEBUG_BUILD and symbolsPath and os.path.exists(symbolsPath): # Run each line through a function in fix_stack_using_bpsyms.py (uses breakpad symbol files) # This method is preferred for Tinderbox builds, since native symbols may have been stripped. sys.path.insert(0, utilityPath) import fix_stack_using_bpsyms as stackFixerModule stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line, symbolsPath) del sys.path[0] elif self.IS_DEBUG_BUILD and self.IS_MAC: # Run each line through a function in fix_macosx_stack.py (uses atos) sys.path.insert(0, utilityPath) import fix_macosx_stack as stackFixerModule stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line) del sys.path[0] elif self.IS_DEBUG_BUILD and self.IS_LINUX: # Run each line through a function in fix_linux_stack.py (uses addr2line) # This method is preferred for developer machines, so we don't have to run "make buildsymbols". sys.path.insert(0, utilityPath) import fix_linux_stack as stackFixerModule stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line) del sys.path[0] # With metro browser runs this script launches the metro test harness which launches the browser. # The metro test harness hands back the real browser process id via log output which we need to # pick up on and parse out. This variable tracks the real browser process id if we find it. browserProcessId = -1 (line, didTimeout) = self.readWithTimeout(logsource, timeout) while line != "" and not didTimeout: if stackFixerFunction: line = stackFixerFunction(line) self.log.info(line.rstrip().decode("UTF-8", "ignore")) if "TEST-START" in line and "|" in line: self.lastTestSeen = line.split("|")[1].strip() if not debuggerInfo and "TEST-UNEXPECTED-FAIL" in line and "Test timed out" in line: self.dumpScreen(utilityPath) (line, didTimeout) = self.readWithTimeout(logsource, timeout) if not hitMaxTime and maxTime and datetime.now() - startTime > timedelta(seconds=maxTime): # Kill the application. hitMaxTime = True self.log.info( "TEST-UNEXPECTED-FAIL | %s | application ran for longer than allowed maximum time of %d seconds", self.lastTestSeen, int(maxTime), ) self.killAndGetStack(proc.pid, utilityPath, debuggerInfo) if didTimeout: if line: self.log.info(line.rstrip().decode("UTF-8", "ignore")) self.log.info( "TEST-UNEXPECTED-FAIL | %s | application timed out after %d seconds with no output", self.lastTestSeen, int(timeout), ) if browserProcessId == -1: browserProcessId = proc.pid self.killAndGetStack(browserProcessId, utilityPath, debuggerInfo) status = proc.wait() automationutils.printstatus(status, "Main app process") if status == 0: self.lastTestSeen = "Main app process exited normally" if status != 0 and not didTimeout and not hitMaxTime: self.log.info("TEST-UNEXPECTED-FAIL | %s | Exited with code %d during test run", self.lastTestSeen, status) return status