1132 lines
33 KiB
OCaml
1132 lines
33 KiB
OCaml
(* Lightweight thread library for Objective Caml
|
|
* http://www.ocsigen.org/lwt
|
|
* Interface Lwt_unix
|
|
* Copyright (C) 2005-2008 Jérôme Vouillon
|
|
* Laboratoire PPS - CNRS Université Paris Diderot
|
|
* 2009 Jérémie Dimino
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as
|
|
* published by the Free Software Foundation, with linking exceptions;
|
|
* either version 2.1 of the License, or (at your option) any later
|
|
* version. See COPYING file for details.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*)
|
|
|
|
(** Cooperative system calls *)
|
|
|
|
(** This modules redefine system calls, as in the [Unix] module of the
|
|
standard library, but mapped into cooperative ones, which will not
|
|
block the program, letting other threads run.
|
|
|
|
The semantic of all operations is the following: if the action
|
|
(for example reading from a {b file descriptor}) can be performed
|
|
immediatly, it is done and returns immediatly, otherwise it
|
|
returns a sleeping threads which is waked up when the operation
|
|
completes.
|
|
|
|
Moreover all sleeping threads returned by function of this modules
|
|
are {b cancelable}, this means that you can cancel them with
|
|
{!Lwt.cancel}. For example if you want to read something from a {b
|
|
file descriptor} with a timeout, you can cancel the action after
|
|
the timeout and the reading will not be performed if not already
|
|
done.
|
|
|
|
More precisely, assuming that you have two {b file descriptor}
|
|
[fd1] and [fd2] and you want to read something from [fd1] or
|
|
exclusively from [fd2], and fail with an exception if a timeout of
|
|
1 second expires, without reading anything from [fd1] and [fd2],
|
|
even if they become readable in the future.
|
|
|
|
Then you can do:
|
|
|
|
{[
|
|
Lwt.pick [Lwt_unix.timeout 1.0; read fd1 buf1 ofs1 len1; read fd2 buf2 ofs2 len2]
|
|
]}
|
|
|
|
In this case it is guaranteed that exactly one of the three
|
|
operations will completes, and other will just 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 *)
|
|
|
|
(** {6 Configuration} *)
|
|
|
|
(** For system calls that cannot be made asynchronously, Lwt uses one
|
|
of the following method: *)
|
|
type async_method =
|
|
| Async_none
|
|
(** System calls are made synchronously, and may block the
|
|
entire program. *)
|
|
| Async_detach
|
|
(** System calls are made in another system thread, thus without
|
|
blocking other Lwt threads. The drawback is that it may
|
|
degrade performances in some cases.
|
|
|
|
This is the default. *)
|
|
| Async_switch
|
|
(** System calls are made in the main thread, and if one blocks
|
|
the execution continue in another system thread. This method
|
|
is the most efficint, also you will get better performances
|
|
if you force all threads to run on the same cpu. On linux
|
|
this can be done by using the command [taskset].
|
|
|
|
Note that this method is still experimental. *)
|
|
|
|
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_none f] is a shorthand for:
|
|
|
|
{[
|
|
Lwt.with_value async_method_key (Some Async_detach) f
|
|
]}
|
|
*)
|
|
|
|
val with_async_switch : (unit -> 'a) -> 'a
|
|
(** [with_async_none f] is a shorthand for:
|
|
|
|
{[
|
|
Lwt.with_value async_method_key (Some Async_switch) f
|
|
]}
|
|
*)
|
|
|
|
(** {6 Sleeping} *)
|
|
|
|
val sleep : float -> unit Lwt.t
|
|
(** [sleep d] is a threads which remain suspended for [d] seconds
|
|
and then terminates. *)
|
|
|
|
val yield : unit -> unit Lwt.t
|
|
(** [yield ()] is a threads which 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] which will yield
|
|
every [timeout] seconds. *)
|
|
|
|
exception Timeout
|
|
(** Exception raised by timeout operations *)
|
|
|
|
val timeout : float -> 'a Lwt.t
|
|
(** [timeout d] is a threads which remain suspended for [d] seconds
|
|
then fail with {!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 ()]
|
|
]}
|
|
*)
|
|
|
|
(** {6 Operation on file-descriptors} *)
|
|
|
|
type file_descr
|
|
(** The abstract type for {b file descriptor}s. A Lwt {b file
|
|
descriptor} is a pair of a unix {b file descriptor} (of type
|
|
[Unix.file_descr]) and a {b state}.
|
|
|
|
A {b file descriptor} may be:
|
|
|
|
- {b opened}, in which case it is fully usable
|
|
- {b closed} or {b aborted}, in which case it is no longer
|
|
usable *)
|
|
|
|
(** State of a {b file descriptor} *)
|
|
type state =
|
|
| Opened
|
|
(** The {b file descriptor} is opened *)
|
|
| Closed
|
|
(** The {b file descriptor} has been closed by {!close}. It must
|
|
not be used for any operation. *)
|
|
| Aborted of exn
|
|
(** The {b file descriptor} has been aborted, the only operation
|
|
possible is {!close}, all others will fail. *)
|
|
|
|
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 {b file descriptor}. It always
|
|
succeed, even if the {b file descriptor}'s state is not
|
|
{!Open}. *)
|
|
|
|
val of_unix_file_descr : ?blocking : bool -> ?set_flags : bool -> Unix.file_descr -> file_descr
|
|
(** Creates a lwt {b file descriptor} from a unix one.
|
|
|
|
[blocking] is the blocking mode of the file-descriptor, it
|
|
describe how Lwt will use it. In non-blocking mode, read/write
|
|
on this file descriptor are made using non-blocking IO; in
|
|
blocking mode they are made using the current async method. If
|
|
[blocking] is not specified it is guessed according to the file
|
|
kind: socket and pipes are in non-blocking mode and others are
|
|
in blocking mode.
|
|
|
|
If [set_flags] is [true] (the default) then the file flags are
|
|
modified according to the [blocking] argument, otherwise they
|
|
are left unchanged.
|
|
|
|
Note that the blocking mode is less efficient than the
|
|
non-blocking one, so it should be used only for file descriptors
|
|
that does not support asynchronous operations, such as regular
|
|
files, or for shared descriptors such as {!stdout}, {!stderr} or
|
|
{!stdin}. *)
|
|
|
|
val blocking : file_descr -> bool Lwt.t
|
|
(** [blocking fd] returns whether [fd] is used in blocking or
|
|
non-blocking mode. *)
|
|
|
|
val set_blocking : ?set_flags : bool -> file_descr -> bool -> unit
|
|
(** [set_blocking fd b] puts [fd] in blocking or non-blocking
|
|
mode. If [set_flags] is [true] (the default) then the file flags
|
|
are modified, otherwise the modification is only done at the
|
|
application level. *)
|
|
|
|
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 {b file
|
|
descriptor} into the {!Aborted} state.
|
|
|
|
If the {b file descrptor} 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. *)
|
|
|
|
(** {6 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
|
|
{!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] *)
|
|
|
|
(** Resource usages *)
|
|
type resource_usage = {
|
|
ru_utime : float;
|
|
(** User time used *)
|
|
|
|
ru_stime : float;
|
|
(** System time used *)
|
|
}
|
|
|
|
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
|
|
(** Wrapper for [Unix.system] *)
|
|
|
|
(** {6 Basic file input/output} *)
|
|
|
|
val stdin : file_descr
|
|
(** The standard {b file descriptor} for input. This one is usually
|
|
a terminal is the program is started from a terminal. *)
|
|
|
|
val stdout : file_descr
|
|
(** The standard {b file descriptor} for output *)
|
|
|
|
val stderr : file_descr
|
|
(** The standard {b 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
|
|
|
|
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 {b file descriptor}. This close the underlying unix {b
|
|
file descriptor} and set its state to {!Closed} *)
|
|
|
|
val read : file_descr -> string -> int -> int -> int Lwt.t
|
|
(** [read fd buf ofs len] has the same semantic as [Unix.read], but
|
|
is cooperative *)
|
|
|
|
val write : file_descr -> string -> int -> int -> int Lwt.t
|
|
(** [read fd buf ofs len] has the same semantic as [Unix.write], but
|
|
is cooperative *)
|
|
|
|
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 *)
|
|
|
|
(** {6 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] *)
|
|
|
|
(** {6 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 all platforms. *)
|
|
|
|
(** {6 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 isatty : file_descr -> bool Lwt.t
|
|
(** Wrapper for [Unix.isatty] *)
|
|
|
|
(** {6 File operations on large files} *)
|
|
|
|
module LargeFile : sig
|
|
val lseek : file_descr -> int64 -> seek_command -> int64 Lwt.t
|
|
(** Wrapper for [Unix.LargeFile.lseek] *)
|
|
|
|
val truncate : string -> int64 -> unit Lwt.t
|
|
(** Wrapper for [Unix.LargeFile.truncate] *)
|
|
|
|
val ftruncate : file_descr -> int64 -> unit Lwt.t
|
|
(** Wrapper for [Unix.LargeFile.ftruncate] *)
|
|
|
|
type stats =
|
|
Unix.LargeFile.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 : int64;
|
|
st_atime : float;
|
|
st_mtime : float;
|
|
st_ctime : float;
|
|
}
|
|
|
|
val stat : string -> stats Lwt.t
|
|
(** Wrapper for [Unix.LargeFile.stat] *)
|
|
|
|
val lstat : string -> stats Lwt.t
|
|
(** Wrapper for [Unix.LargeFile.lstat] *)
|
|
|
|
val fstat : file_descr -> stats Lwt.t
|
|
(** Wrapper for [Unix.LargeFile.fstat] *)
|
|
end
|
|
|
|
(** {6 Operations on file names} *)
|
|
|
|
val unlink : string -> unit Lwt.t
|
|
(** Wrapper for [Unix.unlink] *)
|
|
|
|
val rename : string -> string -> unit Lwt.t
|
|
(** Wrapper for [Unix.rename] *)
|
|
|
|
val link : string -> string -> unit Lwt.t
|
|
(** Wrapper for [Unix.link] *)
|
|
|
|
(** {6 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 -> access_permission list -> unit Lwt.t
|
|
(** Wrapper for [Unix.access] *)
|
|
|
|
(** {6 Operations on file descriptors} *)
|
|
|
|
val dup : file_descr -> file_descr
|
|
(** Wrapper for [Unix.dup] *)
|
|
|
|
val dup2 : file_descr -> file_descr -> unit
|
|
(** Wrapper for [Unix.dup2] *)
|
|
|
|
val set_close_on_exec : file_descr -> unit
|
|
(** Wrapper for [Unix.set_close_on_exec] *)
|
|
|
|
val clear_close_on_exec : file_descr -> unit
|
|
(** Wrapper for [Unix.clear_close_on_exec] *)
|
|
|
|
(** {6 Directories} *)
|
|
|
|
val mkdir : string -> file_perm -> unit Lwt.t
|
|
(** Wrapper for [Unix.mkdir] *)
|
|
|
|
val rmdir : string -> unit Lwt.t
|
|
(** Wrapper for [Unix.rmdir] *)
|
|
|
|
val chdir : string -> unit Lwt.t
|
|
(** Wrapper for [Unix.chdir] *)
|
|
|
|
val chroot : string -> unit Lwt.t
|
|
(** Wrapper for [Unix.chroot] *)
|
|
|
|
type dir_handle = Unix.dir_handle
|
|
|
|
val opendir : string -> dir_handle Lwt.t
|
|
(** Wrapper for [Unix.opendir] *)
|
|
|
|
val readdir : dir_handle -> string Lwt.t
|
|
(** Wrapper for [Unix.dir] *)
|
|
|
|
val readdir_n : dir_handle -> int -> string array Lwt.t
|
|
(** [readdir_n handle count] reads at most [count] entry from the
|
|
given directory. It is more efficient that callling [count]
|
|
times [readdir]. If the length of the returned array is smaller
|
|
than [count], this means that the end of the directory has been
|
|
reached. *)
|
|
|
|
val rewinddir : dir_handle -> unit Lwt.t
|
|
(** Wrapper for [Unix.rewinddir] *)
|
|
|
|
val closedir : dir_handle -> unit Lwt.t
|
|
(** Wrapper for [Unix.closedir] *)
|
|
|
|
val files_of_directory : string -> string Lwt_stream.t
|
|
(** [files_of_directory dir] returns the stream of all files of
|
|
[dir]. *)
|
|
|
|
(** {6 Pipes and redirections} *)
|
|
|
|
val pipe : unit -> file_descr * file_descr
|
|
(** [pipe ()] creates pipe using [Unix.pipe] and returns two lwt {b
|
|
file descriptor}s created from unix {b file_descriptor} *)
|
|
|
|
val pipe_in : unit -> file_descr * Unix.file_descr
|
|
(** [pipe_in ()] is the same as {!pipe} but maps only the unix {b
|
|
file descriptor} for reading into a lwt one. The second is not
|
|
put into non-blocking mode. You usually want to use this before
|
|
forking to receive data from the child process. *)
|
|
|
|
val pipe_out : unit -> Unix.file_descr * file_descr
|
|
(** [pipe_out ()] is the inverse of {!pipe_in}. You usually want to
|
|
use this before forking to send data to the child process *)
|
|
|
|
val mkfifo : string -> file_perm -> unit Lwt.t
|
|
(** Wrapper for [Unix.mkfifo] *)
|
|
|
|
(** {6 Symbolic links} *)
|
|
|
|
val symlink : string -> string -> unit Lwt.t
|
|
(** Wrapper for [Unix.symlink] *)
|
|
|
|
val readlink : string -> string Lwt.t
|
|
(** Wrapper for [Unix.readlink] *)
|
|
|
|
(** {6 Locking} *)
|
|
|
|
type lock_command =
|
|
Unix.lock_command =
|
|
| F_ULOCK
|
|
| F_LOCK
|
|
| F_TLOCK
|
|
| F_TEST
|
|
| F_RLOCK
|
|
| F_TRLOCK
|
|
|
|
val lockf : file_descr -> lock_command -> int -> unit Lwt.t
|
|
(** Wrapper for [Unix.lockf] *)
|
|
|
|
(** {6 User id, group id} *)
|
|
|
|
type passwd_entry =
|
|
Unix.passwd_entry =
|
|
{
|
|
pw_name : string;
|
|
pw_passwd : string;
|
|
pw_uid : int;
|
|
pw_gid : int;
|
|
pw_gecos : string;
|
|
pw_dir : string;
|
|
pw_shell : string
|
|
}
|
|
|
|
type group_entry =
|
|
Unix.group_entry =
|
|
{
|
|
gr_name : string;
|
|
gr_passwd : string;
|
|
gr_gid : int;
|
|
gr_mem : string array
|
|
}
|
|
|
|
val getlogin : unit -> string Lwt.t
|
|
(** Wrapper for [Unix.getlogin] *)
|
|
|
|
val getpwnam : string -> passwd_entry Lwt.t
|
|
(** Wrapper for [Unix.getpwnam] *)
|
|
|
|
val getgrnam : string -> group_entry Lwt.t
|
|
(** Wrapper for [Unix.getgrnam] *)
|
|
|
|
val getpwuid : int -> passwd_entry Lwt.t
|
|
(** Wrapper for [Unix.getpwuid] *)
|
|
|
|
val getgrgid : int -> group_entry Lwt.t
|
|
(** Wrapper for [Unix.getgrgid] *)
|
|
|
|
(** {6 Signals} *)
|
|
|
|
type signal_handler_id
|
|
(** Id of a signal handler, used to cancel it *)
|
|
|
|
val on_signal : int -> (int -> unit) -> signal_handler_id
|
|
(** [on_signal signum f] calls [f] each time the signal with numnber
|
|
[signum] is received by the process. It returns a signal handler
|
|
identifier which can be used to stop monitoring [signum]. *)
|
|
|
|
val disable_signal_handler : signal_handler_id -> unit
|
|
(** Stops receiving this signal *)
|
|
|
|
val signal_count : unit -> int
|
|
(** Returns the number of registered signal handler. *)
|
|
|
|
val reinstall_signal_handler : int -> unit
|
|
(** [reinstall_signal_handler signum] if any signal handler is
|
|
registered for this signal with {!on_signal}, it reinstall the
|
|
signal handler (with [Sys.set_signal]). This is usefull in case
|
|
another part of the program install another signal handler. *)
|
|
|
|
(** {6 Sockets} *)
|
|
|
|
type inet_addr = Unix.inet_addr
|
|
|
|
type socket_domain =
|
|
Unix.socket_domain =
|
|
| PF_UNIX
|
|
| PF_INET
|
|
| PF_INET6
|
|
|
|
type socket_type =
|
|
Unix.socket_type =
|
|
| SOCK_STREAM
|
|
| SOCK_DGRAM
|
|
| SOCK_RAW
|
|
| SOCK_SEQPACKET
|
|
|
|
type sockaddr = Unix.sockaddr = ADDR_UNIX of string | ADDR_INET of inet_addr * int
|
|
|
|
val socket : socket_domain -> socket_type -> int -> file_descr
|
|
(** [socket domain type proto] is the same as [Unix.socket] but maps
|
|
the result into a lwt {b file descriptor} *)
|
|
|
|
val socketpair : socket_domain -> socket_type -> int -> file_descr * file_descr
|
|
(** Wrapper for [Unix.socketpair] *)
|
|
|
|
val bind : file_descr -> sockaddr -> unit
|
|
(** Wrapper for [Unix.bind] *)
|
|
|
|
val listen : file_descr -> int -> unit
|
|
(** Wrapper for [Unix.listen] *)
|
|
|
|
val accept : file_descr -> (file_descr * sockaddr) Lwt.t
|
|
(** Wrapper for [Unix.accept] *)
|
|
|
|
val accept_n : file_descr -> int -> ((file_descr * sockaddr) list * exn option) Lwt.t
|
|
(** [accept_n fd count] accepts up to [count] connection in one time.
|
|
|
|
- if no connection is available right now, it returns a sleeping
|
|
thread
|
|
|
|
- if more that 1 and less than [count] are available, it returns
|
|
all of them
|
|
|
|
- if more that [count] are available, it returns the next
|
|
[count] of them
|
|
|
|
- if an error happen, it returns the connections that have been
|
|
successfully accepted so far and the error
|
|
|
|
[accept_n] has the advantage of improving performances. If you
|
|
want a more detailed description, you can have a look at:
|
|
|
|
{{:http://portal.acm.org/citation.cfm?id=1247435}Acceptable strategies for improving web server performance} *)
|
|
|
|
val connect : file_descr -> sockaddr -> unit Lwt.t
|
|
(** Wrapper for [Unix.connect] *)
|
|
|
|
type shutdown_command =
|
|
Unix.shutdown_command =
|
|
| SHUTDOWN_RECEIVE
|
|
| SHUTDOWN_SEND
|
|
| SHUTDOWN_ALL
|
|
|
|
val shutdown : file_descr -> shutdown_command -> unit
|
|
(** Wrapper for [Unix.shutdown] *)
|
|
|
|
val getsockname : file_descr -> sockaddr
|
|
(** Wrapper for [Unix.getsockname] *)
|
|
|
|
val getpeername : file_descr -> sockaddr
|
|
(** Wrapper for [Unix.getpeername] *)
|
|
|
|
type msg_flag =
|
|
Unix.msg_flag =
|
|
| MSG_OOB
|
|
| MSG_DONTROUTE
|
|
| MSG_PEEK
|
|
|
|
val recv : file_descr -> string -> int -> int -> msg_flag list -> int Lwt.t
|
|
(** Wrapper for [Unix.recv] *)
|
|
|
|
val recvfrom : file_descr -> string -> int -> int -> msg_flag list -> (int * sockaddr) Lwt.t
|
|
(** Wrapper for [Unix.recvfrom] *)
|
|
|
|
val send : file_descr -> string -> int -> int -> msg_flag list -> int Lwt.t
|
|
(** Wrapper for [Unix.send] *)
|
|
|
|
val sendto : file_descr -> string -> int -> int -> msg_flag list -> sockaddr -> int Lwt.t
|
|
(** Wrapper for [Unix.sendto] *)
|
|
|
|
(** An io-vector. Used by {!recv_msg} and {!send_msg}. *)
|
|
type io_vector = {
|
|
iov_buffer : string;
|
|
iov_offset : int;
|
|
iov_length : int;
|
|
}
|
|
|
|
val io_vector : buffer : string -> offset : int -> length : int -> io_vector
|
|
(** Creates an io-vector *)
|
|
|
|
val recv_msg : socket : file_descr -> io_vectors : io_vector list -> (int * Unix.file_descr list) Lwt.t
|
|
(** [recv_msg ~socket ~io_vectors] receives data into a list of
|
|
io-vectors, plus any file-descriptors that may accompany the
|
|
message.
|
|
|
|
This call is not available on windows. *)
|
|
|
|
val send_msg : socket : file_descr -> io_vectors : io_vector list -> fds : Unix.file_descr list -> int Lwt.t
|
|
(** [send_msg ~socket ~io_vectors ~fds] sends data from a list of
|
|
io-vectors, accompanied with a list of file-descriptor. If
|
|
fd-passing is not possible on the current system and [fds] is
|
|
not empty, it raises [Lwt_sys.Not_available "fd_passing"].
|
|
|
|
This call is not available on windows. *)
|
|
|
|
type credentials = {
|
|
cred_pid : int;
|
|
cred_uid : int;
|
|
cred_gid : int;
|
|
}
|
|
|
|
val get_credentials : file_descr -> credentials
|
|
(** [get_credentials fd] returns credential informations from the
|
|
given socket. *)
|
|
|
|
(** {8 Socket options} *)
|
|
|
|
type socket_bool_option =
|
|
Unix.socket_bool_option =
|
|
| SO_DEBUG
|
|
| SO_BROADCAST
|
|
| SO_REUSEADDR
|
|
| SO_KEEPALIVE
|
|
| SO_DONTROUTE
|
|
| SO_OOBINLINE
|
|
| SO_ACCEPTCONN
|
|
| TCP_NODELAY
|
|
| IPV6_ONLY
|
|
|
|
type socket_int_option =
|
|
Unix.socket_int_option =
|
|
| SO_SNDBUF
|
|
| SO_RCVBUF
|
|
| SO_ERROR
|
|
| SO_TYPE
|
|
| SO_RCVLOWAT
|
|
| SO_SNDLOWAT
|
|
|
|
type socket_optint_option = Unix.socket_optint_option = SO_LINGER
|
|
|
|
type socket_float_option =
|
|
Unix.socket_float_option =
|
|
| SO_RCVTIMEO
|
|
| SO_SNDTIMEO
|
|
|
|
val getsockopt : file_descr -> socket_bool_option -> bool
|
|
(** Wrapper for [Unix.getsockopt] *)
|
|
|
|
val setsockopt : file_descr -> socket_bool_option -> bool -> unit
|
|
(** Wrapper for [Unix.setsockopt] *)
|
|
|
|
val getsockopt_int : file_descr -> socket_int_option -> int
|
|
(** Wrapper for [Unix.getsockopt_int] *)
|
|
|
|
val setsockopt_int : file_descr -> socket_int_option -> int -> unit
|
|
(** Wrapper for [Unix.setsockopt_int] *)
|
|
|
|
val getsockopt_optint : file_descr -> socket_optint_option -> int option
|
|
(** Wrapper for [Unix.getsockopt_optint] *)
|
|
|
|
val setsockopt_optint : file_descr -> socket_optint_option -> int option -> unit
|
|
(** Wrapper for [Unix.setsockopt_optint] *)
|
|
|
|
val getsockopt_float : file_descr -> socket_float_option -> float
|
|
(** Wrapper for [Unix.getsockopt_float] *)
|
|
|
|
val setsockopt_float : file_descr -> socket_float_option -> float -> unit
|
|
(** Wrapper for [Unix.setsockopt_float] *)
|
|
|
|
val getsockopt_error : file_descr -> Unix.error option
|
|
(** Wrapper for [Unix.getsockopt_error] *)
|
|
|
|
(** {6 Host and protocol databases} *)
|
|
|
|
type host_entry =
|
|
Unix.host_entry =
|
|
{
|
|
h_name : string;
|
|
h_aliases : string array;
|
|
h_addrtype : socket_domain;
|
|
h_addr_list : inet_addr array
|
|
}
|
|
|
|
type protocol_entry =
|
|
Unix.protocol_entry =
|
|
{
|
|
p_name : string;
|
|
p_aliases : string array;
|
|
p_proto : int
|
|
}
|
|
|
|
type service_entry =
|
|
Unix.service_entry =
|
|
{
|
|
s_name : string;
|
|
s_aliases : string array;
|
|
s_port : int;
|
|
s_proto : string
|
|
}
|
|
|
|
val gethostname : unit -> string Lwt.t
|
|
(** Wrapper for [Unix.gethostname] *)
|
|
|
|
val gethostbyname : string -> host_entry Lwt.t
|
|
(** Wrapper for [Unix.gethostbyname] *)
|
|
|
|
val gethostbyaddr : inet_addr -> host_entry Lwt.t
|
|
(** Wrapper for [Unix.gethostbyaddr] *)
|
|
|
|
val getprotobyname : string -> protocol_entry Lwt.t
|
|
(** Wrapper for [Unix.getprotobyname] *)
|
|
|
|
val getprotobynumber : int -> protocol_entry Lwt.t
|
|
(** Wrapper for [Unix.getprotobynumber] *)
|
|
|
|
val getservbyname : string -> string -> service_entry Lwt.t
|
|
(** Wrapper for [Unix.getservbyname] *)
|
|
|
|
val getservbyport : int -> string -> service_entry Lwt.t
|
|
(** Wrapper for [Unix.getservbyport] *)
|
|
|
|
type addr_info =
|
|
Unix.addr_info =
|
|
{
|
|
ai_family : socket_domain;
|
|
ai_socktype : socket_type;
|
|
ai_protocol : int;
|
|
ai_addr : sockaddr;
|
|
ai_canonname : string;
|
|
}
|
|
|
|
type getaddrinfo_option =
|
|
Unix.getaddrinfo_option =
|
|
| AI_FAMILY of socket_domain
|
|
| AI_SOCKTYPE of socket_type
|
|
| AI_PROTOCOL of int
|
|
| AI_NUMERICHOST
|
|
| AI_CANONNAME
|
|
| AI_PASSIVE
|
|
|
|
val getaddrinfo : string -> string -> getaddrinfo_option list -> addr_info list Lwt.t
|
|
(** Wrapper for [Unix.getaddrinfo] *)
|
|
|
|
type name_info =
|
|
Unix.name_info =
|
|
{
|
|
ni_hostname : string;
|
|
ni_service : string;
|
|
}
|
|
|
|
type getnameinfo_option =
|
|
Unix.getnameinfo_option =
|
|
| NI_NOFQDN
|
|
| NI_NUMERICHOST
|
|
| NI_NAMEREQD
|
|
| NI_NUMERICSERV
|
|
| NI_DGRAM
|
|
|
|
val getnameinfo : sockaddr -> getnameinfo_option list -> name_info Lwt.t
|
|
(** Wrapper for [Unix.getnameinfo] *)
|
|
|
|
(** {6 Terminal interface} *)
|
|
|
|
type terminal_io =
|
|
Unix.terminal_io =
|
|
{
|
|
mutable c_ignbrk : bool;
|
|
mutable c_brkint : bool;
|
|
mutable c_ignpar : bool;
|
|
mutable c_parmrk : bool;
|
|
mutable c_inpck : bool;
|
|
mutable c_istrip : bool;
|
|
mutable c_inlcr : bool;
|
|
mutable c_igncr : bool;
|
|
mutable c_icrnl : bool;
|
|
mutable c_ixon : bool;
|
|
mutable c_ixoff : bool;
|
|
mutable c_opost : bool;
|
|
mutable c_obaud : int;
|
|
mutable c_ibaud : int;
|
|
mutable c_csize : int;
|
|
mutable c_cstopb : int;
|
|
mutable c_cread : bool;
|
|
mutable c_parenb : bool;
|
|
mutable c_parodd : bool;
|
|
mutable c_hupcl : bool;
|
|
mutable c_clocal : bool;
|
|
mutable c_isig : bool;
|
|
mutable c_icanon : bool;
|
|
mutable c_noflsh : bool;
|
|
mutable c_echo : bool;
|
|
mutable c_echoe : bool;
|
|
mutable c_echok : bool;
|
|
mutable c_echonl : bool;
|
|
mutable c_vintr : char;
|
|
mutable c_vquit : char;
|
|
mutable c_verase : char;
|
|
mutable c_vkill : char;
|
|
mutable c_veof : char;
|
|
mutable c_veol : char;
|
|
mutable c_vmin : int;
|
|
mutable c_vtime : int;
|
|
mutable c_vstart : char;
|
|
mutable c_vstop : char;
|
|
}
|
|
|
|
val tcgetattr : file_descr -> terminal_io Lwt.t
|
|
(** Wrapper for [Unix.tcgetattr] *)
|
|
|
|
type setattr_when =
|
|
Unix.setattr_when =
|
|
| TCSANOW
|
|
| TCSADRAIN
|
|
| TCSAFLUSH
|
|
|
|
val tcsetattr : file_descr -> setattr_when -> terminal_io -> unit Lwt.t
|
|
(** Wrapper for [Unix.tcsetattr] *)
|
|
|
|
val tcsendbreak : file_descr -> int -> unit Lwt.t
|
|
(** Wrapper for [Unix.tcsendbreak] *)
|
|
|
|
val tcdrain : file_descr -> unit Lwt.t
|
|
(** Wrapper for [Unix.tcdrain] *)
|
|
|
|
type flush_queue =
|
|
Unix.flush_queue =
|
|
| TCIFLUSH
|
|
| TCOFLUSH
|
|
| TCIOFLUSH
|
|
|
|
val tcflush : file_descr -> flush_queue -> unit Lwt.t
|
|
(** Wrapper for [Unix.tcflush] *)
|
|
|
|
type flow_action =
|
|
Unix.flow_action =
|
|
| TCOOFF
|
|
| TCOON
|
|
| TCIOFF
|
|
| TCION
|
|
|
|
val tcflow : file_descr -> flow_action -> unit Lwt.t
|
|
(** Wrapper for [Unix.tcflow] *)
|
|
|
|
(** {6 Low-level interaction} *)
|
|
|
|
exception Retry
|
|
(** If an action raises {!Retry}, it will be requeued until the {b
|
|
file descriptor} becomes readable/writable again. *)
|
|
|
|
exception Retry_read
|
|
(** If an action raises {!Retry_read}, it will be requeued until the
|
|
{b file descriptor} becomes readable. *)
|
|
|
|
exception Retry_write
|
|
(** If an action raises {!Retry_read}, it will be requeued until the
|
|
{b file descriptor} becomes writables. *)
|
|
|
|
type io_event = Read | Write
|
|
|
|
val wrap_syscall : io_event -> file_descr -> (unit -> 'a) -> 'a Lwt.t
|
|
(** [wrap_syscall set fd action] wrap an action on a {b file
|
|
descriptor}. It tries to execture action, and if it can not be
|
|
performed immediately without blocking, it is registered for
|
|
latter.
|
|
|
|
In the latter case, if the thread is canceled, [action] is
|
|
removed from [set]. *)
|
|
|
|
val check_descriptor : file_descr -> unit
|
|
(** [check_descriptor fd] raise an exception if [fd] is not in the
|
|
state {!Open} *)
|
|
|
|
val register_action : io_event -> file_descr -> (unit -> 'a) -> 'a Lwt.t
|
|
(** [register_action set fd action] registers [action] on [fd]. When
|
|
[fd] becomes [readable]/[writable] [action] is called.
|
|
|
|
Note:
|
|
|
|
- you must call [check_descriptor fd] before calling
|
|
[register_action]
|
|
|
|
- you should prefer using {!wrap_syscall}
|
|
*)
|
|
|
|
type 'a job
|
|
(** Type of jobs that run:
|
|
|
|
- on another thread if the current async method is [Async_thread]
|
|
- on the main thread if the current async method is [Async_none]. *)
|
|
|
|
val execute_job :
|
|
?async_method : async_method ->
|
|
job : 'a job ->
|
|
result : ('a job -> 'b) ->
|
|
free : ('a job -> unit) -> 'b Lwt.t
|
|
(** [execute_job ?async_method ~job ~get ~free] starts
|
|
[job] and wait for its termination.
|
|
|
|
[async_method] is how the job will be executed. It defaults to
|
|
the async method of the current thread. [result] is used to get
|
|
the result of the job, and [free] to free its associated
|
|
resources. *)
|
|
|
|
val cancel_jobs : unit -> unit
|
|
(** [cancel_jobs ()] make all pending jobs to fail with
|
|
{!Lwt.Canceled}. *)
|
|
|
|
val wait_for_jobs : unit -> unit Lwt.t
|
|
(** Wait for all pending jobs to terminate. *)
|
|
|
|
(** {6 Notifications} *)
|
|
|
|
(** Lwt internally use a pipe to send notification to the main
|
|
thread. The following functions allow to use this pipe. *)
|
|
|
|
val make_notification : ?once : bool -> (unit -> unit) -> int
|
|
(** [new_notifier ?once f] registers a new notifier. It returns the
|
|
id of the notifier. Each time a notification with this id is
|
|
received, [f] is called.
|
|
|
|
if [once] is specified, then the notification is stopped after
|
|
the first time it is received. It defaults to [false]. *)
|
|
|
|
val send_notification : int -> unit
|
|
(** [send_notification id] sends a notification.
|
|
|
|
This function is thread-safe. *)
|
|
|
|
val stop_notification : int -> unit
|
|
(** Stop the given notification. Note that you should not reuse the
|
|
id after the notification has been stopped, the result is
|
|
unspecified if you do so. *)
|
|
|
|
val set_notification : int -> (unit -> unit) -> unit
|
|
(** [set_notification id f] replace the function associated to the
|
|
notification by [f]. It raises [Not_found] if the given
|
|
notification is not found. *)
|
|
|
|
(** {6 System threads pool} *)
|
|
|
|
(** If the program is using the async method {!Async_detach} or
|
|
{!Async_switch}, Lwt will launch system threads to execute
|
|
blocking system calls asynchronously. *)
|
|
|
|
val pool_size : unit -> int
|
|
(** Maximum number of system threads that can be started. If this
|
|
limit is reached, jobs will be executed synchronously. *)
|
|
|
|
val set_pool_size : int -> unit
|
|
(** Change the size of the pool. *)
|
|
|
|
val thread_count : unit -> int
|
|
(** The number of system threads running (excluding this one). *)
|
|
|
|
val thread_waiting_count : unit -> int
|
|
(** The number threads waiting for a job. *)
|
|
|
|
(** {6 CPUs} *)
|
|
|
|
val get_cpu : unit -> int
|
|
(** [get_cpu ()] returns the number of the CPU the current thread is
|
|
running on. *)
|
|
|
|
val get_affinity : ?pid : int -> unit -> int list
|
|
(** [get_affinity ?pid ()] returns the list of CPUs the process with
|
|
pid [pid] is allowed to run on. If [pid] is not specified then
|
|
the affinity of the current process is returned. *)
|
|
|
|
val set_affinity : ?pid : int -> int list -> unit
|
|
(** [set_affinity ?pid cpus] sets the list of CPUs the given process
|
|
is allowed to run on. *)
|
|
|
|
(**/**)
|
|
|
|
val run : 'a Lwt.t -> 'a
|
|
(* Same as {!Lwt_main.run} *)
|
|
|
|
val has_wait4 : bool
|
|
(* Deprecated, use [Lwt_sys.have `wait4]. *)
|