How to get useful backtraces?

#1

I may be imagining things, but I feel like the quality of OCaml backtraces has recently deteriorated. Here is an example to illustrate my point:

Uncaught exception:
  
  Not_found

Raised at file "src/import0.ml" (inlined), line 234, characters 22-32
Called from file "src/exn.ml", line 70, characters 6-15
Called from file "bin/dump/dump.ml", line 159, characters 4-642

Here is the code in “bin/dump/dump.ml”, line 159:

Out_channel.with_file (dir ^ "/results.log") ~f:(fun log ->
  List.iter max_failures ~f:(fun max_failures ->
    List.iter failure_probs ~f:(fun failure_prob ->
      printf "\n%s, Pr[failure] = %s, max failures = %d\n" (Filename.basename base_name)
        (Prob.to_string failure_prob) max_failures;
      printf "================================================================\n";
      analyze base_name ~max_failures ~failure_prob ~log
      |> List.iter ~f:(dump_data ~dir);
      printf "\n";
    )
  )
)

The backtrace is obviously completely useless.
Any ideas why the backtrace may be so useless and what I might do to get better backtraces? I tried the -g and -inline 0 flags, but with no success. I’m using jbuilder.

Thanks!

4 Likes
OCaml and backtraces
#2

Addendum: I’m using Unix.fork () and the exception is thrown in the child process. I think this may be the cause for the bad backtrace.

#3

I’ve been quite happy since I discovered:

Printexc.record_backtrace true;;

which gives you longer backtraces.

1 Like
#4

If you compile your program with -g and run your process with OCAMLRUNPARAM=b (see documentation), then a forked process terminating with an uncaught exception will print a backtrace as it should – and the backtrace should start from the start of both processes, not at fork point.

Repro case:

let rec g n =
  if n = 0 then raise Not_found
  else try g (n - 1) with exn -> raise exn (* line 3 *)

let rec f n =
  if n > 0 then try f (n - 1) with exn -> raise exn (* line 6 *)
  else begin
  match Unix.fork () with
  | 0 -> 
    g 2
  | n -> exit 0
end

let () =
  f 2
$ ocamlopt unix.cmxa -g -o test test.ml; OCAMLRUNPARAM=b ./test
Fatal error: exception Not_found
Raised at file "test.ml", line 2, characters 22-31
Called from file "test.ml", line 3, characters 11-20
Re-raised at file "test.ml", line 3, characters 39-42
Called from file "test.ml", line 3, characters 11-20
Re-raised at file "test.ml", line 3, characters 39-42
Called from file "test.ml", line 6, characters 20-29
Re-raised at file "test.ml", line 6, characters 48-51
Called from file "test.ml", line 6, characters 20-29
Re-raised at file "test.ml", line 6, characters 48-51
Called from file "test.ml", line 15, characters 2-5
3 Likes