Skip to content

Commit 8c426d2

Browse files
authored
CA-423574: avoid losing backtraces when reraising (#6896)
Xenopsd reraises some exceptions in a different, simplified form. But this needs to retain the stacktrace from the original place that raised the first exception, otherwise it might be hard to debug. This is a followup to [the previous PR ](#6891), I found a few more places that would lose a stacktrace while working on another code change in the area. Recommended to review with 'ignore whitespaces' enabled. To avoid losing the backtrace we need to mark it with `Backtrace.is_important` and to use `Backtrace.reraise` instead of `raise`. (or we could do this using purely the stdlib with `Printexc.get_raw_backtrace()` and `Printexc.raise_with_bt`, but the rest of the code around here uses Backtrace already, so for consistency use that)
2 parents 90d6814 + d51aad7 commit 8c426d2

1 file changed

Lines changed: 43 additions & 33 deletions

File tree

ocaml/xenopsd/xc/xenops_server_xen.ml

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ let finally = Xapi_stdext_pervasives.Pervasiveext.finally
3131

3232
let with_lock = Xapi_stdext_threads.Threadext.Mutex.execute
3333

34-
let internal_error fmt =
34+
let internal_error' e fmt =
3535
Printf.ksprintf
3636
(fun str ->
3737
error "%s" str ;
38-
raise (Xenopsd_error (Internal_error str))
38+
let err = Xenopsd_error (Internal_error str) in
39+
match e with None -> raise err | Some e -> Backtrace.reraise e err
3940
)
4041
fmt
4142

43+
let internal_error fmt = internal_error' None fmt
44+
4245
(* libxl_internal.h:DISABLE_UDEV_PATH *)
4346
let disable_udev_path = "libxl/disable_udev"
4447

@@ -269,8 +272,9 @@ let di_of_uuid ~xc uuid =
269272
let domid_list = String.concat ", " (List.map domid_of_di possible) in
270273
let uuid' = Uuidx.to_string uuid in
271274
internal_error "More than one domain with uuid %s: (%s)" uuid' domid_list
272-
| exception Failure r ->
273-
internal_error "%s" r
275+
| exception (Failure r as e) ->
276+
Backtrace.is_important e ;
277+
internal_error' (Some e) "%s" r
274278

275279
let domid_of_uuid ~xs uuid =
276280
(* We don't fully control the domain lifecycle because libxenguest will
@@ -2621,36 +2625,42 @@ module VM = struct
26212625
try
26222626
build_domain_exn xc xs domid task vm vbds vifs vgpus vusbs extras
26232627
force
2624-
with
2625-
| Bootloader.Bad_sexpr x ->
2626-
internal_error "VM = %s; domid = %d; Bootloader.Bad_sexpr %s"
2627-
vm.Vm.id domid x
2628-
| Bootloader.Bad_error x ->
2629-
internal_error "VM = %s; domid = %d; Bootloader.Bad_error %s"
2630-
vm.Vm.id domid x
2631-
| Bootloader.Unknown_bootloader x ->
2632-
internal_error
2633-
"VM = %s; domid = %d; Bootloader.Unknown_bootloader %s" vm.Vm.id
2634-
domid x
2635-
| Bootloader.Error_from_bootloader x ->
2636-
let m =
2637-
Printf.sprintf
2638-
"VM = %s; domid = %d; Bootloader.Error_from_bootloader %s"
2628+
with e -> (
2629+
Backtrace.is_important e ;
2630+
let internal_error fmt = internal_error' (Some e) fmt in
2631+
match e with
2632+
| Bootloader.Bad_sexpr x ->
2633+
internal_error "VM = %s; domid = %d; Bootloader.Bad_sexpr %s"
26392634
vm.Vm.id domid x
2640-
in
2641-
debug "%s" m ;
2642-
raise (Xenopsd_error (Bootloader_error (vm.Vm.id, x)))
2643-
| Domain.Not_enough_memory m ->
2644-
debug
2645-
"VM = %s; domid = %d; Domain.Not_enough_memory. Needed: %Ld bytes"
2646-
vm.Vm.id domid m ;
2647-
raise (Xenopsd_error (Not_enough_memory m))
2648-
| e ->
2649-
let m =
2650-
Printf.sprintf "VM = %s; domid = %d; Error: %s" vm.Vm.id domid
2651-
(Printexc.to_string e)
2652-
in
2653-
debug "%s" m ; raise e
2635+
| Bootloader.Bad_error x ->
2636+
internal_error "VM = %s; domid = %d; Bootloader.Bad_error %s"
2637+
vm.Vm.id domid x
2638+
| Bootloader.Unknown_bootloader x ->
2639+
internal_error
2640+
"VM = %s; domid = %d; Bootloader.Unknown_bootloader %s" vm.Vm.id
2641+
domid x
2642+
| Bootloader.Error_from_bootloader x ->
2643+
let m =
2644+
Printf.sprintf
2645+
"VM = %s; domid = %d; Bootloader.Error_from_bootloader %s"
2646+
vm.Vm.id domid x
2647+
in
2648+
debug "%s" m ;
2649+
Backtrace.reraise e
2650+
(Xenopsd_error (Bootloader_error (vm.Vm.id, x)))
2651+
| Domain.Not_enough_memory m ->
2652+
debug
2653+
"VM = %s; domid = %d; Domain.Not_enough_memory. Needed: %Ld \
2654+
bytes"
2655+
vm.Vm.id domid m ;
2656+
Backtrace.reraise e (Xenopsd_error (Not_enough_memory m))
2657+
| e ->
2658+
let m =
2659+
Printf.sprintf "VM = %s; domid = %d; Error: %s" vm.Vm.id domid
2660+
(Printexc.to_string e)
2661+
in
2662+
debug "%s" m ; Backtrace.reraise e e
2663+
)
26542664
)
26552665
(fun () -> clean_memory_reservation task di.Xenctrl.domid)
26562666

0 commit comments

Comments
 (0)