For communicating a dynamically chosen TCP port from a child process to its parent.
This is used to fork+exec a child process that will create create a TCP server that listens to a dynamically chosen port, and to make the port number available in the parent process once the child process is listening on the port.
Here is the intended usage:
1. The parent creates a Dynamic_port_writer.t value together with a deferred that
will eventually be determined with the port assigned to the child process by the OS.
2. The parent communicates the Dynamic_port_writer.t value to a child it has
spawned. This can happen in a number of ways,
to_string and either arg or of_string.3. The child calls Tcp.Server.create with the value returned by where_to_listen.
Once the server created in step (3) is listening on its OS-assigned port, the parent's deferred obtained in step (1) will soon become determined with the value of the port.
Code for the parent process would look something like:
      Dynamic_port_writer.create ()
      >>= fun (dynamic_port_writer, port_d) ->
      Unix.fork_exec ~prog
        ~argv:([ prog ]
               @ Dynamic_port_writer.flag_args dynamic_port_writer
               @ [ ... other args ... ])
        ()
      >>= fun _child_pid ->
      port_d
      >>= fun r ->
      let `Port port = ok_exn r in
      Tcp.connect (Tcp.Where_to_connect.of_host_and_port {host = "localhost"; port})
      >>= fun (_, reader, writer) ->
      ...Code for the Command.t for the child process would look something like:
      Command.basic
        ~summary:"child"
        (Command.Spec.(empty +> Dynamic_port_writer.flag))
        (fun dynamic_port_writer () ->
           ...
           Tcp.Server.create
               (Dynamic_port_writer.where_to_listen dynamic_port_writer)
               (fun _ reader writer -> ...))include sig ... endval bin_t : t Bin_prot.Type_class.tval bin_read_t : t Bin_prot.Read.readerval __bin_read_t__ : (int ‑> t) Bin_prot.Read.readerval bin_reader_t : t Bin_prot.Type_class.readerval bin_size_t : t Bin_prot.Size.sizerval bin_write_t : t Bin_prot.Write.writerval bin_writer_t : t Bin_prot.Type_class.writerval bin_shape_t : Bin_prot.Shape.tval t_of_sexp : Sexplib.Sexp.t ‑> tval sexp_of_t : t ‑> Sexplib.Sexp.tval create : unit ‑> (t * [ `Port of int ] Core.Or_error.t Async_extra__.Import.Deferred.t) Async_extra__.Import.Deferred.tval where_to_listen : t ‑> (Async_extra__.Import.Socket.Address.Inet.t, int) Tcp.Where_to_listen.tval flag : t Core.Command.Spec.paramOne can pass a t from parent to child by including flag_args t in the command-line
arguments and using flag in the Command.t in the child.
val flag_args : t ‑> string list