Hi Ashish,
I realise I'm entering this conversation a bit late... but it is possible to get your
example working without any dark magic.
Aside: Use of blocking printf is confusing unless a flush is forced with [%!]:
let printf fmt = ksprintf (Core.Std.Printf.printf "%s%!") fmt
In your example, we want to [main2] to be composed as sleep-then-[main1], whilst ensuring
the fork occurs before starting the async scheduler. Consequently, we mustn't call [fork]
from [main1], but instead can define [run] to co-ordinate the fork and [Scheduler.go].
Once we ensure the async scheduler is started correctly in parent & child, Async's printf
works just fine, and no explicit flush is required.
Nick.
open Core.Std
open Async.Std
let main1 ~where () : unit Deferred.t =
match where with
| `In_the_parent child_pid -> (
let child_pid = Pid.to_int child_pid in
let pid = Unix.getpid() |> Pid.to_int in
printf "START: In the parent %d of child %d\n" pid child_pid;
after (sec 1.) >>= fun () ->
printf "END: In the parent %d of child %d\n" pid child_pid;
shutdown 0;
Deferred.unit
)
| `In_the_child -> (
let ppid = Unix.getppid() |> Option.value_map ~default:0 ~f:Pid.to_int in
let pid = Unix.getpid() |> Pid.to_int in
printf "START: In the child %d with parent %d\n" pid ppid;
after (sec 1.) >>= fun () ->
printf "END: In the child %d with parent %d\n" pid ppid;
shutdown 42; (* no-one collects this exit code *)
Deferred.unit
)
let main2 ~where () : unit Deferred.t =
after (sec 1.) >>= fun () ->
main1 ~where ()
let run main () : unit =
let where = Core.Std.Unix.fork() in
don't_wait_for (main ~where ());
never_returns (Scheduler.go())
let cmd1 = Command.basic'
~summary:"run main1" Command.Param.nil (run main1)
let cmd2 = Command.basic'
~summary:"run main2" Command.Param.nil (run main2)
let () = Command.group
~summary:"fork + async example"
["cmd1",cmd1; "cmd2",cmd2]
|> Command.run