Module Miou_unixSource

The Unix layer of Miou.

This module offers a re-implementation of the I/O according to Miou's model. This module is essentially concerned with reading and writing Unix.file_descr from sockets, pipes, fifos, terminals (and pseudo-terminals) and probably devices. For all these types of file_descr, reading/writing can block (waiting for bytes or waiting for the system's internal buffer to be free).

This is not generally the case for files and folders where read/write does not block. So, as far as files/folders are concerned, there is no point in using the suspend/resume mechanisms offered by Miou. These mechanisms (and the use of poll(2)/ppoll(2)) could actually degrade performance. It is therefore advisable to use the Unix module directly rather than Miou_unix for files/folders.

It should be noted, however, that reading/writing files can take a long time. So, in a cooperative context (with Miou.async), it may be worthwhile to increase the availability of other tasks to run with Miou.yield - so associate a Miou.yield with these operations. However, in the case of parallelization (Miou.call), it is not necessary to cooperate with the other tasks as they run in parallel. In this sense, and depending on the design of your application, these operations should, or should not, be associated with a Miou.yield.

How to spawn & handle processes with Miou_unix?

The Miou_unix module essentially only provides suspension points for reading and writing blocking file_descr (such as sockets). But users would probably like another type of suspension: namely, suspension until a launched program (via Unix.create_process) has finished.

The underlying mechanism provided by the system to signal the end of a program's execution is not related to file_descr but to signals. Here is an example of how to launch and wait for the end of a program using signals and the Miou.Computation module.

let pid =
  Unix.create_process "sleep" [| "sleep"; "1" |] Unix.stdin Unix.stdout
    Unix.stderr
in
let c = Miou.Computation.create () in
let handler _sigchld =
  match Unix.waitpid [ WNOHANG ] pid with
  | 0, _ -> ()
  | pid', status when pid' = pid ->
      ignore (Miou.sys_signal Sys.sigchld Sys.Signal_default);
      assert (Miou.Computation.try_return c status)
in
ignore (Miou.sys_signal Sys.sigchld (Sys.Signal_handle handler));
match Miou.Computation.await_exn c with
| Unix.WEXITED _ -> ()
| Unix.WSIGNALED _ -> ()
| Unix.WSTOPPED _ -> ()

Here are some explanations of the code above.

  1. There is no reference to the Miou_unix module (although there are references to Unix). As we said, Miou_unix only manages type:file-descr. In the code above, it is more about signal management.
  2. First, a program is launched with Unix.create_process and a handler is installed on the SIGCHLD signal. Please refer to the Miou.sys_signal documentation.
  3. This handler then fills in a Miou.Computation.t value c which, at the same time, is suspended further on with Miou.Computation.await_exn.

The suspension performed by Miou.Computation.await_exn can cooperate with the execution of other Miou tasks. In this way, the termination of the program is no longer blocking and you can, at the same time, execute tasks cooperatively and/or in parallel.

The handler function (which completes our Miou.Computation.t) is always executed by dom0 (as specified in the Miou.sys_signal documentation).

Finally, it is entirely possible to extend this code in order to associate our Miou.Computation.t with the PIDs of several launched programs (in a Hashtbl, for example) in order to define a more generic handler capable of unblocking several suspension points.

Why not integrate such a mechanism into Miou_unix?

This code currently has a global side effect: it installs a handler to manage the SIGCHLD signal. Miou and Miou_unix are libraries that should only slightly modify the global state of your program.

Therefore, it is your responsibility to install such a handler in order to enforce the explicit nature of what your program does — and to prevent Miou and Miou_unix from doing things implicitly just because you want to depend on these libraries.

Sourcetype file_descr

Type of file-descriptors.

Sourceval of_file_descr : ?non_blocking:bool -> Unix.file_descr -> file_descr

of_file_descr ?non_blocking ?owner fd creates a new file_descr. Depending on non_blocking (defaults to true), we set the given fd to non-blocking mode or not.

