Module Lwt_unix

module Lwt_unix : sig..end

Cooperative system calls


This modules maps system calls, like those of the standard library's Unix module, to cooperative ones, which will not block the program.

The semantics of all operations is the following: if the action (for example reading from a file descriptor) can be performed immediately, it is done and returns immediately, otherwise it returns a sleeping thread which is woken up when the operation completes.

Most operations on sockets and pipes (on Windows it is only sockets) are cancelable, meaning you can cancel them with Lwt.​cancel. For example if you want to read something from a file descriptor with a timeout, you can cancel the action after the timeout and the reading will not be performed if not already done.

For example, consider that you have two sockets sock1 and sock2. You want to read something from sock1 or exclusively from sock2 and fail with an exception if a timeout of 1 second expires, without reading anything from sock1 and sock2, even if they become readable in the future.

Then you can do:

Lwt.pick
      [Lwt_unix.timeout 1.0;
       read sock1 buf1 ofs1 len1;
       read sock2 buf2 ofs2 len2]

In this case, it is guaranteed that exactly one of the three operations will complete, and the others will be cancelled.

val handle_unix_error : ('a -> 'b Lwt.t) -> 'a -> 'b Lwt.t

Same as Unix.handle_unix_error but catches lwt-level exceptions

Configuration

type async_method =  | Async_none(* <<div class="odocwiki_info"|~System calls are made synchronously~, and may block the
          entire program~.
>> *) | Async_detach(* <<div class="odocwiki_info"|~System calls are made in another system thread~, thus without
          blocking other ~Lwt threads~. ~The drawback is that it may
          degrade performance in some cases~.


          ~This is the default~.
>> *) | Async_switch(* <<div class="odocwiki_info"|~System calls are made in the main thread~, and if one blocks
          the execution continue in another system thread~. ~This method
          is the most efficient~, also you will get better performance
          if you force all threads to run on the same cpu~. ~On linux
          this can be done by using the command <<span class="odocwiki_inlinecode"|taskset>>~.


          ~Note that this method is still experimental~.
>> *)

For system calls that cannot be made asynchronously, Lwt uses one of the following method:

val default_async_method : unit -> async_method

Returns the default async method.

This can be initialized using the environment variable "LWT_ASYNC_METHOD" with possible values "none", "detach" and "switch".

val set_default_async_method : async_method -> unit

Sets the default async method.

val async_method : unit -> async_method

async_method () returns the async method used in the current thread.

val async_method_key : async_method Lwt.key

The key for storing the local async method.

