[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] tools/oxenstored: Set uncaught exception handler
commit ee7815f49faf743e960dac9e72809eb66393bc6d Author: Edwin Török <edvin.torok@xxxxxxxxxx> AuthorDate: Mon Nov 7 17:41:36 2022 +0000 Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CommitDate: Thu Dec 1 16:07:17 2022 +0000 tools/oxenstored: Set uncaught exception handler Unhandled exceptions go to stderr by default, but this doesn't typically work for oxenstored because: * daemonize reopens stderr as /dev/null * systemd redirects stderr to /dev/null too Debugging an unhandled exception requires reproducing the issue locally when using --no-fork, and is not conducive to figuring out what went wrong on a remote system. Install a custom handler which also tries to render the backtrace to the configured syslog facility, and DAEMON|ERR otherwise. Signed-off-by: Edwin Török <edvin.torok@xxxxxxxxxx> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Acked-by: Christian Lindig <christian.lindig@xxxxxxxxxx> --- tools/ocaml/xenstored/logging.ml | 29 +++++++++++++++++++++++++++++ tools/ocaml/xenstored/xenstored.ml | 3 ++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/tools/ocaml/xenstored/logging.ml b/tools/ocaml/xenstored/logging.ml index 39c3036155..255051437d 100644 --- a/tools/ocaml/xenstored/logging.ml +++ b/tools/ocaml/xenstored/logging.ml @@ -342,3 +342,32 @@ let xb_answer ~tid ~con ~ty data = let watch_not_fired ~con perms path = let data = Printf.sprintf "EPERM perms=[%s] path=%s" perms path in access_logging ~tid:0 ~con ~data Watch_not_fired ~level:Info + +let msg_of exn bt = + Printf.sprintf "Fatal exception: %s\n%s\n" (Printexc.to_string exn) + (Printexc.raw_backtrace_to_string bt) + +let fallback_exception_handler exn bt = + (* stderr goes to /dev/null, so use the logger where possible, + but always print to stderr too, in case everything else fails, + e.g. this can be used to debug with --no-fork + + this function should try not to raise exceptions, but if it does + the ocaml runtime should still print the exception, both the original, + and the one from this function, but to stderr this time + *) + let msg = msg_of exn bt in + prerr_endline msg; + (* See Printexc.set_uncaught_exception_handler, need to flush, + so has to call stop and flush *) + match !xenstored_logger with + | Some l -> error "xenstored-fallback" "%s" msg; l.stop () + | None -> + (* Too early, no logger set yet. + We normally try to use the configured logger so we don't flood syslog + during development for example, or if the user has a file set + *) + try Syslog.log Syslog.Daemon Syslog.Err msg + with e -> + let bt = Printexc.get_raw_backtrace () in + prerr_endline @@ msg_of e bt diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml index 35b8cbd43f..4d5851c5cb 100644 --- a/tools/ocaml/xenstored/xenstored.ml +++ b/tools/ocaml/xenstored/xenstored.ml @@ -355,7 +355,8 @@ let tweak_gc () = Gc.set { (Gc.get ()) with Gc.max_overhead = !Define.gc_max_overhead } -let _ = +let () = + Printexc.set_uncaught_exception_handler Logging.fallback_exception_handler; let cf = do_argv in let pidfile = if Sys.file_exists (config_filename cf) then -- generated by git-patchbot for /home/xen/git/xen.git#master
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |