def test_for_crash_with_retries(testcase, testcase_path, test_timeout, http_flag=False, compare_crash=True): """Test for a crash and return crash parameters like crash type, crash state, crash stacktrace, etc.""" # Cleanup any existing application instances and user profile directories. # Cleaning up temp clears user profile directories and should be done before # calling |get_command_line_for_application| call since that creates # dependencies in the profile folder. process_handler.terminate_stale_application_instances() shell.clear_temp_directory() app_directory = environment.get_value('APP_DIR') command = get_command_line_for_application(testcase_path, needs_http=http_flag) crash_retries = environment.get_value('CRASH_RETRIES') flaky_stacktrace = testcase.flaky_stack warmup_timeout = environment.get_value('WARMUP_TIMEOUT') logs.log('Testing for crash (command="%s").' % command) for round_number in xrange(1, crash_retries + 1): run_timeout = warmup_timeout if round_number == 1 else test_timeout return_code, crash_time, output = process_handler.run_process( command, timeout=run_timeout, gestures=testcase.gestures, current_working_directory=app_directory) process_handler.terminate_stale_application_instances() crash_result = CrashResult(return_code, crash_time, output) if not crash_result.is_crash(): continue state = crash_result.get_symbolized_data() logs.log('Crash occurred in %d seconds (round %d). State:\n%s' % (crash_time, round_number, state.crash_state)) if not compare_crash or not testcase.crash_state: logs.log('Crash stacktrace comparison skipped.') return crash_result if flaky_stacktrace: logs.log('Crash stacktrace is marked flaky, skipping comparison.') return crash_result if crash_result.should_ignore(): logs.log('Crash stacktrace matched ignore signatures, ignored.') continue if crash_result.is_security_issue() != testcase.security_flag: logs.log('Crash security flag does not match, ignored.') continue crash_comparer = CrashComparer(state.crash_state, testcase.crash_state) if crash_comparer.is_similar(): logs.log('Crash stacktrace is similar to original stacktrace.') return crash_result else: logs.log('Crash stacktrace does not match original stacktrace.') logs.log("Didn't crash at all.") crash_result = CrashResult(return_code=0, crash_time=0, output=output) return crash_result
def check_for_bad_build(job_type, crash_revision): """Return true if the build is bad, i.e. crashes on startup.""" # Check the bad build check flag to see if we want do this. if not environment.get_value('BAD_BUILD_CHECK'): return False # Create a blank command line with no file to run and no http. command = get_command_line_for_application(file_to_run='', needs_http=False) # When checking for bad builds, we use the default window size. # We don't want to pick a custom size since it can potentially cause a # startup crash and cause a build to be detected incorrectly as bad. default_window_argument = environment.get_value('WINDOW_ARG', '') if default_window_argument: command = command.replace(' %s' % default_window_argument, '') # TSAN is slow, and boots slow on first startup. Increase the warmup # timeout for this case. if environment.tool_matches('TSAN', job_type): fast_warmup_timeout = environment.get_value('WARMUP_TIMEOUT') else: fast_warmup_timeout = environment.get_value('FAST_WARMUP_TIMEOUT') # Initialize helper variables. is_bad_build = False build_run_console_output = '' app_directory = environment.get_value('APP_DIR') # Exit all running instances. process_handler.terminate_stale_application_instances() # Check if the build is bad. return_code, crash_time, output = process_handler.run_process( command, timeout=fast_warmup_timeout, current_working_directory=app_directory) crash_result = CrashResult(return_code, crash_time, output) # 1. Need to account for startup crashes with no crash state. E.g. failed to # load shared library. So, ignore state for comparison. # 2. Ignore leaks as they don't block a build from reporting regular crashes # and also don't impact regression range calculations. if (crash_result.is_crash(ignore_state=True) and not crash_result.should_ignore() and not crash_result.get_type() in ['Direct-leak', 'Indirect-leak']): is_bad_build = True build_run_console_output = utils.get_crash_stacktrace_output( command, crash_result.get_stacktrace(symbolized=True), crash_result.get_stacktrace(symbolized=False)) logs.log('Bad build for %s detected at r%d.' % (job_type, crash_revision), output=build_run_console_output) # Exit all running instances. process_handler.terminate_stale_application_instances() # Any of the conditions below indicate that bot is in a bad state and it is # not caused by the build itself. In that case, just exit. build_state = data_handler.get_build_state(job_type, crash_revision) if is_bad_build and utils.sub_string_exists_in(BAD_STATE_HINTS, output): logs.log_fatal_and_exit( 'Bad bot environment detected, exiting.', output=build_run_console_output, snapshot=process_handler.get_runtime_snapshot()) # If none of the other bots have added information about this build, # then add it now. if (build_state == data_types.BuildState.UNMARKED and not crash_result.should_ignore()): data_handler.add_build_metadata(job_type, crash_revision, is_bad_build, build_run_console_output) return is_bad_build
parser.add_argument("--outputfile", type=str, help="crashing program output", required=True) parser.add_argument("--exitcode", type=int, help="crashing program exit code", required=True) parser.add_argument("--time", type=int, help="crash collection time, Unix timestamp", default=0) args = parser.parse_args() output = open(args.outputfile).read() cr = CrashResult(args.exitcode, args.time, output) result = { 'type': cr.get_type(), 'is_crash': cr.is_crash(), 'is_security_issue': cr.is_security_issue(), 'should_ignore': cr.should_ignore(), 'stacktrace': cr.get_stacktrace(), 'output': cr.output, 'return_code': cr.return_code, } print(json.dumps(result, indent=4))