val with_async_none : (unit -> 'a) -> 'a

with_async_none f is a shorthand for:

Lwt.with_value async_method_key (Some Async_none) f
val with_async_detach : (unit -> 'a) -> 'a

with_async_detach f is a shorthand for:

Lwt.with_value async_method_key (Some Async_detach) f
val with_async_switch : (unit -> 'a) -> 'a

with_async_switch f is a shorthand for:

Lwt.with_value async_method_key (Some Async_switch) f

Sleeping

val sleep : float -> unit Lwt.t

sleep d is a thread that remains suspended for d seconds and then terminates.

val yield : unit -> unit Lwt.t

yield () is a thread that suspends itself and then resumes as soon as possible and terminates.

val auto_yield : float -> unit -> unit Lwt.t

auto_yield timeout returns a function f that will yield every timeout seconds.

exception Timeout

Exception raised by timeout operations

val timeout : float -> 'a Lwt.t

timeout d is a thread that remains suspended for d seconds and then fails with Lwt_unix.​Timeout.

val with_timeout : float -> (unit -> 'a Lwt.t) -> 'a Lwt.t

with_timeout d f is a short-hand for:

Lwt.pick [Lwt_unix.timeout d; f ()]

Operation on file-descriptors

type file_descr

The abstract type for file descriptors. A Lwt file descriptor is a pair of a unix file descriptor (of type Unix.file_descr) and a state.

A file descriptor may be:

  • opened, in which case it is fully usable
  • closed or aborted, in which case it is no longer usable
type state =  | Opened(* <<div class="odocwiki_info"|~The **file descriptor** is opened
>> *) | Closed(* <<div class="odocwiki_info"|~The **file descriptor** has been closed by <<a_api | val Lwt_unix.close >>~. ~It must
          not be used for any operation~.
>> *) | Aborted of exn(* <<div class="odocwiki_info"|~The **file descriptor** has been aborted~, the only operation
          possible is <<a_api | val Lwt_unix.close >>~, all others will fail~.
>> *)

State of a file descriptor

val state : file_descr -> state

state fd returns the state of fd

val unix_file_descr : file_descr -> Unix.file_descr

Returns the underlying unix file descriptor. It always succeeds, even if the file descriptor's state is not Open.

val of_unix_file_descr : 
  ?blocking:bool ->
  ?set_flags:bool -> Unix.file_descr -> file_descr

Wraps a Unix file descriptor fd in an Lwt_unix.file_descr fd'.

~blocking controls the internal strategy Lwt uses to perform I/O on the underlying fd. Regardless of ~blocking, at the API level, Lwt_unix.read, Lwt_unix.write, etc. on fd' always block the Lwt thread, but never block the whole process. However, for performance reasons, it is important that ~blocking match the actual blocking mode of fd.

If ~blocking is not specified, of_unix_file_descr chooses non-blocking mode for Unix sockets, Unix pipes, and Windows sockets, and blocking mode for everything else.

of_unix_file_descr runs a system call to set the specified or chosen blocking mode on the underlying fd.

To prevent of_unix_file_descr from running this system call, you can pass ~set_flags:false. Note that, in this case, if ~blocking, whether passed explicitly or chosen by Lwt, does not match the true blocking mode of the underlying fd, I/O on fd' will suffer performance degradation.

Note that ~set_flags is effectively always false if running on Windows and fd is not a socket.

Generally, non-blocking I/O is faster: for blocking I/O, Lwt typically has to run system calls in worker threads to avoid blocking the process. See your system documentation for whether particular kinds of file descriptors support non-blocking I/O.

val blocking : file_descr -> bool Lwt.t

blocking fd indicates whether Lwt is internally using blocking or non-blocking I/O with fd.

Note that this may differ from the blocking mode of the underlying Unix file descriptor (i.e. unix_file_descr fd).

See Lwt_unix.​of_unix_file_descr for details.

val set_blocking : ?set_flags:bool -> file_descr -> bool -> unit

set_blocking fd b causes Lwt to internally use blocking or non-blocking I/O with fd, according to the value of b.

If ~set_flags is true (the default), Lwt also makes a system call to set the underlying file descriptor's blocking mode to match. Otherwise, set_blocking is only informational for Lwt.

It is important that the underlying file descriptor actually have the same blocking mode as that indicated by b.

See Lwt_unix.​of_unix_file_descr for details.

val abort : file_descr -> exn -> unit

abort fd exn makes all current and further uses of the file descriptor fail with the given exception. This put the file descriptor into the Aborted state.

If the file descriptor is closed, this does nothing, if it is aborted, this replace the abort exception by exn.

Note that this only works for reading and writing operations on file descriptors supporting non-blocking mode.

Process handling

val fork : unit -> int

fork () does the same as Unix.fork. You must use this function instead of Unix.fork when you want to use Lwt in the child process.

Notes:

  • in the child process all pending jobs are canceled,
  • if you are going to use Lwt in the parent and the child, it is a good idea to call Lwt_io.​flush_all before callling Lwt_unix.​fork to avoid double-flush.
type process_status = Unix.process_status  =  | WEXITED of int | WSIGNALED of int | WSTOPPED of int
type wait_flag = Unix.wait_flag  =  | WNOHANG | WUNTRACED
val wait : unit -> (int * process_status) Lwt.t

Wrapper for Unix.wait

val waitpid : 
  wait_flag list ->
  int -> (int * process_status) Lwt.t

Wrapper for Unix.waitpid

type resource_usage = {
  ru_utime: float;(* <<div class="odocwiki_info"|~User time used
>> *)  ru_stime: float;(* <<div class="odocwiki_info"|~System time used
>> *)}

Resource usages

val wait4 : 
  wait_flag list ->
  int -> (int * process_status * resource_usage) Lwt.t

wait4 flags pid returns (pid, status, rusage) where (pid, status) is the same result as Unix.waitpid flags pid, and rusage contains accounting information about the child.

On windows it will always returns { utime = 0.0; stime = 0.0 }.

val wait_count : unit -> int

Returns the number of threads waiting for a child to terminate.

val system : string -> process_status Lwt.t

Executes the given command, waits until it terminates, and return its termination status. The string is interpreted by the shell /bin/sh on Unix and cmd.exe on Windows. The result WEXITED 127 indicates that the shell couldn't be executed.

Basic file input/output

val stdin : file_descr

The standard file descriptor for input. This one is usually a terminal is the program is started from a terminal.

val stdout : file_descr

The standard file descriptor for output

val stderr : file_descr

The standard file descriptor for printing error messages

type file_perm = Unix.file_perm
type open_flag = Unix.open_flag  =  | O_RDONLY | O_WRONLY | O_RDWR | O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC | O_EXCL | O_NOCTTY | O_DSYNC | O_SYNC | O_RSYNC | O_SHARE_DELETE | O_CLOEXEC
val openfile : 
  string ->
  open_flag list ->
  file_perm -> file_descr Lwt.t

Wrapper for Unix.openfile.

val close : file_descr -> unit Lwt.t

Close a file descriptor. This close the underlying unix file descriptor and set its state to Closed

val read : file_descr -> bytes -> int -> int -> int Lwt.t

read fd buf ofs len reads up to len bytes from fd, and writes them to buf, starting at offset ofs. The function immediately evaluates to an Lwt thread, which waits for the operation to complete. If it completes successfully, the thread indicates the number of bytes actually read, or zero if the end of file has been reached.

Note that the Lwt thread waits for data (or end of file) even if the underlying file descriptor is in non-blocking mode. See Lwt_unix.​of_unix_file_descr for a discussion of non-blocking I/O and Lwt.

If Lwt is using blocking I/O on fd, read writes data into a temporary buffer, then copies it into buf.

The thread can fail with any exception that can be raised by Unix.read, except Unix.Unix_error Unix.EAGAIN, Unix.Unix_error Unix.EWOULDBLOCK or Unix.Unix_error Unix.EINTR.

val write : file_descr -> bytes -> int -> int -> int Lwt.t

write fd buf ofs len writes up to len bytes to fd from buf, starting at buffer offset ofs. The function immediately evaluates to an Lwt thread, which waits for the operation to complete. If the operation completes successfully, the thread indicates the number of bytes actually written, which may be less than len.

Note that the Lwt thread waits to write even if the underlying file descriptor is in non-blocking mode. See Lwt_unix.​of_unix_file_descr for a discussion of non-blocking I/O and Lwt.

If Lwt is using blocking I/O on fd, buf is copied before writing.

The thread can fail with any exception that can be raised by Unix.single_write, except Unix.Unix_error Unix.EAGAIN, Unix.Unix_error Unix.EWOULDBLOCK or Unix.Unix_error Unix.EINTR.

val write_string : file_descr -> string -> int -> int -> int Lwt.t
module IO_vectors : sig..end

Sequences of buffer slices for Lwt_unix.​writev.

val readv : file_descr -> IO_vectors.t -> int Lwt.t

readv fd vs reads bytes from fd into the buffer slices vs. If the operation completes successfully, the resulting thread indicates the number of bytes read.

Data is always read directly into Bigarray slices. If the Unix file descriptor underlying fd is in non-blocking mode, data is also read directly into bytes slices. Otherwise, data for bytes slices is first read into temporary buffers, then copied.

Note that the returned Lwt thread is blocked until failure or a successful read, even if the underlying file descriptor is in non-blocking mode. See Lwt_unix.​of_unix_file_descr for a discussion of non-blocking I/O and Lwt.

If Lwt_unix.​IO_vectors.​system_limit is Some n and the count of slices in vs exceeds n, then Lwt_unix.readv reads only into the first n slices of vs.

Not implemented on Windows. It should be possible to implement, upon request, for Windows sockets only.

See readv(3p). Since 2.7.0

val writev : file_descr -> IO_vectors.t -> int Lwt.t

writev fd vs writes the bytes in the buffer slices vs to the file descriptor fd. If the operation completes successfully, the resulting thread indicates the number of bytes written.

If the Unix file descriptor underlying fd is in non-blocking mode, writev does not make a copy the bytes before writing. Otherwise, it copies bytes slices, but not Bigarray slices.

Note that the returned Lwt thread is blocked until failure or a successful write, even if the underlying descriptor is in non-blocking mode. See Lwt_unix.​of_unix_file_descr for a discussion of non-blocking I/O and Lwt.

If Lwt_unix.​IO_vectors.​system_limit is Some n and the count of slices in vs exceeds n, then Lwt_unix.writev passes only the first n slices in vs to the underlying writev system call.

Not implemented on Windows. It should be possible to implement, upon request, for Windows sockets only.

The behavior of writev when vs has zero slices depends on the system, and may change in future versions of Lwt. On Linux, writev will succeed and write zero bytes. On BSD (including macOS), writev will fail with Unix.Unix_error (Unix.EINVAL, "writev", ...).

See writev(3p). Since 2.7.0

val readable : file_descr -> bool

Returns whether the given file descriptor is currently readable.

val writable : file_descr -> bool

Returns whether the given file descriptor is currently writable.

val wait_read : file_descr -> unit Lwt.t

waits (without blocking other threads) until there is something to read on the file descriptor

val wait_write : file_descr -> unit Lwt.t

waits (without blocking other threads) until it is possible to write on the file descriptor

Seeking and truncating

type seek_command = Unix.seek_command  =  | SEEK_SET | SEEK_CUR | SEEK_END
val lseek : file_descr -> int -> seek_command -> int Lwt.t

Wrapper for Unix.lseek

val truncate : string -> int -> unit Lwt.t

Wrapper for Unix.truncate

val ftruncate : file_descr -> int -> unit Lwt.t

Wrapper for Unix.ftruncate

Syncing

val fsync : file_descr -> unit Lwt.t

Synchronise all data and metadata of the file descriptor with the disk. On Windows it uses FlushFileBuffers.

val fdatasync : file_descr -> unit Lwt.t

Synchronise all data (but not metadata) of the file descriptor with the disk.

Note that fdatasync is not available on Windows and OS X.

File status

type file_kind = Unix.file_kind  =  | S_REG | S_DIR | S_CHR | S_BLK | S_LNK | S_FIFO | S_SOCK
type stats = Unix.stats  = {
  st_dev: int;  st_ino: int;  st_kind: file_kind;  st_perm: file_perm;  st_nlink: int;  st_uid: int;  st_gid: int;  st_rdev: int;  st_size: int;  st_atime: float;  st_mtime: float;  st_ctime: float;}
val stat : string -> stats Lwt.t

Wrapper for Unix.stat

val lstat : string -> stats Lwt.t

Wrapper for Unix.lstat

val fstat : file_descr -> stats Lwt.t

Wrapper for Unix.fstat

val file_exists : string -> bool Lwt.t

file_exists name tests if a file named name exists.

Note that file_exists behaves similarly to Sys.file_exists:

  • "file" is interpreted as "directory entry" in this context
val utimes : string -> float -> float -> unit Lwt.t

utimes path atime mtime updates the access and modification times of the file at path. The access time is set to atime and the modification time to mtime. To set both to the current time, call utimes path 0. 0..

This function corresponds to Unix.utimes. See also utimes(3p). Since 2.6.0

val isatty : file_descr -> bool Lwt.t

Wrapper for Unix.isatty

File operations on large files

module LargeFile : sig..end

Operations on file names

Wrapper for Unix.unlink

val rename : string -> string -> unit Lwt.t

Wrapper for Unix.rename

Wrapper for Unix.link

File permissions and ownership

val chmod : string -> file_perm -> unit Lwt.t

Wrapper for Unix.chmod

val fchmod : file_descr -> file_perm -> unit Lwt.t

Wrapper for Unix.fchmod

val chown : string -> int -> int -> unit Lwt.t

Wrapper for Unix.chown

val fchown : file_descr -> int -> int -> unit Lwt.t

Wrapper for Unix.fchown

type access_permission = Unix.access_permission  =  | R_OK | W_OK | X_OK | F_OK
val access : string