I’m experimenting with async, core, and a pre-forking tcp server. I noticed that Log.Global.info was not logging anything in my child processes, but only if the parent process logged something before forking.
I narrowed this down a bit and produced the following program (async and core 0.14.0, OCaml 4.10, Linux) that shows that after the parent process uses Writer.stderr, newly forked child processes cannot (writes are seemingly stuck; there is no output, but the Deferred is never completed). In my example program, I expect both child1 and child2 to write two messages each: one via Debug.eprintf and one via Writer.stderr. In between forking child1 and child2, the parent forces Writer.stderr.
Am I doing something wrong? Could Writer.stderr be “reset” somehow (like the Scheduler is)?
parent forced Writer.stderr child1 via Debug.eprintf child1 via Writer.stderr exited normally: child1 child2 via Debug.eprintf
child2 never writes via Writer.stderr, and never exits (which it would do after flushing Writer.stderr).
open Core open Async let in_child name = Scheduler.reset_in_forked_process (); let out = force Writer.stderr in let msg = Format.sprintf "%s via Writer.stderr\n" name in begin Writer.write out msg; Writer.flushed out >>= fun _ -> exit 0 end |> don't_wait_for; schedule (fun () -> Debug.eprintf "%s via Debug.eprintf" name); Scheduler.go () let waitpid pid name = Unix.waitpid pid >>| fun status -> Debug.eprintf "%s: %s" (Core.Unix.Exit_or_signal.to_string_hum status) name let () = match Core.Unix.fork () with | `In_the_child -> in_child "child1" |> never_returns | `In_the_parent pid1 -> let _ = force Writer.stderr in Debug.eprintf "parent forced Writer.stderr"; match Core.Unix.fork () with | `In_the_child -> in_child "child2" |> never_returns | `In_the_parent pid2 -> begin waitpid pid1 "child1" >>= fun () -> waitpid pid2 "child2" end |> don't_wait_for; Scheduler.go () |> never_returns