Hello
Below is a small program that creates a pair of file descriptors via `Unix.socketpair`, and forks a child process. The parent then proceeds to loop writing a byte of data on its descriptor on each iteration, which then is read by the child, after dup2'ing its descriptor to stdin.
I tried to write a wrapper to Unix.fork as below but it seems to block forever, so I had to replace it with a `return (Core.Unix.fork ())`. Is this expected?
let fork () =
In_thread.syscall_exn ~name:"fork" Core.Std.Unix.fork
The second question is that the commented calls to `Unix.close` in the program below cause a "broken pipe error" when uncommented. This is unexpected because in the parent process the descriptor is not used at all, and in the child process it has been dup2'd to stdin, so closing it should cause no issues either. Any hints on what could be going on?
open Core.Std
open Async.Std
let dup2 src dst =
In_thread.syscall_exn ~name:"dup2"
(fun () ->
Fd.with_file_descr_exn src
(fun src ->
Fd.with_file_descr_exn dst
(fun dst ->
Core.Std.Unix.dup2 ~src ~dst)))
let fork () =
return (Core.Std.Unix.fork ())
let write_to_child wr =
let rec write i =
printf "-> %d\n%!" i;
Writer.write wr (Int.to_string i);
Writer.flushed wr >>= fun () ->
Clock.after (Time.Span.of_sec 1.0) >>= fun () ->
write (i + 1) in
write 0
let read_from_parent rd =
let rec read () =
let buf = String.create 1 in
Reader.read rd buf >>= function
| `Eof ->
printf "EOF\n%!";
return ()
| `Ok _ ->
printf "<- %d\n%!" (Int.of_string buf);
read () in
read ()
let main =
let parent_fd, child_fd = Unix.socketpair () in
let child () =
let stdin = Fd.stdin () in
dup2 child_fd stdin >>= fun () ->
(* XXX causes EPIPE *)
(*Unix.close child_fd >>= fun () ->*)
let rd = Reader.create stdin in
read_from_parent rd in
let parent pid =
(* XXX causes EPIPE *)
(*Unix.close child_fd >>= fun () ->*)
let wr = Writer.create parent_fd in
let _ = write_to_child wr in
Unix.waitpid pid >>= function
| Ok () -> exit 0
| _ -> exit 1 in
fork () >>= function
| `In_the_child -> child ()
| `In_the_parent pid -> parent pid
let () =
never_returns (Scheduler.go ())
Thanks in advance,
Andre