|
| 1 | +type mark = .. |
| 2 | + |
| 3 | +module Exn = |
| 4 | +struct |
| 5 | + type t = exn |
| 6 | + let equal = (==) |
| 7 | + let hash = Hashtbl.hash |
| 8 | +end |
| 9 | + |
| 10 | +module EWH = Ephemeron.K1.Make (Exn) |
| 11 | + |
| 12 | +let marks: mark EWH.t = EWH.create 10 |
| 13 | + |
| 14 | +let add_mark e m = |
| 15 | + EWH.add marks e m |
| 16 | + |
| 17 | + |
| 18 | +(* Copied & modified from Fun. *) |
| 19 | +let protect ~(mark: unit -> mark) ~(finally: unit -> unit) work = |
| 20 | + let finally_no_exn () = |
| 21 | + try |
| 22 | + finally () |
| 23 | + with e -> |
| 24 | + let bt = Printexc.get_raw_backtrace () in |
| 25 | + let finally_exn = Fun.Finally_raised e in |
| 26 | + add_mark finally_exn (mark ()); |
| 27 | + Printexc.raise_with_backtrace finally_exn bt |
| 28 | + in |
| 29 | + match work () with |
| 30 | + | result -> |
| 31 | + finally_no_exn (); |
| 32 | + result |
| 33 | + | exception work_exn -> |
| 34 | + let work_bt = Printexc.get_raw_backtrace () in |
| 35 | + finally_no_exn (); |
| 36 | + add_mark work_exn (mark ()); |
| 37 | + Printexc.raise_with_backtrace work_exn work_bt |
| 38 | + |
| 39 | + |
| 40 | +let mark_printers: (mark -> string option) list ref = ref [] |
| 41 | + |
| 42 | +let register_mark_printer f = |
| 43 | + mark_printers := f :: !mark_printers |
| 44 | + |
| 45 | +let apply_mark_printers m = |
| 46 | + List.find_map (fun f -> |
| 47 | + match f m with |
| 48 | + | Some s -> Some s |
| 49 | + | None |
| 50 | + | exception _ -> None |
| 51 | + ) !mark_printers |
| 52 | + |
| 53 | +let mark_to_string_default m = |
| 54 | + Obj.Extension_constructor.(name (of_val m)) |
| 55 | + |
| 56 | +let mark_to_string m = |
| 57 | + match apply_mark_printers m with |
| 58 | + | Some s -> s |
| 59 | + | None -> mark_to_string_default m |
| 60 | + |
| 61 | +let find_marks e = |
| 62 | + List.rev (EWH.find_all marks e) |
| 63 | + |
| 64 | +let print_marktrace oc e = |
| 65 | + let ms = find_marks e in |
| 66 | + List.iter (fun m -> |
| 67 | + Printf.fprintf oc "Marked with %s\n" (mark_to_string m) |
| 68 | + ) ms |
| 69 | + |
| 70 | +let () = |
| 71 | + Printexc.set_uncaught_exception_handler (fun e bt -> |
| 72 | + (* Copied & modified from Printexc.default_uncaught_exception_handler. *) |
| 73 | + Printf.eprintf "Fatal error: exception %s\n" (Printexc.to_string e); |
| 74 | + if Printexc.backtrace_status () then |
| 75 | + print_marktrace stderr e; |
| 76 | + Printexc.print_raw_backtrace stderr bt; |
| 77 | + flush stderr |
| 78 | + ) |
0 commit comments