Hello,
I’m facing strange behaviors in management of signals (Sys.set_signal). And I’ve some questions (see at end of this post)
Here is the Ocaml code
let f signal = (* Do not do that in real (never usr print) *) Fmt.pr "Got signal %d@." signal; exit 1 let route_sig () = let open Sys in Fmt.pr "Route %d@." sigint; set_signal sigint (Signal_handle f) let _ = route_sig (); Fmt.pr "Waiting.....@."; Unix.sleep 60; Fmt.pr "Finalizing.....@."
Here is the C code
#include #include #include #include static void sig_handler(int signo) { /* Never use printf in signal - just for demo */ printf("Got signal %d\n", signo); exit (1); } static void route_sig () { printf("Route %d\n", SIGINT); signal(SIGINT, sig_handler); } int main(void) { route_sig(); printf("Waiting....\n"); sleep(60); printf("Finalizing.....\n"); return 0; } **While running the Ocaml program and then sending a sigint, the sig_handler is called after the Unix.sleep**./sigint.ml.out [000.0] Route -6 [000.0] Waiting.... [008.1] ^C [060.2] Got signal -6With the C program, the sig_handler is called immediately
./sigint.c.out [000.0] Route 2 [000.0] Waiting.... [007.8] ^C [007.8] Got signal 2That probably means that the Ocaml sig_handler is not called from the system signal but through a kind of callback;
That really sounds strange as it is not mentionned in the Sys documentation.Now, supposing that we want to catch the sigsegv
C example#include #include #include #include static void sig_handler(int signo) { /* Never use printf in signal - just for demo */ printf("Got signal %d\n", signo); exit (1); } static void route_sig () { printf("Route %d\n", SIGSEGV); signal(SIGSEGV, sig_handler); } int main(void) { int *a=0; route_sig(); printf("Waiting....\n"); *a=1; printf("Finalizing.....\n"); return 0; }./sigsegv.c.out [000.0] Route 11 [000.1] Waiting.... [000.1] Got signal 11The same in OCaml + Buggy C part
C: #include void sigv_c_fct () { int *a= NULL; *a=1; } Ocaml: external sigv_c_fct:unit -> unit = "sigv_c_fct" let f signo = (* Do not do that in real (never usr print) *) Fmt.pr "Got signal %d@." signo; exit 1 let route_sig () = let open Sys in Fmt.pr "Route %d@." sigsegv; set_signal sigsegv (Signal_handle f) let _ = route_sig (); Fmt.pr "Waiting.....@."; sigv_c_fct (); Fmt.pr "Finalizing.....@."./sigsegv.ml.out [000.0] Route -10 [000.1] Waiting.... and never endstrace shows that SIGSEGV is generated until I sigkill the process
rt_sigreturn({mask=[]}) = 0 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} --- rt_sigreturn({mask=[]}) = 0 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---That shows that the system signal has been released.
The main process redo the faulty instruction (PC has not changed) and then regenerate the signal
The Ocaml handler is never called
I suspect that sigbus/sigill may do the same.
Q1 : I there something I miss in the Sys.set_signal usage?
For some reason (very small permanent storage), I cannot generate core while processes are kill with a SEGV.
Routing sigsegv in OCaml should help to store some useful informations of my process when it crashes but I cannot do it like that.Q2: How can I go back in Ocaml in the signal context / is it possible ?
Thanks,
Erwan