eio
eio copied to clipboard
Signals don't get processed while Fibers are scheduled?
I couldn't get eio to handle my signals while another fiber is running (even if sleeping). Take this pathological case:
open Eio.Std
let () =
Sys.(
set_signal
sigint
(Signal_handle
(fun i ->
Format.eprintf "handle signal: %d@." i;
exit 0)));
Eio_main.run (fun _env ->
Switch.run (fun sw ->
Fiber.fork ~sw (fun () -> Eio.Time.sleep (Eio.Stdenv.clock _env) 5.)))
You can send ctrl+C to the program while it's running and it won't process it until after 5 seconds (when the eio fiber ends).
Tested on macOS (with eio_luv)
This seems to work well with eio_linux.
I'm not sure whether this can work with eio_luv at all (it looks like it takes over signal handling while its event loop is running). A workaround I've found is to install my own signal handling with Luv and run a separate loop:
open Eio.Std
let () =
let loop = Luv.Loop.init () |> Result.get_ok in
let () =
match Luv.Signal.init ~loop () with
| Ok handle ->
let handler () =
Format.eprintf "handle signal@.";
Luv.Handle.close handle ignore
in
Result.get_ok (Luv.Signal.start handle Luv.Signal.sigint handler)
| Error _ -> ()
in
Eio_main.run (fun env ->
Switch.run (fun sw ->
let _d =
(* Not sure why `Eio.Domain_manager.run` doesn't work *)
Domain.spawn (fun () ->
let (_ : bool) = Luv.Loop.run ~loop () in
())
in
Fiber.fork ~sw (fun () -> Eio.Time.sleep (Eio.Stdenv.clock env) 5.)))
This works for now but it imposes a dependency on luv on linux.
We probably need an abstraction for signals (an env#signals perhaps, or something in Eio_unix).
I'm having a quick jab at this, one of the possible issues is that luv exports a considerably smaller set of signals, blame is on windows support:
(** {1:signals Signal numbers}
For the moment, the signals exposed are those that are both present on Unix
and present or emulated by libuv on Windows. See
{{:http://docs.libuv.org/en/v1.x/signal.html#windows-notes} {i Windows
notes}} and {{:http://docs.libuv.org/en/v1.x/signal.html#unix-notes} {i Unix
notes}}.
Note that these signal numbers do not, in general, match the ones in module
[Sys] in the OCaml standard library. *)
val sigabrt : int
val sigfpe : int
val sighup : int
val sigill : int
val sigint : int
val sigkill : int
val sigsegv : int
val sigterm : int
val sigwinch : int
So I have this, needs cleanup and a bit more work:
Eio_main.run @@ fun env ->
let signal = Eio.Stdenv.signal env in
let clock = Eio.Stdenv.clock env in
signal#set Sys.sigint (fun signum -> traceln "got signal %d" signum);
Eio.Time.sleep clock 10.0;
signal#unset Sys.sigint;
Eio.Time.sleep clock 10.0;
traceln ":*"
sam:eio: dune build && EIO_BACKEND=luv ./_build/default/bench/sigtest.exe
+luv signal -6 set
^C+got signal -6
^C+got signal -6
^C+got signal -6
^C+got signal -6
^C+got signal -6
+luv signal -6 unset
^C
Closed by #436.