[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



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.