Lwt_unix.fork causes trouble
talex5 opened this issue · comments
The tests run Lwt_process.(pread (shell "echo test")
, but this isn't reliable.
Simpler test case:
open Eio.Std
let () =
Eio_main.run @@ fun env ->
Lwt_eio.with_event_loop ~clock:env#clock @@ fun _ ->
for _ = 1 to 100 do
let output = Lwt_eio.run_lwt (fun () ->
match Lwt_unix.fork () with
| 0 -> Unix._exit 1
| _child -> Lwt.return "ok"
) in
traceln "got: %s" output
done
Fails with:
+got: ok
+got: ok
fish: “dune exec -- ./examples/simple.…” terminated by signal SIGSEGV (Address boundary error)
(the number of "ok"s varies)
This is a bug in Lwt. It needs to use sigact.sa_flags = SA_ONSTACK
.
A work-around is to do this before running the Eio mainloop:
let () =
(* Let Lwt install its buggy signal handler now. Then we'll put it back. *)
Lwt_main.run (Lwt.pause ());
Sys.(set_signal sigchld) Signal_default
With this, you can't spawn processes using Lwt, but you can using Eio, and there's no memory corruption.
Probably needs an extension to Lwt's engine type: ocsigen/lwt#991
Just mentioning that the work-around above also seems to have worked to fix my code that was apparently hanging on Lwt_preemptive.detach
(I'm experimenting with Caqti_lwt's sqlite backend, which uses system threads, I think that was the problem).