ocaml-multicore / lwt_eio

Use Lwt libraries from within Eio

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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).