diff --git a/infer/src/absint/AbstractInterpreter.ml b/infer/src/absint/AbstractInterpreter.ml index 9d1dc4c55..dc02f8b91 100644 --- a/infer/src/absint/AbstractInterpreter.ml +++ b/infer/src/absint/AbstractInterpreter.ml @@ -114,6 +114,9 @@ module AbstractInterpreterCommon (TransferFunctions : TransferFunctions.SIL) = s NodePrinter.finish_session underlying_node + (** reference to log errors only at the innermost recursive call *) + let logged_error = ref false + let exec_instrs ~debug proc_data node node_id ~visit_count pre inv_map = let on_instrs instrs = if Config.write_html && debug <> DefaultNoExecInstr_UseFromLowerHilAbstractInterpreterOnly @@ -123,9 +126,16 @@ module AbstractInterpreterCommon (TransferFunctions : TransferFunctions.SIL) = s (Node.underlying_node node) ; let astate_post = let compute_post pre instr = - try TransferFunctions.exec_instr pre proc_data node instr with exn -> + try + let post = TransferFunctions.exec_instr pre proc_data node instr in + (* don't forget to reset this so we output messages for future errors too *) + logged_error := false ; + post + with exn -> IExn.reraise_after exn ~f:(fun () -> - L.internal_error "In instruction %a@\n" (Sil.pp_instr Pp.text) instr ) + if not !logged_error then ( + L.internal_error "In instruction %a@\n" (Sil.pp_instr Pp.text) instr ; + logged_error := true ) ) in Instrs.fold ~f:compute_post ~init:pre instrs in diff --git a/infer/src/backend/ondemand.ml b/infer/src/backend/ondemand.ml index f6c98b82b..3ed4c7da2 100644 --- a/infer/src/backend/ondemand.ml +++ b/infer/src/backend/ondemand.ml @@ -116,6 +116,9 @@ let restore_global_state st = Timeout.resume_previous_timeout () +(** reference to log errors only at the innermost recursive call *) +let logged_error = ref false + let run_proc_analysis analyze_proc ~caller_pdesc callee_pdesc = let callee_pname = Procdesc.get_proc_name callee_pdesc in let log_elapsed_time = @@ -164,17 +167,23 @@ let run_proc_analysis analyze_proc ~caller_pdesc callee_pdesc = else initial_summary in let final_summary = postprocess summary in - restore_global_state old_state ; final_summary + restore_global_state old_state ; + (* don't forget to reset this so we output messages for future errors too *) + logged_error := false ; + final_summary with exn -> ( + let backtrace = Printexc.get_backtrace () in IExn.reraise_if exn ~f:(fun () -> - let source_file = attributes.ProcAttributes.translation_unit in - let location = attributes.ProcAttributes.loc in - L.internal_error "While analysing function %a:%a at %a@\n" SourceFile.pp source_file - Typ.Procname.pp callee_pname Location.pp_file_pos location ; + if not !logged_error then ( + let source_file = attributes.ProcAttributes.translation_unit in + let location = attributes.ProcAttributes.loc in + L.internal_error "While analysing function %a:%a at %a@\n" SourceFile.pp source_file + Typ.Procname.pp callee_pname Location.pp_file_pos location ; + logged_error := true ) ; restore_global_state old_state ; not Config.keep_going ) ; L.internal_error "@\nERROR RUNNING BACKEND: %a %s@\n@\nBACK TRACE@\n%s@?" Typ.Procname.pp - callee_pname (Exn.to_string exn) (Printexc.get_backtrace ()) ; + callee_pname (Exn.to_string exn) backtrace ; match exn with | SymOp.Analysis_failure_exe kind -> (* in production mode, log the timeout/crash and continue with the summary we had before