Skip to content

Commit 6ca1cde

Browse files
committed
lib: Provide new with_backtraces to avoid printing invalid backtraces
Instead it prints a message stating there is no backtrace. The new function uses the standard stdlib Signed-off-by: Pau Ruiz Safont <pau.safont@vates.tech>
1 parent 07344a1 commit 6ca1cde

6 files changed

Lines changed: 75 additions & 13 deletions

File tree

lib/backtrace.ml

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ let ( let@ ) f x = f x
155155

156156
let try_result f = try Ok (f ()) with exn -> Error exn
157157

158-
let with_backtraces f =
158+
let with_backtraces_common f with_table =
159159
let id = Thread.(id (self ())) in
160160
let tbl =
161161
let@ () = with_lock in
@@ -172,10 +172,28 @@ let with_backtraces f =
172172
let finally () =
173173
with_lock (fun () -> Hashtbl.remove per_thread_backtraces id)
174174
in
175-
let@ () = Fun.protect ~finally in
176-
match try_result f with
177-
| Ok ok -> `Ok ok
178-
| Error e -> `Error (e, get tbl e)
175+
Fun.protect ~finally (fun () -> with_table tbl (try_result f))
176+
177+
module V1 = struct
178+
let with_backtraces f =
179+
let with_table tbl = function
180+
| Ok ok -> `Ok ok
181+
| Error e -> `Error (e, get tbl e)
182+
in
183+
with_backtraces_common f with_table
184+
end
185+
186+
module V2 = struct
187+
let with_backtraces ~finally f =
188+
let with_table tbl result =
189+
result
190+
|> Result.map_error (function e -> (e, get tbl e))
191+
|> finally
192+
in
193+
with_backtraces_common f with_table
194+
end
195+
196+
let with_backtraces = V1.with_backtraces
179197

180198
let with_table f default =
181199
let id = Thread.(id (self ())) in

lib/backtrace.mli

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,24 @@ val to_string_hum: t -> string
2828
stash away a copy of the backtrace buffer if there is any risk
2929
of us raising another (or even the same) exception) *)
3030

31+
module V1 : sig
32+
val with_backtraces : (unit -> 'a) -> [ `Ok of 'a | `Error of (exn * t) ]
33+
[@@deprecated "V2.with_backtraces"]
34+
end
35+
36+
module V2 : sig
37+
val with_backtraces : finally:(('a, exn * t) result -> 'a) -> (unit -> 'a) -> 'a
38+
(** [with_backtraces thread finally] Allows backtraces to be recorded within
39+
[thread]. [finally] is executed whenever [thread] finishes, this allows
40+
users to use the stacktrace before it's dropped from the cache, for
41+
example, to log it. *)
42+
end
43+
3144
val with_backtraces: (unit -> 'a) -> [ `Ok of 'a | `Error of (exn * t) ]
3245
(** Allow backtraces to be recorded for this thread. All new threads
3346
must be wrapped in this for the backtrace tracking to work.
3447
It is acceptable to nest these wrappers; it will not affect the
35-
backtrace recording behaviour. *)
48+
backtrace recording behaviour. Please change to [V2.with_backtraces] *)
3649

3750
val is_important: exn -> unit
3851
(** Declare that the backtrace is important for debugging and should be

test/log.ml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ let log_backtrace_exn exn bt =
2323
output_log (Printf.sprintf "Raised %s" (Printexc.to_string exn)) ;
2424
List.iter output_log all
2525

26-
let with_thread_associated desc f x =
26+
let with_thread_associated_old desc f x =
2727
let result =
28-
let@ () = Backtrace.with_backtraces in
28+
let@ () = begin [@alert "-deprecated"] Backtrace.V1.with_backtraces end in
2929
try f x with e -> Backtrace.is_important e ; raise e
3030
in
3131
match result with
@@ -38,3 +38,18 @@ let with_thread_associated desc f x =
3838
) ;
3939
log_backtrace_exn exn bt ;
4040
raise exn
41+
42+
let with_thread_associated desc f x =
43+
let print_backtrace = function
44+
| Ok result ->
45+
result
46+
| Error (exn, bt) ->
47+
output_log
48+
(Printf.sprintf "%s failed with exception %s" desc
49+
(Printexc.to_string exn)
50+
) ;
51+
log_backtrace_exn exn bt ;
52+
raise exn
53+
in
54+
let@ () = Backtrace.V2.with_backtraces ~finally:print_backtrace in
55+
try f x with e -> Backtrace.is_important e ; raise e

test/log.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
val with_thread_associated : string -> ('a -> 'b) -> 'a -> 'b
22

3+
val with_thread_associated_old : string -> ('a -> 'b) -> 'a -> 'b
4+
(** Uses V1.with_backtrace *)
5+

test/raiser.ml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,21 @@ let test_reraise () =
1616
Printexc.record_backtrace true ;
1717
try Test_lib.Log.with_thread_associated "Backtrace lab" bar () with _ -> ()
1818

19+
let v1_with_backtrace = ref false
20+
21+
let test_v1_with_backtrace () =
22+
Printexc.record_backtrace false ;
23+
try Test_lib.Log.with_thread_associated_old "Backtrace lab" foo () with _ -> ()
24+
1925
let usage = Printf.sprintf "%s" Sys.argv.(0)
2026
let speclist = [
2127
("-no-backtraces", Arg.Set no_backtraces, "Test no-backtraces")
2228
; ("-reraise", Arg.Set reraise, "Test reraise")
29+
; ("-v1-with-backtrace", Arg.Set v1_with_backtrace, "Test v1-with-backtrace")
2330
]
2431

2532
let () =
2633
Arg.parse speclist (Fun.const ()) usage ;
2734
if !no_backtraces then test_no_backtraces () ;
28-
if !reraise then test_reraise ()
35+
if !reraise then test_reraise () ;
36+
if !v1_with_backtrace then test_v1_with_backtrace ()

test/reraise.t

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
$ ./raiser.exe -no-backtraces
22
Backtrace lab failed with exception Failure("foo")
33
Raised Failure("foo")
4-
1/1 raiser.exe Raised at file (Thread 0 has no backtrace table. Was with_backtraces called?, line 0
5-
4+
raiser.exe: Thread 0 has no backtrace table
65

76
$ ./raiser.exe -reraise
87
Backtrace lab failed with exception Failure("bar")
98
Raised Failure("bar")
10-
1/2 raiser.exe Raised at file lib/backtrace.ml, line 201
11-
2/2 raiser.exe Called from file test/log.ml, line 29
9+
1/2 raiser.exe Raised at file lib/backtrace.ml, line 219
10+
2/2 raiser.exe Called from file test/log.ml, line 55
11+
12+
13+
$ ./raiser.exe -v1-with-backtrace
14+
Backtrace lab failed with exception Failure("foo")
15+
Raised Failure("foo")
16+
1/1 raiser.exe Raised at file (Thread 0 has no backtrace table. Was with_backtraces called?, line 0
1217

0 commit comments

Comments
 (0)