Sourceval to_file_descr : file_descr -> Unix.file_descr

to_file_descr fd returns the real Unix.file_descr.

Sourceval unix_socket : unit -> file_descr

unix_socket () allocates a new Unix-domain socket.

I/O with TCP/IP protocol.

Sourceval tcpv4 : unit -> file_descr

tcpv4 () allocates a new TCP/IPv4 socket.

Sourceval tcpv6 : unit -> file_descr

tcpv6 () allocates a new TCP/IPv6 socket.

Sourceval bind_and_listen : ?backlog:int -> ?reuseaddr:bool -> ?reuseport:bool -> file_descr -> Unix.sockaddr -> unit

bind_and_listen fd sockaddr binds the given socket to the given sockaddr and set up the given fd for receiving connection requests. backlog is the maximal number of pending requests. The optional argument reuseaddr (defaults to true) sets the REUSEADDR socket option on the given fd. The optional argument reuseport (defaults to true sets the REUSEPORT socket option on the given fd.

NOTE: bind_and_listen can also be used with a udpv4/udpv6 file descriptor.

Sourceval accept : ?cloexec:bool -> file_descr -> file_descr * Unix.sockaddr

accept ?cloexec fd is a Miou friendly Unix.accept which returns file descriptors in non-blocking mode.

Sourceval connect : file_descr -> Unix.sockaddr -> unit

connect fd sockaddr is a Miou friendly Unix.connect. The function accepts only file_descrs in non-blocking mode.

Sourceval read : file_descr -> ?off:int -> ?len:int -> bytes -> int

read fd buf ~off ~len reads up to len bytes (defaults to Bytes.length buf - off) from the given file-descriptor fd, storing them in byte sequence buf, starting at position off in buf (defaults to 0). It returns the actual number of characters read, between 0 and len (inclusive).

Sourceval really_read : file_descr -> ?off:int -> ?len:int -> bytes -> unit

really_read fd buf ~off ~len reads len bytes (defaults to Bytes.length buf - off) from the given file-descriptor fd, storing them in byte sequence buf, starting at position off in buf (defaults to 0). If len = 0, really_read does nothing.

Sourceval write : file_descr -> ?off:int -> ?len:int -> string -> unit

write fd str ~off ~len writes len bytes (defaults to String.length str - off) from byte sequence str, starting at offset off (defaults to 0), to the given file-descriptor fd.

Sourceval close : file_descr -> unit

close fd closes properly the given fd.

I/O with UDP/IP protocol.

Sourceval udpv4 : unit -> file_descr

udpv4 () allocates a new UDP/IPv4 socket.

Sourceval udpv6 : unit -> file_descr

udpv6 () allocates a new UDP/IPv6 socket.

Sourceval recvfrom : file_descr -> ?off:int -> ?len:int -> bytes -> Unix.msg_flag list -> int * Unix.sockaddr

recvfrom fd ~off ~len buf flags receives up to len bytes (defaults to Bytes.length buf - off) from the given unconnected socket fd and store it into the given buf at offset off (defaults to 0). It returns the actual number of characters received, between 0 and len (inclusive) and the peer which sent these bytes.

Sourceval sendto : file_descr -> ?off:int -> ?len:int -> string -> Unix.msg_flag list -> Unix.sockaddr -> int

sendto fd ~off ~len str flags sockaddr sends len bytes (defaults to String.length str - off) from byte sequence str, starting at offset off (defaults to 0), to the destination sockaddr via the given file-descriptor fd.

Sleepers.

Sourceval sleep : float -> unit

sleep v suspends the current task and sleeps v seconds.

First entry point.

Sourceval run : ?g:Random.State.t -> ?domains:int -> (unit -> 'a) -> 'a
Sourcemodule Ownership : sig ... end
Sourcemodule Bitv = Miou_bitv

/

Sourceval blocking_read : ?name:string -> Unix.file_descr -> unit
Sourceval blocking_write : ?name:string -> Unix.file_descr -> unit