diff --git a/infer/src/backend/errdesc.ml b/infer/src/backend/errdesc.ml index 1a6c0c6ab..494677e5c 100644 --- a/infer/src/backend/errdesc.ml +++ b/infer/src/backend/errdesc.ml @@ -1148,16 +1148,7 @@ let explain_null_test_after_dereference exp node line loc = Localise.desc_null_test_after_dereference expr_str line loc | None -> Localise.no_desc -let _warning loc fmt fmt_string = - if Config.developer_mode then - begin - F.fprintf - fmt "%s:%d: Warning: " (DB.source_file_to_string !DB.current_source) loc.Location.line; - F.fprintf fmt fmt_string - end - else - F.ifprintf fmt fmt_string - (** Print a warning to the err stream at the given location (note: only prints in developer mode) *) let warning_err loc fmt_string = - _warning loc (Logging.get_err_formatter ()) fmt_string + L.err ("%s:%d: Warning: " ^^ fmt_string) + (DB.source_file_to_string !DB.current_source) loc.Location.line diff --git a/infer/src/backend/inferanalyze.ml b/infer/src/backend/inferanalyze.ml index 7170aaefe..e5877d43c 100644 --- a/infer/src/backend/inferanalyze.ml +++ b/infer/src/backend/inferanalyze.ml @@ -64,48 +64,6 @@ let analyze_cluster cluster_num (cluster : Cluster.t) = (cluster_num + 1) num_procs; analyze_exe_env exe_env -let open_output_file f fname = - try - let cout = open_out fname in - let fmt = Format.formatter_of_out_channel cout in - f fmt; - Some (fmt, cout) - with Sys_error _ -> - Format.fprintf Format.std_formatter "Error: cannot open output file %s@." fname; - exit(-1) - -let close_output_file = function - | None -> () - | Some (_, cout) -> close_out cout - -let setup_logging () = - if Config.developer_mode then - let log_dir_name = "log" in - let analyzer_out_name = "analyzer_out" in - let analyzer_err_name = "analyzer_err" in - let log_dir = - DB.filename_to_string - (DB.Results_dir.path_to_filename DB.Results_dir.Abs_root [log_dir_name]) in - DB.create_dir log_dir; - let analyzer_out_file = - if Config.out_file_cmdline = "" then Filename.concat log_dir analyzer_out_name - else Config.out_file_cmdline in - let analyzer_err_file = - if Config.err_file_cmdline = "" then Filename.concat log_dir analyzer_err_name - else Config.err_file_cmdline in - let analyzer_out_of = open_output_file Logging.set_out_formatter analyzer_out_file in - let analyzer_err_of = open_output_file Logging.set_err_formatter analyzer_err_file in - analyzer_out_of, analyzer_err_of - else None, None - -let teardown_logging analyzer_out_of analyzer_err_of = - if Config.developer_mode then - begin - L.flush_streams (); - close_output_file analyzer_out_of; - close_output_file analyzer_err_of; - end - let output_json_makefile_stats clusters = let clusters_to_analyze = IList.filter ClusterMakefile.cluster_should_be_analyzed clusters in @@ -167,15 +125,9 @@ let () = if Config.allow_specs_cleanup = true && Config.cluster_cmdline = None then DB.Results_dir.clean_specs_dir (); - let analyzer_out_of, analyzer_err_of = setup_logging () in - - let finish_logging () = - teardown_logging analyzer_out_of analyzer_err_of in - match Config.cluster_cmdline with | Some fname -> - process_cluster_cmdline fname; - finish_logging () + process_cluster_cmdline fname | None -> if Config.merge then MergeCapture.merge_captured_targets (); let clusters = DB.find_source_dirs () in @@ -192,5 +144,4 @@ let () = clusters; L.stdout "Analysis finished in %as@." pp_elapsed_time () end; - output_json_makefile_stats clusters; - finish_logging () + output_json_makefile_stats clusters diff --git a/infer/src/backend/logging.ml b/infer/src/backend/logging.ml index 8e2442863..9a2eb7cbe 100644 --- a/infer/src/backend/logging.ml +++ b/infer/src/backend/logging.ml @@ -14,7 +14,6 @@ open! Utils module F = Format -(* =============== START of module MyErr =============== *) (** type of printable elements *) type print_type = | PTatom @@ -64,35 +63,57 @@ let delayed_actions = ref [] (** hook for the current printer of delayed print actions *) let printer_hook = ref (Obj.magic ()) -(** Current formatter for the out stream *) -let current_out_formatter = ref F.std_formatter - -(** Current formatter for the err stream *) -let current_err_formatter = ref F.err_formatter - -(** Get the current err formatter *) -let get_err_formatter () = !current_err_formatter - -(** Set the current out formatter *) -let set_out_formatter fmt = - current_out_formatter := fmt - -(** Set the current err formatter *) -let set_err_formatter fmt = - current_err_formatter := fmt - -(** Flush the current streams *) -let flush_streams () = +let out_formatter, err_formatter = + (** Create a directory if it does not exist already. *) + (* This is the same as DB.create_dir, except for logging to stderr *) + let create_dir dir = + try + if (Unix.stat dir).Unix.st_kind != Unix.S_DIR then + failwithf "@.ERROR: file %s exists and is not a directory@." dir + with Unix.Unix_error _ -> + try Unix.mkdir dir 0o700 + with Unix.Unix_error _ -> + let created_concurrently = (* check if another process created it meanwhile *) + (Unix.stat dir).Unix.st_kind = Unix.S_DIR in + if not created_concurrently then + failwithf "@.ERROR: cannot create directory %s@." dir + in + let open_output_file fname = + try + let cout = open_out fname in + let fmt = F.formatter_of_out_channel cout in + (fmt, cout) + with Sys_error _ -> + failwithf "@.ERROR: cannot open output file %s@." fname + in if Config.developer_mode then - begin - F.fprintf !current_out_formatter "@?"; - F.fprintf !current_err_formatter "@?" - end + let log_dir_name = "log" in + let analyzer_out_name = "analyzer_out" in + let analyzer_err_name = "analyzer_err" in + let log_dir = Filename.concat Config.results_dir log_dir_name in + create_dir log_dir; + let analyzer_out_file = + if Config.out_file_cmdline = "" then Filename.concat log_dir analyzer_out_name + else Config.out_file_cmdline in + let analyzer_err_file = + if Config.err_file_cmdline = "" then Filename.concat log_dir analyzer_err_name + else Config.err_file_cmdline in + let out_fmt, out_chan = open_output_file analyzer_out_file in + let err_fmt, err_chan = open_output_file analyzer_err_file in + Pervasives.at_exit (fun () -> + F.pp_print_flush out_fmt () ; + F.pp_print_flush err_fmt () ; + close_out out_chan ; + close_out err_chan + ); + (out_fmt, err_fmt) + else + (F.std_formatter, F.err_formatter) (** extend the current print log *) let add_print_action pact = if Config.write_html then delayed_actions := pact :: !delayed_actions - else if not Config.test then !printer_hook !current_out_formatter pact + else if not Config.test then !printer_hook out_formatter pact (** reset the delayed print actions *) let reset_delayed_prints () = @@ -117,11 +138,11 @@ let do_print_in_developer_mode fmt fmt_string = (** print to the current out stream (note: only prints in developer mode) *) let out fmt_string = - do_print_in_developer_mode !current_out_formatter fmt_string + do_print_in_developer_mode out_formatter fmt_string (** print to the current err stream (note: only prints in developer mode) *) let err fmt_string = - do_print_in_developer_mode !current_err_formatter fmt_string + do_print_in_developer_mode err_formatter fmt_string (** print immediately to standard error *) let stderr fmt_string = diff --git a/infer/src/backend/logging.mli b/infer/src/backend/logging.mli index 684d41d55..90a2432b6 100644 --- a/infer/src/backend/logging.mli +++ b/infer/src/backend/logging.mli @@ -83,18 +83,6 @@ val stderr : ('a, Format.formatter, unit) format -> 'a (** print immediately to standard output *) val stdout : ('a, Format.formatter, unit) format -> 'a -(** Get the current err formatter *) -val get_err_formatter : unit -> Format.formatter - -(** Set the current out formatter *) -val set_out_formatter : Format.formatter -> unit - -(** Set the current err formatter *) -val set_err_formatter : Format.formatter -> unit - -(** Flush the current streams *) -val flush_streams : unit -> unit - (** Type of location in ml source: __POS__ *) type ml_loc = string * int * int * int diff --git a/infer/src/backend/utils.ml b/infer/src/backend/utils.ml index 701efe77d..a3a9f4579 100644 --- a/infer/src/backend/utils.ml +++ b/infer/src/backend/utils.ml @@ -599,3 +599,11 @@ let with_file file ~f = let write_json_to_file destfile json = with_file destfile ~f:(fun oc -> Yojson.Basic.pretty_to_channel oc json) + +let failwithf fmt = + Format.kfprintf (fun _ -> failwith (Format.flush_str_formatter ())) + Format.str_formatter fmt + +let invalid_argf fmt = + Format.kfprintf (fun _ -> invalid_arg (Format.flush_str_formatter ())) + Format.str_formatter fmt diff --git a/infer/src/backend/utils.mli b/infer/src/backend/utils.mli index 259e2c592..602d2ec9b 100644 --- a/infer/src/backend/utils.mli +++ b/infer/src/backend/utils.mli @@ -269,3 +269,7 @@ val analyzer_of_string: string -> analyzer val read_optional_json_file : string -> (Yojson.Basic.json, string) result val write_json_to_file : string -> Yojson.Basic.json -> unit + +val failwithf : ('a, Format.formatter, unit, 'b) format4 -> 'a + +val invalid_argf : ('a, Format.formatter, unit, 'b) format4 -> 'a diff --git a/infer/src/scripts/checkCopyright.ml b/infer/src/scripts/checkCopyright.ml index 2a1cce033..e1d49c739 100644 --- a/infer/src/scripts/checkCopyright.ml +++ b/infer/src/scripts/checkCopyright.ml @@ -217,7 +217,6 @@ let output_diff fname lines_arr cstart n cend len mono fb_year com_style prefix done; L.stdout "-----@."; L.stdout "@[%a@]" (pp_copyright mono fb_year com_style) prefix; - L.flush_streams (); if !update_files then update_file fname mono fb_year com_style prefix cstart cend lines_arr