summaryrefslogtreecommitdiff
path: root/static/netbsd/man3/libuv.3
diff options
context:
space:
mode:
authorJacob McDonnell <jacob@jacobmcdonnell.com>2026-04-25 19:55:15 -0400
committerJacob McDonnell <jacob@jacobmcdonnell.com>2026-04-25 19:55:15 -0400
commit253e67c8b3a72b3a4757fdbc5845297628db0a4a (patch)
treeadf53b66087aa30dfbf8bf391a1dadb044c3bf4d /static/netbsd/man3/libuv.3
parenta9157ce950dfe2fc30795d43b9d79b9d1bffc48b (diff)
docs: Added All NetBSD Manuals
Diffstat (limited to 'static/netbsd/man3/libuv.3')
-rw-r--r--static/netbsd/man3/libuv.310855
1 files changed, 10855 insertions, 0 deletions
diff --git a/static/netbsd/man3/libuv.3 b/static/netbsd/man3/libuv.3
new file mode 100644
index 00000000..811c5acc
--- /dev/null
+++ b/static/netbsd/man3/libuv.3
@@ -0,0 +1,10855 @@
+.\" Man page generated from reStructuredText.
+.
+.TH "LIBUV" "3" "May 24, 2020" "1.38.0" "libuv API documentation"
+.SH NAME
+libuv \- libuv documentation
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH OVERVIEW
+.sp
+libuv is a multi\-platform support library with a focus on asynchronous I/O. It
+was primarily developed for use by \fI\%Node.js\fP, but it\(aqs also used by \fI\%Luvit\fP,
+\fI\%Julia\fP, \fI\%pyuv\fP, and \fI\%others\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+In case you find errors in this documentation you can help by sending
+\fI\%pull requests\fP!
+.UNINDENT
+.UNINDENT
+.SH FEATURES
+.INDENT 0.0
+.IP \(bu 2
+Full\-featured event loop backed by epoll, kqueue, IOCP, event ports.
+.IP \(bu 2
+Asynchronous TCP and UDP sockets
+.IP \(bu 2
+Asynchronous DNS resolution
+.IP \(bu 2
+Asynchronous file and file system operations
+.IP \(bu 2
+File system events
+.IP \(bu 2
+ANSI escape code controlled TTY
+.IP \(bu 2
+IPC with socket sharing, using Unix domain sockets or named pipes (Windows)
+.IP \(bu 2
+Child processes
+.IP \(bu 2
+Thread pool
+.IP \(bu 2
+Signal handling
+.IP \(bu 2
+High resolution clock
+.IP \(bu 2
+Threading and synchronization primitives
+.UNINDENT
+.SH DOCUMENTATION
+.SS Design overview
+.sp
+libuv is cross\-platform support library which was originally written for \fI\%Node.js\fP\&. It\(aqs designed
+around the event\-driven asynchronous I/O model.
+.sp
+The library provides much more than a simple abstraction over different I/O polling mechanisms:
+\(aqhandles\(aq and \(aqstreams\(aq provide a high level abstraction for sockets and other entities;
+cross\-platform file I/O and threading functionality is also provided, amongst other things.
+.sp
+Here is a diagram illustrating the different parts that compose libuv and what subsystem they
+relate to:
+[image]
+.SS Handles and requests
+.sp
+libuv provides users with 2 abstractions to work with, in combination with the event loop:
+handles and requests.
+.sp
+Handles represent long\-lived objects capable of performing certain operations while active. Some examples:
+.INDENT 0.0
+.IP \(bu 2
+A prepare handle gets its callback called once every loop iteration when active.
+.IP \(bu 2
+A TCP server handle that gets its connection callback called every time there is a new connection.
+.UNINDENT
+.sp
+Requests represent (typically) short\-lived operations. These operations can be performed over a
+handle: write requests are used to write data on a handle; or standalone: getaddrinfo requests
+don\(aqt need a handle they run directly on the loop.
+.SS The I/O loop
+.sp
+The I/O (or event) loop is the central part of libuv. It establishes the content for all I/O
+operations, and it\(aqs meant to be tied to a single thread. One can run multiple event loops
+as long as each runs in a different thread. The libuv event loop (or any other API involving
+the loop or handles, for that matter) \fBis not thread\-safe\fP except where stated otherwise.
+.sp
+The event loop follows the rather usual single threaded asynchronous I/O approach: all (network)
+I/O is performed on non\-blocking sockets which are polled using the best mechanism available
+on the given platform: epoll on Linux, kqueue on OSX and other BSDs, event ports on SunOS and IOCP
+on Windows. As part of a loop iteration the loop will block waiting for I/O activity on sockets
+which have been added to the poller and callbacks will be fired indicating socket conditions
+(readable, writable hangup) so handles can read, write or perform the desired I/O operation.
+.sp
+In order to better understand how the event loop operates, the following diagram illustrates all
+stages of a loop iteration:
+[image]
+.INDENT 0.0
+.IP 1. 4
+The loop concept of \(aqnow\(aq is updated. The event loop caches the current time at the start of
+the event loop tick in order to reduce the number of time\-related system calls.
+.IP 2. 4
+If the loop is \fIalive\fP an iteration is started, otherwise the loop will exit immediately. So,
+when is a loop considered to be \fIalive\fP? If a loop has active and ref\(aqd handles, active
+requests or closing handles it\(aqs considered to be \fIalive\fP\&.
+.IP 3. 4
+Due timers are run. All active timers scheduled for a time before the loop\(aqs concept of \fInow\fP
+get their callbacks called.
+.IP 4. 4
+Pending callbacks are called. All I/O callbacks are called right after polling for I/O, for the
+most part. There are cases, however, in which calling such a callback is deferred for the next
+loop iteration. If the previous iteration deferred any I/O callback it will be run at this point.
+.IP 5. 4
+Idle handle callbacks are called. Despite the unfortunate name, idle handles are run on every
+loop iteration, if they are active.
+.IP 6. 4
+Prepare handle callbacks are called. Prepare handles get their callbacks called right before
+the loop will block for I/O.
+.IP 7. 4
+Poll timeout is calculated. Before blocking for I/O the loop calculates for how long it should
+block. These are the rules when calculating the timeout:
+.INDENT 4.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+If the loop was run with the \fBUV_RUN_NOWAIT\fP flag, the timeout is 0.
+.IP \(bu 2
+If the loop is going to be stopped (\fBuv_stop()\fP was called), the timeout is 0.
+.IP \(bu 2
+If there are no active handles or requests, the timeout is 0.
+.IP \(bu 2
+If there are any idle handles active, the timeout is 0.
+.IP \(bu 2
+If there are any handles pending to be closed, the timeout is 0.
+.IP \(bu 2
+If none of the above cases matches, the timeout of the closest timer is taken, or
+if there are no active timers, infinity.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.IP 8. 4
+The loop blocks for I/O. At this point the loop will block for I/O for the duration calculated
+in the previous step. All I/O related handles that were monitoring a given file descriptor
+for a read or write operation get their callbacks called at this point.
+.IP 9. 4
+Check handle callbacks are called. Check handles get their callbacks called right after the
+loop has blocked for I/O. Check handles are essentially the counterpart of prepare handles.
+.IP 10. 4
+Close callbacks are called. If a handle was closed by calling \fBuv_close()\fP it will
+get the close callback called.
+.IP 11. 4
+Special case in case the loop was run with \fBUV_RUN_ONCE\fP, as it implies forward progress.
+It\(aqs possible that no I/O callbacks were fired after blocking for I/O, but some time has passed
+so there might be timers which are due, those timers get their callbacks called.
+.IP 12. 4
+Iteration ends. If the loop was run with \fBUV_RUN_NOWAIT\fP or \fBUV_RUN_ONCE\fP modes the
+iteration ends and \fBuv_run()\fP will return. If the loop was run with \fBUV_RUN_DEFAULT\fP
+it will continue from the start if it\(aqs still \fIalive\fP, otherwise it will also end.
+.UNINDENT
+.sp
+\fBIMPORTANT:\fP
+.INDENT 0.0
+.INDENT 3.5
+libuv uses a thread pool to make asynchronous file I/O operations possible, but
+network I/O is \fBalways\fP performed in a single thread, each loop\(aqs thread.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+While the polling mechanism is different, libuv makes the execution model consistent
+across Unix systems and Windows.
+.UNINDENT
+.UNINDENT
+.SS File I/O
+.sp
+Unlike network I/O, there are no platform\-specific file I/O primitives libuv could rely on,
+so the current approach is to run blocking file I/O operations in a thread pool.
+.sp
+For a thorough explanation of the cross\-platform file I/O landscape, checkout
+\fI\%this post\fP\&.
+.sp
+libuv currently uses a global thread pool on which all loops can queue work. 3 types of
+operations are currently run on this pool:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+File system operations
+.IP \(bu 2
+DNS functions (getaddrinfo and getnameinfo)
+.IP \(bu 2
+User specified code via \fBuv_queue_work()\fP
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+See the threadpool section for more details, but keep in mind the thread pool size
+is quite limited.
+.UNINDENT
+.UNINDENT
+.SS API documentation
+.SS Error handling
+.sp
+In libuv errors are negative numbered constants. As a rule of thumb, whenever
+there is a status parameter, or an API functions returns an integer, a negative
+number will imply an error.
+.sp
+When a function which takes a callback returns an error, the callback will never
+be called.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Implementation detail: on Unix error codes are the negated \fIerrno\fP (or \fI\-errno\fP), while on
+Windows they are defined by libuv to arbitrary negative numbers.
+.UNINDENT
+.UNINDENT
+.SS Error constants
+.INDENT 0.0
+.TP
+.B UV_E2BIG
+argument list too long
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EACCES
+permission denied
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EADDRINUSE
+address already in use
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EADDRNOTAVAIL
+address not available
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAFNOSUPPORT
+address family not supported
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAGAIN
+resource temporarily unavailable
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_ADDRFAMILY
+address family not supported
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_AGAIN
+temporary failure
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_BADFLAGS
+bad ai_flags value
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_BADHINTS
+invalid value for hints
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_CANCELED
+request canceled
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_FAIL
+permanent failure
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_FAMILY
+ai_family not supported
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_MEMORY
+out of memory
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_NODATA
+no address
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_NONAME
+unknown node or service
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_OVERFLOW
+argument buffer overflow
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_PROTOCOL
+resolved protocol is unknown
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_SERVICE
+service not available for socket type
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EAI_SOCKTYPE
+socket type not supported
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EALREADY
+connection already in progress
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EBADF
+bad file descriptor
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EBUSY
+resource busy or locked
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ECANCELED
+operation canceled
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ECHARSET
+invalid Unicode character
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ECONNABORTED
+software caused connection abort
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ECONNREFUSED
+connection refused
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ECONNRESET
+connection reset by peer
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EDESTADDRREQ
+destination address required
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EEXIST
+file already exists
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EFAULT
+bad address in system call argument
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EFBIG
+file too large
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EHOSTUNREACH
+host is unreachable
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EINTR
+interrupted system call
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EINVAL
+invalid argument
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EIO
+i/o error
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EISCONN
+socket is already connected
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EISDIR
+illegal operation on a directory
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ELOOP
+too many symbolic links encountered
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EMFILE
+too many open files
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EMSGSIZE
+message too long
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENAMETOOLONG
+name too long
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENETDOWN
+network is down
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENETUNREACH
+network is unreachable
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENFILE
+file table overflow
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOBUFS
+no buffer space available
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENODEV
+no such device
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOENT
+no such file or directory
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOMEM
+not enough memory
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENONET
+machine is not on the network
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOPROTOOPT
+protocol not available
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOSPC
+no space left on device
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOSYS
+function not implemented
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOTCONN
+socket is not connected
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOTDIR
+not a directory
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOTEMPTY
+directory not empty
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOTSOCK
+socket operation on non\-socket
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENOTSUP
+operation not supported on socket
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EPERM
+operation not permitted
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EPIPE
+broken pipe
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EPROTO
+protocol error
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EPROTONOSUPPORT
+protocol not supported
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EPROTOTYPE
+protocol wrong type for socket
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ERANGE
+result too large
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EROFS
+read\-only file system
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ESHUTDOWN
+cannot send after transport endpoint shutdown
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ESPIPE
+invalid seek
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ESRCH
+no such process
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ETIMEDOUT
+connection timed out
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ETXTBSY
+text file is busy
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EXDEV
+cross\-device link not permitted
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_UNKNOWN
+unknown error
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EOF
+end of file
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_ENXIO
+no such device or address
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_EMLINK
+too many links
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B UV_ERRNO_MAP(iter_macro)
+Macro that expands to a series of invocations of \fIiter_macro\fP for
+each of the error constants above. \fIiter_macro\fP is invoked with two
+arguments: the name of the error constant without the \fIUV_\fP prefix,
+and the error message string literal.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B const char* uv_strerror(int\fI\ err\fP)
+Returns the error message for the given error code. Leaks a few bytes
+of memory when you call it with an unknown error code.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B char* uv_strerror_r(int\fI\ err\fP, char*\fI\ buf\fP, size_t\fI\ buflen\fP)
+Returns the error message for the given error code. The zero\-terminated
+message is stored in the user\-supplied buffer \fIbuf\fP of at most \fIbuflen\fP bytes.
+.sp
+New in version 1.22.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B const char* uv_err_name(int\fI\ err\fP)
+Returns the error name for the given error code. Leaks a few bytes
+of memory when you call it with an unknown error code.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B char* uv_err_name_r(int\fI\ err\fP, char*\fI\ buf\fP, size_t\fI\ buflen\fP)
+Returns the error name for the given error code. The zero\-terminated
+name is stored in the user\-supplied buffer \fIbuf\fP of at most \fIbuflen\fP bytes.
+.sp
+New in version 1.22.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_translate_sys_error(int\fI\ sys_errno\fP)
+Returns the libuv error code equivalent to the given platform dependent error
+code: POSIX error codes on Unix (the ones stored in \fIerrno\fP), and Win32 error
+codes on Windows (those returned by \fIGetLastError()\fP or \fIWSAGetLastError()\fP).
+.sp
+If \fIsys_errno\fP is already a libuv error, it is simply returned.
+.sp
+Changed in version 1.10.0: function declared public.
+
+.UNINDENT
+.SS Version\-checking macros and functions
+.sp
+Starting with version 1.0.0 libuv follows the \fI\%semantic versioning\fP
+scheme. This means that new APIs can be introduced throughout the lifetime of
+a major release. In this section you\(aqll find all macros and functions that
+will allow you to write or compile code conditionally, in order to work with
+multiple libuv versions.
+.SS Macros
+.INDENT 0.0
+.TP
+.B UV_VERSION_MAJOR
+libuv version\(aqs major number.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_VERSION_MINOR
+libuv version\(aqs minor number.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_VERSION_PATCH
+libuv version\(aqs patch number.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_VERSION_IS_RELEASE
+Set to 1 to indicate a release version of libuv, 0 for a development
+snapshot.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_VERSION_SUFFIX
+libuv version suffix. Certain development releases such as Release Candidates
+might have a suffix such as "rc".
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_VERSION_HEX
+Returns the libuv version packed into a single integer. 8 bits are used for
+each component, with the patch number stored in the 8 least significant
+bits. E.g. for libuv 1.2.3 this would be 0x010203.
+.sp
+New in version 1.7.0.
+
+.UNINDENT
+.SS Functions
+.INDENT 0.0
+.TP
+.B unsigned int uv_version(void)
+Returns \fI\%UV_VERSION_HEX\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B const char* uv_version_string(void)
+Returns the libuv version number as a string. For non\-release versions the
+version suffix is included.
+.UNINDENT
+.SS \fI\%uv_loop_t\fP \-\-\- Event loop
+.sp
+The event loop is the central part of libuv\(aqs functionality. It takes care
+of polling for i/o and scheduling callbacks to be run based on different sources
+of events.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_loop_t
+Loop data type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_run_mode
+Mode used to run the loop with \fI\%uv_run()\fP\&.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef enum {
+ UV_RUN_DEFAULT = 0,
+ UV_RUN_ONCE,
+ UV_RUN_NOWAIT
+} uv_run_mode;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_walk_cb)(uv_handle_t*\fI\ handle\fP, void*\fI\ arg\fP)
+Type definition for callback passed to \fI\%uv_walk()\fP\&.
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B void* uv_loop_t.data
+Space for user\-defined arbitrary data. libuv does not use and does not
+touch this field.
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_loop_init(uv_loop_t*\fI\ loop\fP)
+Initializes the given \fIuv_loop_t\fP structure.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_loop_configure(uv_loop_t*\fI\ loop\fP, uv_loop_option\fI\ option\fP, \&...)
+New in version 1.0.2.
+
+.sp
+Set additional loop options. You should normally call this before the
+first call to \fI\%uv_run()\fP unless mentioned otherwise.
+.sp
+Returns 0 on success or a UV_E* error code on failure. Be prepared to
+handle UV_ENOSYS; it means the loop option is not supported by the platform.
+.sp
+Supported options:
+.INDENT 7.0
+.IP \(bu 2
+UV_LOOP_BLOCK_SIGNAL: Block a signal when polling for new events. The
+second argument to \fI\%uv_loop_configure()\fP is the signal number.
+.sp
+This operation is currently only implemented for SIGPROF signals,
+to suppress unnecessary wakeups when using a sampling profiler.
+Requesting other signals will fail with UV_EINVAL.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_loop_close(uv_loop_t*\fI\ loop\fP)
+Releases all internal loop resources. Call this function only when the loop
+has finished executing and all open handles and requests have been closed,
+or it will return UV_EBUSY. After this function returns, the user can free
+the memory allocated for the loop.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_loop_t* uv_default_loop(void)
+Returns the initialized default loop. It may return NULL in case of
+allocation failure.
+.sp
+This function is just a convenient way for having a global loop throughout
+an application, the default loop is in no way different than the ones
+initialized with \fI\%uv_loop_init()\fP\&. As such, the default loop can (and
+should) be closed with \fI\%uv_loop_close()\fP so the resources associated
+with it are freed.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function is not thread safe.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_run(uv_loop_t*\fI\ loop\fP, uv_run_mode\fI\ mode\fP)
+This function runs the event loop. It will act differently depending on the
+specified mode:
+.INDENT 7.0
+.IP \(bu 2
+UV_RUN_DEFAULT: Runs the event loop until there are no more active and
+referenced handles or requests. Returns non\-zero if \fI\%uv_stop()\fP
+was called and there are still active handles or requests. Returns
+zero in all other cases.
+.IP \(bu 2
+UV_RUN_ONCE: Poll for i/o once. Note that this function blocks if
+there are no pending callbacks. Returns zero when done (no active handles
+or requests left), or non\-zero if more callbacks are expected (meaning
+you should run the event loop again sometime in the future).
+.IP \(bu 2
+UV_RUN_NOWAIT: Poll for i/o once but don\(aqt block if there are no
+pending callbacks. Returns zero if done (no active handles
+or requests left), or non\-zero if more callbacks are expected (meaning
+you should run the event loop again sometime in the future).
+.UNINDENT
+.sp
+\fI\%uv_run()\fP is not reentrant. It must not be called from a callback.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_loop_alive(const uv_loop_t*\fI\ loop\fP)
+Returns non\-zero if there are referenced active handles, active
+requests or closing handles in the loop.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_stop(uv_loop_t*\fI\ loop\fP)
+Stop the event loop, causing \fI\%uv_run()\fP to end as soon as
+possible. This will happen not sooner than the next loop iteration.
+If this function was called before blocking for i/o, the loop won\(aqt block
+for i/o on this iteration.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B size_t uv_loop_size(void)
+Returns the size of the \fIuv_loop_t\fP structure. Useful for FFI binding
+writers who don\(aqt want to know the structure layout.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_backend_fd(const uv_loop_t*\fI\ loop\fP)
+Get backend file descriptor. Only kqueue, epoll and event ports are
+supported.
+.sp
+This can be used in conjunction with \fIuv_run(loop, UV_RUN_NOWAIT)\fP to
+poll in one thread and run the event loop\(aqs callbacks in another see
+test/test\-embed.c for an example.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Embedding a kqueue fd in another kqueue pollset doesn\(aqt work on all platforms. It\(aqs not
+an error to add the fd but it never generates events.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_backend_timeout(const uv_loop_t*\fI\ loop\fP)
+Get the poll timeout. The return value is in milliseconds, or \-1 for no
+timeout.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uint64_t uv_now(const uv_loop_t*\fI\ loop\fP)
+Return the current timestamp in milliseconds. The timestamp is cached at
+the start of the event loop tick, see \fI\%uv_update_time()\fP for details
+and rationale.
+.sp
+The timestamp increases monotonically from some arbitrary point in time.
+Don\(aqt make assumptions about the starting point, you will only get
+disappointed.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Use \fBuv_hrtime()\fP if you need sub\-millisecond granularity.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_update_time(uv_loop_t*\fI\ loop\fP)
+Update the event loop\(aqs concept of "now". Libuv caches the current time
+at the start of the event loop tick in order to reduce the number of
+time\-related system calls.
+.sp
+You won\(aqt normally need to call this function unless you have callbacks
+that block the event loop for longer periods of time, where "longer" is
+somewhat subjective but probably on the order of a millisecond or more.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_walk(uv_loop_t*\fI\ loop\fP, uv_walk_cb\fI\ walk_cb\fP, void*\fI\ arg\fP)
+Walk the list of handles: \fIwalk_cb\fP will be executed with the given \fIarg\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_loop_fork(uv_loop_t*\fI\ loop\fP)
+New in version 1.12.0.
+
+.sp
+Reinitialize any kernel state necessary in the child process after
+a \fI\%fork(2)\fP system call.
+.sp
+Previously started watchers will continue to be started in the
+child process.
+.sp
+It is necessary to explicitly call this function on every event
+loop created in the parent process that you plan to continue to
+use in the child, including the default loop (even if you don\(aqt
+continue to use it in the parent). This function must be called
+before calling \fI\%uv_run()\fP or any other API function using
+the loop in the child. Failure to do so will result in undefined
+behaviour, possibly including duplicate events delivered to both
+parent and child or aborting the child process.
+.sp
+When possible, it is preferred to create a new loop in the child
+process instead of reusing a loop created in the parent. New loops
+created in the child process after the fork should not use this
+function.
+.sp
+This function is not implemented on Windows, where it returns \fBUV_ENOSYS\fP\&.
+.sp
+\fBCAUTION:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function is experimental. It may contain bugs, and is subject to
+change or removal. API and ABI stability is not guaranteed.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Mac OS X, if directory FS event handles were in use in the
+parent process \fIfor any event loop\fP, the child process will no
+longer be able to use the most efficient FSEvent
+implementation. Instead, uses of directory FS event handles in
+the child will fall back to the same implementation used for
+files and on other kqueue\-based systems.
+.UNINDENT
+.UNINDENT
+.sp
+\fBCAUTION:\fP
+.INDENT 7.0
+.INDENT 3.5
+On AIX and SunOS, FS event handles that were already started in
+the parent process at the time of forking will \fInot\fP deliver
+events in the child process; they must be closed and restarted.
+On all other platforms, they will continue to work normally
+without any further intervention.
+.UNINDENT
+.UNINDENT
+.sp
+\fBCAUTION:\fP
+.INDENT 7.0
+.INDENT 3.5
+Any previous value returned from \fI\%uv_backend_fd()\fP is now
+invalid. That function must be called again to determine the
+correct backend file descriptor.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_loop_get_data(const uv_loop_t*\fI\ loop\fP)
+Returns \fIloop\->data\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_loop_set_data(uv_loop_t*\fI\ loop\fP, void*\fI\ data\fP)
+Sets \fIloop\->data\fP to \fIdata\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.SS \fI\%uv_handle_t\fP \-\-\- Base handle
+.sp
+\fIuv_handle_t\fP is the base type for all libuv handle types.
+.sp
+Structures are aligned so that any libuv handle can be cast to \fIuv_handle_t\fP\&.
+All API functions defined here work with any handle type.
+.sp
+Libuv handles are not movable. Pointers to handle structures passed to
+functions must remain valid for the duration of the requested operation. Take
+care when using stack allocated handles.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_handle_t
+The base libuv handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_handle_type
+The kind of the libuv handle.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef enum {
+ UV_UNKNOWN_HANDLE = 0,
+ UV_ASYNC,
+ UV_CHECK,
+ UV_FS_EVENT,
+ UV_FS_POLL,
+ UV_HANDLE,
+ UV_IDLE,
+ UV_NAMED_PIPE,
+ UV_POLL,
+ UV_PREPARE,
+ UV_PROCESS,
+ UV_STREAM,
+ UV_TCP,
+ UV_TIMER,
+ UV_TTY,
+ UV_UDP,
+ UV_SIGNAL,
+ UV_FILE,
+ UV_HANDLE_TYPE_MAX
+} uv_handle_type;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_any_handle
+Union of all handle types.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_alloc_cb)(uv_handle_t*\fI\ handle\fP, size_t\fI\ suggested_size\fP, uv_buf_t*\fI\ buf\fP)
+Type definition for callback passed to \fBuv_read_start()\fP and
+\fBuv_udp_recv_start()\fP\&. The user must allocate memory and fill the supplied
+\fBuv_buf_t\fP structure. If NULL is assigned as the buffer\(aqs base or 0 as its length,
+a \fBUV_ENOBUFS\fP error will be triggered in the \fBuv_udp_recv_cb\fP or the
+\fBuv_read_cb\fP callback.
+.sp
+Each buffer is used only once and the user is responsible for freeing it in the
+\fBuv_udp_recv_cb\fP or the \fBuv_read_cb\fP callback.
+.sp
+A suggested size (65536 at the moment in most cases) is provided, but it\(aqs just an indication,
+not related in any way to the pending data to be read. The user is free to allocate the amount
+of memory they decide.
+.sp
+As an example, applications with custom allocation schemes such as using freelists, allocation
+pools or slab based allocators may decide to use a different size which matches the memory
+chunks they already have.
+.sp
+Example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+static void my_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
+ buf\->base = malloc(suggested_size);
+ buf\->len = suggested_size;
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_close_cb)(uv_handle_t*\fI\ handle\fP)
+Type definition for callback passed to \fI\%uv_close()\fP\&.
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B uv_loop_t* uv_handle_t.loop
+Pointer to the \fBuv_loop_t\fP the handle is running on. Readonly.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_handle_type uv_handle_t.type
+The \fI\%uv_handle_type\fP, indicating the type of the underlying handle. Readonly.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_handle_t.data
+Space for user\-defined arbitrary data. libuv does not use this field.
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B UV_HANDLE_TYPE_MAP(iter_macro)
+Macro that expands to a series of invocations of \fIiter_macro\fP for
+each of the handle types. \fIiter_macro\fP is invoked with two
+arguments: the name of the \fIuv_handle_type\fP element without the
+\fIUV_\fP prefix, and the name of the corresponding structure type
+without the \fIuv_\fP prefix and \fI_t\fP suffix.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_is_active(const uv_handle_t*\fI\ handle\fP)
+Returns non\-zero if the handle is active, zero if it\(aqs inactive. What
+"active" means depends on the type of handle:
+.INDENT 7.0
+.IP \(bu 2
+A uv_async_t handle is always active and cannot be deactivated, except
+by closing it with uv_close().
+.IP \(bu 2
+A uv_pipe_t, uv_tcp_t, uv_udp_t, etc. handle \- basically any handle that
+deals with i/o \- is active when it is doing something that involves i/o,
+like reading, writing, connecting, accepting new connections, etc.
+.IP \(bu 2
+A uv_check_t, uv_idle_t, uv_timer_t, etc. handle is active when it has
+been started with a call to uv_check_start(), uv_idle_start(), etc.
+.UNINDENT
+.sp
+Rule of thumb: if a handle of type \fIuv_foo_t\fP has a \fIuv_foo_start()\fP
+function, then it\(aqs active from the moment that function is called.
+Likewise, \fIuv_foo_stop()\fP deactivates the handle again.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_is_closing(const uv_handle_t*\fI\ handle\fP)
+Returns non\-zero if the handle is closing or closed, zero otherwise.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function should only be used between the initialization of the handle and the
+arrival of the close callback.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_close(uv_handle_t*\fI\ handle\fP, uv_close_cb\fI\ close_cb\fP)
+Request handle to be closed. \fIclose_cb\fP will be called asynchronously after
+this call. This MUST be called on each handle before memory is released.
+Moreover, the memory can only be released in \fIclose_cb\fP or after it has
+returned.
+.sp
+Handles that wrap file descriptors are closed immediately but
+\fIclose_cb\fP will still be deferred to the next iteration of the event loop.
+It gives you a chance to free up any resources associated with the handle.
+.sp
+In\-progress requests, like uv_connect_t or uv_write_t, are cancelled and
+have their callbacks called asynchronously with status=UV_ECANCELED.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_ref(uv_handle_t*\fI\ handle\fP)
+Reference the given handle. References are idempotent, that is, if a handle
+is already referenced calling this function again will have no effect.
+.sp
+See \fI\%Reference counting\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_unref(uv_handle_t*\fI\ handle\fP)
+Un\-reference the given handle. References are idempotent, that is, if a handle
+is not referenced calling this function again will have no effect.
+.sp
+See \fI\%Reference counting\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_has_ref(const uv_handle_t*\fI\ handle\fP)
+Returns non\-zero if the handle referenced, zero otherwise.
+.sp
+See \fI\%Reference counting\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B size_t uv_handle_size(uv_handle_type\fI\ type\fP)
+Returns the size of the given handle type. Useful for FFI binding writers
+who don\(aqt want to know the structure layout.
+.UNINDENT
+.SS Miscellaneous API functions
+.sp
+The following API functions take a \fI\%uv_handle_t\fP argument but they work
+just for some handle types.
+.INDENT 0.0
+.TP
+.B int uv_send_buffer_size(uv_handle_t*\fI\ handle\fP, int*\fI\ value\fP)
+Gets or sets the size of the send buffer that the operating
+system uses for the socket.
+.sp
+If \fI*value\fP == 0, then it will set \fI*value\fP to the current send buffer size.
+If \fI*value\fP > 0 then it will use \fI*value\fP to set the new send buffer size.
+.sp
+On success, zero is returned. On error, a negative result is
+returned.
+.sp
+This function works for TCP, pipe and UDP handles on Unix and for TCP and
+UDP handles on Windows.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Linux will set double the size and return double the size of the original set value.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_recv_buffer_size(uv_handle_t*\fI\ handle\fP, int*\fI\ value\fP)
+Gets or sets the size of the receive buffer that the operating
+system uses for the socket.
+.sp
+If \fI*value\fP == 0, then it will set \fI*value\fP to the current receive buffer size.
+If \fI*value\fP > 0 then it will use \fI*value\fP to set the new receive buffer size.
+.sp
+On success, zero is returned. On error, a negative result is
+returned.
+.sp
+This function works for TCP, pipe and UDP handles on Unix and for TCP and
+UDP handles on Windows.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Linux will set double the size and return double the size of the original set value.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fileno(const uv_handle_t*\fI\ handle\fP, uv_os_fd_t*\fI\ fd\fP)
+Gets the platform dependent file descriptor equivalent.
+.sp
+The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing
+any other handle type will fail with \fIUV_EINVAL\fP\&.
+.sp
+If a handle doesn\(aqt have an attached file descriptor yet or the handle
+itself has been closed, this function will return \fIUV_EBADF\fP\&.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+Be very careful when using this function. libuv assumes it\(aqs in control of the file
+descriptor so any change to it may lead to malfunction.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_loop_t* uv_handle_get_loop(const uv_handle_t*\fI\ handle\fP)
+Returns \fIhandle\->loop\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_handle_get_data(const uv_handle_t*\fI\ handle\fP)
+Returns \fIhandle\->data\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_handle_set_data(uv_handle_t*\fI\ handle\fP, void*\fI\ data\fP)
+Sets \fIhandle\->data\fP to \fIdata\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_handle_type uv_handle_get_type(const uv_handle_t*\fI\ handle\fP)
+Returns \fIhandle\->type\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B const char* uv_handle_type_name(uv_handle_type\fI\ type\fP)
+Returns the name for the equivalent struct for a given handle type,
+e.g. \fI"pipe"\fP (as in \fBuv_pipe_t\fP) for \fIUV_NAMED_PIPE\fP\&.
+.sp
+If no such handle type exists, this returns \fINULL\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.SS Reference counting
+.sp
+The libuv event loop (if run in the default mode) will run until there are no
+active \fIand\fP referenced handles left. The user can force the loop to exit early
+by unreferencing handles which are active, for example by calling \fI\%uv_unref()\fP
+after calling \fBuv_timer_start()\fP\&.
+.sp
+A handle can be referenced or unreferenced, the refcounting scheme doesn\(aqt use
+a counter, so both operations are idempotent.
+.sp
+All handles are referenced when active by default, see \fI\%uv_is_active()\fP
+for a more detailed explanation on what being \fIactive\fP involves.
+.SS \fI\%uv_req_t\fP \-\-\- Base request
+.sp
+\fIuv_req_t\fP is the base type for all libuv request types.
+.sp
+Structures are aligned so that any libuv request can be cast to \fIuv_req_t\fP\&.
+All API functions defined here work with any request type.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_req_t
+The base libuv request structure.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_any_req
+Union of all request types.
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B void* uv_req_t.data
+Space for user\-defined arbitrary data. libuv does not use this field.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_req_type uv_req_t.type
+Indicated the type of request. Readonly.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef enum {
+ UV_UNKNOWN_REQ = 0,
+ UV_REQ,
+ UV_CONNECT,
+ UV_WRITE,
+ UV_SHUTDOWN,
+ UV_UDP_SEND,
+ UV_FS,
+ UV_WORK,
+ UV_GETADDRINFO,
+ UV_GETNAMEINFO,
+ UV_REQ_TYPE_MAX,
+} uv_req_type;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B UV_REQ_TYPE_MAP(iter_macro)
+Macro that expands to a series of invocations of \fIiter_macro\fP for
+each of the request types. \fIiter_macro\fP is invoked with two
+arguments: the name of the \fIuv_req_type\fP element without the \fIUV_\fP
+prefix, and the name of the corresponding structure type without the
+\fIuv_\fP prefix and \fI_t\fP suffix.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_cancel(uv_req_t*\fI\ req\fP)
+Cancel a pending request. Fails if the request is executing or has finished
+executing.
+.sp
+Returns 0 on success, or an error code < 0 on failure.
+.sp
+Only cancellation of \fBuv_fs_t\fP, \fBuv_getaddrinfo_t\fP,
+\fBuv_getnameinfo_t\fP, \fBuv_random_t\fP and \fBuv_work_t\fP
+requests is currently supported.
+.sp
+Cancelled requests have their callbacks invoked some time in the future.
+It\(aqs \fBnot\fP safe to free the memory associated with the request until the
+callback is called.
+.sp
+Here is how cancellation is reported to the callback:
+.INDENT 7.0
+.IP \(bu 2
+A \fBuv_fs_t\fP request has its req\->result field set to \fIUV_ECANCELED\fP\&.
+.IP \(bu 2
+A \fBuv_work_t\fP, \fBuv_getaddrinfo_t\fP,
+\fBuv_getnameinfo_t\fP or \fBuv_random_t\fP request has its
+callback invoked with status == \fIUV_ECANCELED\fP\&.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B size_t uv_req_size(uv_req_type\fI\ type\fP)
+Returns the size of the given request type. Useful for FFI binding writers
+who don\(aqt want to know the structure layout.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_req_get_data(const uv_req_t*\fI\ req\fP)
+Returns \fIreq\->data\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_req_set_data(uv_req_t*\fI\ req\fP, void*\fI\ data\fP)
+Sets \fIreq\->data\fP to \fIdata\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_req_type uv_req_get_type(const uv_req_t*\fI\ req\fP)
+Returns \fIreq\->type\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B const char* uv_req_type_name(uv_req_type\fI\ type\fP)
+Returns the name for the equivalent struct for a given request type,
+e.g. \fI"connect"\fP (as in \fBuv_connect_t\fP) for \fIUV_CONNECT\fP\&.
+.sp
+If no such request type exists, this returns \fINULL\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.SS \fI\%uv_timer_t\fP \-\-\- Timer handle
+.sp
+Timer handles are used to schedule callbacks to be called in the future.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_timer_t
+Timer handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_timer_cb)(uv_timer_t*\fI\ handle\fP)
+Type definition for callback passed to \fI\%uv_timer_start()\fP\&.
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_timer_init(uv_loop_t*\fI\ loop\fP, uv_timer_t*\fI\ handle\fP)
+Initialize the handle.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_timer_start(uv_timer_t*\fI\ handle\fP, uv_timer_cb\fI\ cb\fP, uint64_t\fI\ timeout\fP, uint64_t\fI\ repeat\fP)
+Start the timer. \fItimeout\fP and \fIrepeat\fP are in milliseconds.
+.sp
+If \fItimeout\fP is zero, the callback fires on the next event loop iteration.
+If \fIrepeat\fP is non\-zero, the callback fires first after \fItimeout\fP
+milliseconds and then repeatedly after \fIrepeat\fP milliseconds.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Does not update the event loop\(aqs concept of "now". See \fBuv_update_time()\fP for more information.
+.sp
+If the timer is already active, it is simply updated.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_timer_stop(uv_timer_t*\fI\ handle\fP)
+Stop the timer, the callback will not be called anymore.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_timer_again(uv_timer_t*\fI\ handle\fP)
+Stop the timer, and if it is repeating restart it using the repeat value
+as the timeout. If the timer has never been started before it returns
+UV_EINVAL.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_timer_set_repeat(uv_timer_t*\fI\ handle\fP, uint64_t\fI\ repeat\fP)
+Set the repeat interval value in milliseconds. The timer will be scheduled
+to run on the given interval, regardless of the callback execution
+duration, and will follow normal timer semantics in the case of a
+time\-slice overrun.
+.sp
+For example, if a 50ms repeating timer first runs for 17ms, it will be
+scheduled to run again 33ms later. If other tasks consume more than the
+33ms following the first timer callback, then the callback will run as soon
+as possible.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+If the repeat value is set from a timer callback it does not immediately take effect.
+If the timer was non\-repeating before, it will have been stopped. If it was repeating,
+then the old repeat value will have been used to schedule the next timeout.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uint64_t uv_timer_get_repeat(const uv_timer_t*\fI\ handle\fP)
+Get the timer repeat value.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_prepare_t\fP \-\-\- Prepare handle
+.sp
+Prepare handles will run the given callback once per loop iteration, right
+before polling for i/o.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_prepare_t
+Prepare handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_prepare_cb)(uv_prepare_t*\fI\ handle\fP)
+Type definition for callback passed to \fI\%uv_prepare_start()\fP\&.
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_prepare_init(uv_loop_t*\fI\ loop\fP, uv_prepare_t*\fI\ prepare\fP)
+Initialize the handle. This function always succeeds.
+.INDENT 7.0
+.TP
+.B Returns
+0
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_prepare_start(uv_prepare_t*\fI\ prepare\fP, uv_prepare_cb\fI\ cb\fP)
+Start the handle with the given callback. This function always succeeds,
+except when \fIcb\fP is \fINULL\fP\&.
+.INDENT 7.0
+.TP
+.B Returns
+0 on success, or \fIUV_EINVAL\fP when \fIcb == NULL\fP\&.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_prepare_stop(uv_prepare_t*\fI\ prepare\fP)
+Stop the handle, the callback will no longer be called.
+This function always succeeds.
+.INDENT 7.0
+.TP
+.B Returns
+0
+.UNINDENT
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_check_t\fP \-\-\- Check handle
+.sp
+Check handles will run the given callback once per loop iteration, right
+after polling for i/o.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_check_t
+Check handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_check_cb)(uv_check_t*\fI\ handle\fP)
+Type definition for callback passed to \fI\%uv_check_start()\fP\&.
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_check_init(uv_loop_t*\fI\ loop\fP, uv_check_t*\fI\ check\fP)
+Initialize the handle. This function always succeeds.
+.INDENT 7.0
+.TP
+.B Returns
+0
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_check_start(uv_check_t*\fI\ check\fP, uv_check_cb\fI\ cb\fP)
+Start the handle with the given callback. This function always succeeds,
+except when \fIcb\fP is \fINULL\fP\&.
+.INDENT 7.0
+.TP
+.B Returns
+0 on success, or \fIUV_EINVAL\fP when \fIcb == NULL\fP\&.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_check_stop(uv_check_t*\fI\ check\fP)
+Stop the handle, the callback will no longer be called.
+This function always succeeds.
+.INDENT 7.0
+.TP
+.B Returns
+0
+.UNINDENT
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_idle_t\fP \-\-\- Idle handle
+.sp
+Idle handles will run the given callback once per loop iteration, right
+before the \fBuv_prepare_t\fP handles.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The notable difference with prepare handles is that when there are active idle handles,
+the loop will perform a zero timeout poll instead of blocking for i/o.
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+Despite the name, idle handles will get their callbacks called on every loop iteration,
+not when the loop is actually "idle".
+.UNINDENT
+.UNINDENT
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_idle_t
+Idle handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_idle_cb)(uv_idle_t*\fI\ handle\fP)
+Type definition for callback passed to \fI\%uv_idle_start()\fP\&.
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_idle_init(uv_loop_t*\fI\ loop\fP, uv_idle_t*\fI\ idle\fP)
+Initialize the handle. This function always succeeds.
+.INDENT 7.0
+.TP
+.B Returns
+0
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_idle_start(uv_idle_t*\fI\ idle\fP, uv_idle_cb\fI\ cb\fP)
+Start the handle with the given callback. This function always succeeds,
+except when \fIcb\fP is \fINULL\fP\&.
+.INDENT 7.0
+.TP
+.B Returns
+0 on success, or \fIUV_EINVAL\fP when \fIcb == NULL\fP\&.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_idle_stop(uv_idle_t*\fI\ idle\fP)
+Stop the handle, the callback will no longer be called.
+This function always succeeds.
+.INDENT 7.0
+.TP
+.B Returns
+0
+.UNINDENT
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_async_t\fP \-\-\- Async handle
+.sp
+Async handles allow the user to "wakeup" the event loop and get a callback
+called from another thread.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_async_t
+Async handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_async_cb)(uv_async_t*\fI\ handle\fP)
+Type definition for callback passed to \fI\%uv_async_init()\fP\&.
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_async_init(uv_loop_t*\fI\ loop\fP, uv_async_t*\fI\ async\fP, uv_async_cb\fI\ async_cb\fP)
+Initialize the handle. A NULL callback is allowed.
+.INDENT 7.0
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Unlike other handle initialization functions, it immediately starts the handle.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_async_send(uv_async_t*\fI\ async\fP)
+Wake up the event loop and call the async handle\(aqs callback.
+.INDENT 7.0
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+It\(aqs safe to call this function from any thread. The callback will be called on the
+loop thread.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fI\%uv_async_send()\fP is \fI\%async\-signal\-safe\fP\&.
+It\(aqs safe to call this function from a signal handler.
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+libuv will coalesce calls to \fI\%uv_async_send()\fP, that is, not every call to it will
+yield an execution of the callback. For example: if \fI\%uv_async_send()\fP is called 5
+times in a row before the callback is called, the callback will only be called once. If
+\fI\%uv_async_send()\fP is called again after the callback was called, it will be called
+again.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_poll_t\fP \-\-\- Poll handle
+.sp
+Poll handles are used to watch file descriptors for readability,
+writability and disconnection similar to the purpose of \fI\%poll(2)\fP\&.
+.sp
+The purpose of poll handles is to enable integrating external libraries that
+rely on the event loop to signal it about the socket status changes, like
+c\-ares or libssh2. Using uv_poll_t for any other purpose is not recommended;
+\fBuv_tcp_t\fP, \fBuv_udp_t\fP, etc. provide an implementation that is faster and
+more scalable than what can be achieved with \fI\%uv_poll_t\fP, especially on
+Windows.
+.sp
+It is possible that poll handles occasionally signal that a file descriptor is
+readable or writable even when it isn\(aqt. The user should therefore always
+be prepared to handle EAGAIN or equivalent when it attempts to read from or
+write to the fd.
+.sp
+It is not okay to have multiple active poll handles for the same socket, this
+can cause libuv to busyloop or otherwise malfunction.
+.sp
+The user should not close a file descriptor while it is being polled by an
+active poll handle. This can cause the handle to report an error,
+but it might also start polling another socket. However the fd can be safely
+closed immediately after a call to \fI\%uv_poll_stop()\fP or \fBuv_close()\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+On windows only sockets can be polled with poll handles. On Unix any file
+descriptor that would be accepted by \fI\%poll(2)\fP can be used.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+On AIX, watching for disconnection is not supported.
+.UNINDENT
+.UNINDENT
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_poll_t
+Poll handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_poll_cb)(uv_poll_t*\fI\ handle\fP, int\fI\ status\fP, int\fI\ events\fP)
+Type definition for callback passed to \fI\%uv_poll_start()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_poll_event
+Poll event types
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+enum uv_poll_event {
+ UV_READABLE = 1,
+ UV_WRITABLE = 2,
+ UV_DISCONNECT = 4,
+ UV_PRIORITIZED = 8
+};
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_poll_init(uv_loop_t*\fI\ loop\fP, uv_poll_t*\fI\ handle\fP, int\fI\ fd\fP)
+Initialize the handle using a file descriptor.
+.sp
+Changed in version 1.2.2: the file descriptor is set to non\-blocking mode.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_poll_init_socket(uv_loop_t*\fI\ loop\fP, uv_poll_t*\fI\ handle\fP, uv_os_sock_t\fI\ socket\fP)
+Initialize the handle using a socket descriptor. On Unix this is identical
+to \fI\%uv_poll_init()\fP\&. On windows it takes a SOCKET handle.
+.sp
+Changed in version 1.2.2: the socket is set to non\-blocking mode.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_poll_start(uv_poll_t*\fI\ handle\fP, int\fI\ events\fP, uv_poll_cb\fI\ cb\fP)
+Starts polling the file descriptor. \fIevents\fP is a bitmask made up of
+UV_READABLE, UV_WRITABLE, UV_PRIORITIZED and UV_DISCONNECT. As soon as an
+event is detected the callback will be called with \fIstatus\fP set to 0, and the
+detected events set on the \fIevents\fP field.
+.sp
+The UV_PRIORITIZED event is used to watch for sysfs interrupts or TCP out\-of\-band
+messages.
+.sp
+The UV_DISCONNECT event is optional in the sense that it may not be
+reported and the user is free to ignore it, but it can help optimize the shutdown
+path because an extra read or write call might be avoided.
+.sp
+If an error happens while polling, \fIstatus\fP will be < 0 and corresponds
+with one of the UV_E* error codes (see errors). The user should
+not close the socket while the handle is active. If the user does that
+anyway, the callback \fImay\fP be called reporting an error status, but this
+is \fBnot\fP guaranteed.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Calling \fI\%uv_poll_start()\fP on a handle that is already active is fine. Doing so
+will update the events mask that is being watched for.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Though UV_DISCONNECT can be set, it is unsupported on AIX and as such will not be set
+on the \fIevents\fP field in the callback.
+.UNINDENT
+.UNINDENT
+.sp
+Changed in version 1.9.0: Added the UV_DISCONNECT event.
+
+.sp
+Changed in version 1.14.0: Added the UV_PRIORITIZED event.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_poll_stop(uv_poll_t*\fI\ poll\fP)
+Stop polling the file descriptor, the callback will no longer be called.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_signal_t\fP \-\-\- Signal handle
+.sp
+Signal handles implement Unix style signal handling on a per\-event loop bases.
+.SS Windows notes
+.sp
+Reception of some signals is emulated:
+.INDENT 0.0
+.IP \(bu 2
+SIGINT is normally delivered when the user presses CTRL+C. However, like
+on Unix, it is not generated when terminal raw mode is enabled.
+.IP \(bu 2
+SIGBREAK is delivered when the user pressed CTRL + BREAK.
+.IP \(bu 2
+SIGHUP is generated when the user closes the console window. On SIGHUP the
+program is given approximately 10 seconds to perform cleanup. After that
+Windows will unconditionally terminate it.
+.IP \(bu 2
+SIGWINCH is raised whenever libuv detects that the console has been
+resized. When a libuv app is running under a console emulator, or when a
+32\-bit libuv app is running on 64\-bit system, SIGWINCH will be emulated. In
+such cases SIGWINCH signals may not always be delivered in a timely manner.
+For a writable \fBuv_tty_t\fP handle libuv will only detect size changes
+when the cursor is moved. When a readable \fBuv_tty_t\fP handle is used,
+resizing of the console buffer will be detected only if the handle is in raw
+mode and is being read.
+.IP \(bu 2
+Watchers for other signals can be successfully created, but these signals
+are never received. These signals are: \fISIGILL\fP, \fISIGABRT\fP, \fISIGFPE\fP, \fISIGSEGV\fP,
+\fISIGTERM\fP and \fISIGKILL.\fP
+.IP \(bu 2
+Calls to raise() or abort() to programmatically raise a signal are
+not detected by libuv; these will not trigger a signal watcher.
+.UNINDENT
+.sp
+Changed in version 1.15.0: SIGWINCH support on Windows was improved.
+
+.sp
+Changed in version 1.31.0: 32\-bit libuv SIGWINCH support on 64\-bit Windows was
+rolled back to old implementation.
+
+.SS Unix notes
+.INDENT 0.0
+.IP \(bu 2
+SIGKILL and SIGSTOP are impossible to catch.
+.IP \(bu 2
+Handling SIGBUS, SIGFPE, SIGILL or SIGSEGV via libuv results into undefined behavior.
+.IP \(bu 2
+SIGABRT will not be caught by libuv if generated by \fIabort()\fP, e.g. through \fIassert()\fP\&.
+.IP \(bu 2
+On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads library to
+manage threads. Installing watchers for those signals will lead to unpredictable behavior
+and is strongly discouraged. Future versions of libuv may simply reject them.
+.UNINDENT
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_signal_t
+Signal handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_signal_cb)(uv_signal_t*\fI\ handle\fP, int\fI\ signum\fP)
+Type definition for callback passed to \fI\%uv_signal_start()\fP\&.
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B int uv_signal_t.signum
+Signal being monitored by this handle. Readonly.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_signal_init(uv_loop_t*\fI\ loop\fP, uv_signal_t*\fI\ signal\fP)
+Initialize the handle.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_signal_start(uv_signal_t*\fI\ signal\fP, uv_signal_cb\fI\ cb\fP, int\fI\ signum\fP)
+Start the handle with the given callback, watching for the given signal.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_signal_start_oneshot(uv_signal_t*\fI\ signal\fP, uv_signal_cb\fI\ cb\fP, int\fI\ signum\fP)
+New in version 1.12.0.
+
+.sp
+Same functionality as \fI\%uv_signal_start()\fP but the signal handler is reset the moment
+the signal is received.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_signal_stop(uv_signal_t*\fI\ signal\fP)
+Stop the handle, the callback will no longer be called.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_process_t\fP \-\-\- Process handle
+.sp
+Process handles will spawn a new process and allow the user to control it and
+establish communication channels with it using streams.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_process_t
+Process handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t
+Options for spawning the process (passed to \fI\%uv_spawn()\fP\&.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_process_options_s {
+ uv_exit_cb exit_cb;
+ const char* file;
+ char** args;
+ char** env;
+ const char* cwd;
+ unsigned int flags;
+ int stdio_count;
+ uv_stdio_container_t* stdio;
+ uv_uid_t uid;
+ uv_gid_t gid;
+} uv_process_options_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_exit_cb)(uv_process_t*, int64_t\fI\ exit_status\fP, int\fI\ term_signal\fP)
+Type definition for callback passed in \fI\%uv_process_options_t\fP which
+will indicate the exit status and the signal that caused the process to
+terminate, if any.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_flags
+Flags to be set on the flags field of \fI\%uv_process_options_t\fP\&.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+enum uv_process_flags {
+ /*
+ * Set the child process\(aq user id.
+ */
+ UV_PROCESS_SETUID = (1 << 0),
+ /*
+ * Set the child process\(aq group id.
+ */
+ UV_PROCESS_SETGID = (1 << 1),
+ /*
+ * Do not wrap any arguments in quotes, or perform any other escaping, when
+ * converting the argument list into a command line string. This option is
+ * only meaningful on Windows systems. On Unix it is silently ignored.
+ */
+ UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2),
+ /*
+ * Spawn the child process in a detached state \- this will make it a process
+ * group leader, and will effectively enable the child to keep running after
+ * the parent exits. Note that the child process will still keep the
+ * parent\(aqs event loop alive unless the parent process calls uv_unref() on
+ * the child\(aqs process handle.
+ */
+ UV_PROCESS_DETACHED = (1 << 3),
+ /*
+ * Hide the subprocess window that would normally be created. This option is
+ * only meaningful on Windows systems. On Unix it is silently ignored.
+ */
+ UV_PROCESS_WINDOWS_HIDE = (1 << 4),
+ /*
+ * Hide the subprocess console window that would normally be created. This
+ * option is only meaningful on Windows systems. On Unix it is silently
+ * ignored.
+ */
+ UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5),
+ /*
+ * Hide the subprocess GUI window that would normally be created. This
+ * option is only meaningful on Windows systems. On Unix it is silently
+ * ignored.
+ */
+ UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6)
+};
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stdio_container_t
+Container for each stdio handle or fd passed to a child process.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_stdio_container_s {
+ uv_stdio_flags flags;
+ union {
+ uv_stream_t* stream;
+ int fd;
+ } data;
+} uv_stdio_container_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stdio_flags
+Flags specifying how a stdio should be transmitted to the child process.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef enum {
+ UV_IGNORE = 0x00,
+ UV_CREATE_PIPE = 0x01,
+ UV_INHERIT_FD = 0x02,
+ UV_INHERIT_STREAM = 0x04,
+ /*
+ * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE
+ * determine the direction of flow, from the child process\(aq perspective. Both
+ * flags may be specified to create a duplex data stream.
+ */
+ UV_READABLE_PIPE = 0x10,
+ UV_WRITABLE_PIPE = 0x20
+ /*
+ * Open the child pipe handle in overlapped mode on Windows.
+ * On Unix it is silently ignored.
+ */
+ UV_OVERLAPPED_PIPE = 0x40
+} uv_stdio_flags;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B uv_process_t.pid
+The PID of the spawned process. It\(aqs set after calling \fI\%uv_spawn()\fP\&.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.exit_cb
+Callback called after the process exits.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.file
+Path pointing to the program to be executed.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.args
+Command line arguments. args[0] should be the path to the program. On
+Windows this uses \fICreateProcess\fP which concatenates the arguments into a
+string this can cause some strange errors. See the
+\fBUV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS\fP flag on \fI\%uv_process_flags\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.env
+Environment for the new process. If NULL the parents environment is used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.cwd
+Current working directory for the subprocess.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.flags
+Various flags that control how \fI\%uv_spawn()\fP behaves. See
+\fI\%uv_process_flags\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.stdio_count
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.stdio
+The \fIstdio\fP field points to an array of \fI\%uv_stdio_container_t\fP
+structs that describe the file descriptors that will be made available to
+the child process. The convention is that stdio[0] points to stdin,
+fd 1 is used for stdout, and fd 2 is stderr.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows file descriptors greater than 2 are available to the child process only if
+the child processes uses the MSVCRT runtime.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.uid
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_process_options_t.gid
+Libuv can change the child process\(aq user/group id. This happens only when
+the appropriate bits are set in the flags fields.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+This is not supported on Windows, \fI\%uv_spawn()\fP will fail and set the error
+to \fBUV_ENOTSUP\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stdio_container_t.flags
+Flags specifying how the stdio container should be passed to the child. See
+\fI\%uv_stdio_flags\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stdio_container_t.data
+Union containing either the stream or fd to be passed on to the child
+process.
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B void uv_disable_stdio_inheritance(void)
+Disables inheritance for file descriptors / handles that this process
+inherited from its parent. The effect is that child processes spawned by
+this process don\(aqt accidentally inherit these handles.
+.sp
+It is recommended to call this function as early in your program as possible,
+before the inherited file descriptors can be closed or duplicated.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function works on a best\-effort basis: there is no guarantee that libuv can discover
+all file descriptors that were inherited. In general it does a better job on Windows than
+it does on Unix.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_spawn(uv_loop_t*\fI\ loop\fP, uv_process_t*\fI\ handle\fP, const uv_process_options_t*\fI\ options\fP)
+Initializes the process handle and starts the process. If the process is
+successfully spawned, this function will return 0. Otherwise, the
+negative error code corresponding to the reason it couldn\(aqt spawn is
+returned.
+.sp
+Possible reasons for failing to spawn would include (but not be limited to)
+the file to execute not existing, not having permissions to use the setuid or
+setgid specified, or not having enough memory to allocate for the new
+process.
+.sp
+Changed in version 1.24.0: Added \fIUV_PROCESS_WINDOWS_HIDE_CONSOLE\fP and
+\fIUV_PROCESS_WINDOWS_HIDE_GUI\fP flags.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_process_kill(uv_process_t*\fI\ handle\fP, int\fI\ signum\fP)
+Sends the specified signal to the given process handle. Check the documentation
+on signal for signal support, specially on Windows.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_kill(int\fI\ pid\fP, int\fI\ signum\fP)
+Sends the specified signal to the given PID. Check the documentation
+on signal for signal support, specially on Windows.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_pid_t uv_process_get_pid(const uv_process_t*\fI\ handle\fP)
+Returns \fIhandle\->pid\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_stream_t\fP \-\-\- Stream handle
+.sp
+Stream handles provide an abstraction of a duplex communication channel.
+\fI\%uv_stream_t\fP is an abstract type, libuv provides 3 stream implementations
+in the form of \fBuv_tcp_t\fP, \fBuv_pipe_t\fP and \fBuv_tty_t\fP\&.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_stream_t
+Stream handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_connect_t
+Connect request type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_shutdown_t
+Shutdown request type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_write_t
+Write request type. Careful attention must be paid when reusing objects of
+this type. When a stream is in non\-blocking mode, write requests sent
+with \fBuv_write\fP will be queued. Reusing objects at this point is undefined
+behaviour. It is safe to reuse the \fBuv_write_t\fP object only after the
+callback passed to \fBuv_write\fP is fired.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_read_cb)(uv_stream_t*\fI\ stream\fP, ssize_t\fI\ nread\fP, const uv_buf_t*\fI\ buf\fP)
+Callback called when data was read on a stream.
+.sp
+\fInread\fP is > 0 if there is data available or < 0 on error. When we\(aqve
+reached EOF, \fInread\fP will be set to \fBUV_EOF\fP\&. When \fInread\fP < 0,
+the \fIbuf\fP parameter might not point to a valid buffer; in that case
+\fIbuf.len\fP and \fIbuf.base\fP are both set to 0.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fInread\fP might be 0, which does \fInot\fP indicate an error or EOF. This
+is equivalent to \fBEAGAIN\fP or \fBEWOULDBLOCK\fP under \fBread(2)\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+The callee is responsible for stopping/closing the stream when an error happens
+by calling \fI\%uv_read_stop()\fP or \fBuv_close()\fP\&. Trying to read
+from the stream again is undefined.
+.sp
+The callee is responsible for freeing the buffer, libuv does not reuse it.
+The buffer may be a null buffer (where \fIbuf\->base\fP == NULL and \fIbuf\->len\fP == 0)
+on error.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_write_cb)(uv_write_t*\fI\ req\fP, int\fI\ status\fP)
+Callback called after data was written on a stream. \fIstatus\fP will be 0 in
+case of success, < 0 otherwise.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_connect_cb)(uv_connect_t*\fI\ req\fP, int\fI\ status\fP)
+Callback called after a connection started by \fBuv_connect()\fP is done.
+\fIstatus\fP will be 0 in case of success, < 0 otherwise.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_shutdown_cb)(uv_shutdown_t*\fI\ req\fP, int\fI\ status\fP)
+Callback called after a shutdown request has been completed. \fIstatus\fP will
+be 0 in case of success, < 0 otherwise.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_connection_cb)(uv_stream_t*\fI\ server\fP, int\fI\ status\fP)
+Callback called when a stream server has received an incoming connection.
+The user can accept the connection by calling \fI\%uv_accept()\fP\&.
+\fIstatus\fP will be 0 in case of success, < 0 otherwise.
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B size_t uv_stream_t.write_queue_size
+Contains the amount of queued bytes waiting to be sent. Readonly.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stream_t* uv_connect_t.handle
+Pointer to the stream where this connection request is running.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stream_t* uv_shutdown_t.handle
+Pointer to the stream where this shutdown request is running.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stream_t* uv_write_t.handle
+Pointer to the stream where this write request is running.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stream_t* uv_write_t.send_handle
+Pointer to the stream being sent using this write request.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_shutdown(uv_shutdown_t*\fI\ req\fP, uv_stream_t*\fI\ handle\fP, uv_shutdown_cb\fI\ cb\fP)
+Shutdown the outgoing (write) side of a duplex stream. It waits for pending
+write requests to complete. The \fIhandle\fP should refer to a initialized stream.
+\fIreq\fP should be an uninitialized shutdown request struct. The \fIcb\fP is called
+after shutdown is complete.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_listen(uv_stream_t*\fI\ stream\fP, int\fI\ backlog\fP, uv_connection_cb\fI\ cb\fP)
+Start listening for incoming connections. \fIbacklog\fP indicates the number of
+connections the kernel might queue, same as \fI\%listen(2)\fP\&. When a new
+incoming connection is received the \fI\%uv_connection_cb\fP callback is
+called.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_accept(uv_stream_t*\fI\ server\fP, uv_stream_t*\fI\ client\fP)
+This call is used in conjunction with \fI\%uv_listen()\fP to accept incoming
+connections. Call this function after receiving a \fI\%uv_connection_cb\fP
+to accept the connection. Before calling this function the client handle must
+be initialized. < 0 return value indicates an error.
+.sp
+When the \fI\%uv_connection_cb\fP callback is called it is guaranteed that
+this function will complete successfully the first time. If you attempt to use
+it more than once, it may fail. It is suggested to only call this function once
+per \fI\%uv_connection_cb\fP call.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIserver\fP and \fIclient\fP must be handles running on the same loop.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_read_start(uv_stream_t*\fI\ stream\fP, uv_alloc_cb\fI\ alloc_cb\fP, uv_read_cb\fI\ read_cb\fP)
+Read data from an incoming stream. The \fI\%uv_read_cb\fP callback will
+be made several times until there is no more data to read or
+\fI\%uv_read_stop()\fP is called.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_read_stop(uv_stream_t*)
+Stop reading data from the stream. The \fI\%uv_read_cb\fP callback will
+no longer be called.
+.sp
+This function is idempotent and may be safely called on a stopped stream.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_write(uv_write_t*\fI\ req\fP, uv_stream_t*\fI\ handle\fP, const uv_buf_t\fI\ bufs[]\fP, unsigned int\fI\ nbufs\fP, uv_write_cb\fI\ cb\fP)
+Write data to stream. Buffers are written in order. Example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void cb(uv_write_t* req, int status) {
+ /* Logic which handles the write result */
+}
+
+uv_buf_t a[] = {
+ { .base = "1", .len = 1 },
+ { .base = "2", .len = 1 }
+};
+
+uv_buf_t b[] = {
+ { .base = "3", .len = 1 },
+ { .base = "4", .len = 1 }
+};
+
+uv_write_t req1;
+uv_write_t req2;
+
+/* writes "1234" */
+uv_write(&req1, stream, a, 2, cb);
+uv_write(&req2, stream, b, 2, cb);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+The memory pointed to by the buffers must remain valid until the callback gets called.
+This also holds for \fI\%uv_write2()\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_write2(uv_write_t*\fI\ req\fP, uv_stream_t*\fI\ handle\fP, const uv_buf_t\fI\ bufs[]\fP, unsigned int\fI\ nbufs\fP, uv_stream_t*\fI\ send_handle\fP, uv_write_cb\fI\ cb\fP)
+Extended write function for sending handles over a pipe. The pipe must be
+initialized with \fIipc\fP == 1.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIsend_handle\fP must be a TCP socket or pipe, which is a server or a connection (listening
+or connected state). Bound sockets or pipes will be assumed to be servers.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_try_write(uv_stream_t*\fI\ handle\fP, const uv_buf_t\fI\ bufs[]\fP, unsigned int\fI\ nbufs\fP)
+Same as \fI\%uv_write()\fP, but won\(aqt queue a write request if it can\(aqt be
+completed immediately.
+.sp
+Will return either:
+.INDENT 7.0
+.IP \(bu 2
+> 0: number of bytes written (can be less than the supplied buffer size).
+.IP \(bu 2
+< 0: negative error code (\fBUV_EAGAIN\fP is returned if no data can be sent
+immediately).
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_is_readable(const uv_stream_t*\fI\ handle\fP)
+Returns 1 if the stream is readable, 0 otherwise.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_is_writable(const uv_stream_t*\fI\ handle\fP)
+Returns 1 if the stream is writable, 0 otherwise.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_stream_set_blocking(uv_stream_t*\fI\ handle\fP, int\fI\ blocking\fP)
+Enable or disable blocking mode for a stream.
+.sp
+When blocking mode is enabled all writes complete synchronously. The
+interface remains unchanged otherwise, e.g. completion or failure of the
+operation will still be reported through a callback which is made
+asynchronously.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+Relying too much on this API is not recommended. It is likely to change
+significantly in the future.
+.sp
+Currently only works on Windows for \fBuv_pipe_t\fP handles.
+On UNIX platforms, all \fI\%uv_stream_t\fP handles are supported.
+.sp
+Also libuv currently makes no ordering guarantee when the blocking mode
+is changed after write requests have already been submitted. Therefore it is
+recommended to set the blocking mode immediately after opening or creating
+the stream.
+.UNINDENT
+.UNINDENT
+.sp
+Changed in version 1.4.0: UNIX implementation added.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B size_t uv_stream_get_write_queue_size(const uv_stream_t*\fI\ stream\fP)
+Returns \fIstream\->write_queue_size\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_tcp_t\fP \-\-\- TCP handle
+.sp
+TCP handles are used to represent both TCP streams and servers.
+.sp
+\fI\%uv_tcp_t\fP is a \(aqsubclass\(aq of \fBuv_stream_t\fP\&.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_tcp_t
+TCP handle type.
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_stream_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_tcp_init(uv_loop_t*\fI\ loop\fP, uv_tcp_t*\fI\ handle\fP)
+Initialize the handle. No socket is created as of yet.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_init_ex(uv_loop_t*\fI\ loop\fP, uv_tcp_t*\fI\ handle\fP, unsigned int\fI\ flags\fP)
+Initialize the handle with the specified flags. At the moment only the lower 8 bits
+of the \fIflags\fP parameter are used as the socket domain. A socket will be created
+for the given domain. If the specified domain is \fBAF_UNSPEC\fP no socket is created,
+just like \fI\%uv_tcp_init()\fP\&.
+.sp
+New in version 1.7.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_open(uv_tcp_t*\fI\ handle\fP, uv_os_sock_t\fI\ sock\fP)
+Open an existing file descriptor or SOCKET as a TCP handle.
+.sp
+Changed in version 1.2.1: the file descriptor is set to non\-blocking mode.
+
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+The passed file descriptor or SOCKET is not checked for its type, but
+it\(aqs required that it represents a valid stream socket.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_nodelay(uv_tcp_t*\fI\ handle\fP, int\fI\ enable\fP)
+Enable \fITCP_NODELAY\fP, which disables Nagle\(aqs algorithm.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_keepalive(uv_tcp_t*\fI\ handle\fP, int\fI\ enable\fP, unsigned int\fI\ delay\fP)
+Enable / disable TCP keep\-alive. \fIdelay\fP is the initial delay in seconds,
+ignored when \fIenable\fP is zero.
+.sp
+After \fIdelay\fP has been reached, 10 successive probes, each spaced 1 second
+from the previous one, will still happen. If the connection is still lost
+at the end of this procedure, then the handle is destroyed with a
+\fBUV_ETIMEDOUT\fP error passed to the corresponding callback.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_simultaneous_accepts(uv_tcp_t*\fI\ handle\fP, int\fI\ enable\fP)
+Enable / disable simultaneous asynchronous accept requests that are
+queued by the operating system when listening for new TCP connections.
+.sp
+This setting is used to tune a TCP server for the desired performance.
+Having simultaneous accepts can significantly improve the rate of accepting
+connections (which is why it is enabled by default) but may lead to uneven
+load distribution in multi\-process setups.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_bind(uv_tcp_t*\fI\ handle\fP, const struct sockaddr*\fI\ addr\fP, unsigned int\fI\ flags\fP)
+Bind the handle to an address and port. \fIaddr\fP should point to an
+initialized \fBstruct sockaddr_in\fP or \fBstruct sockaddr_in6\fP\&.
+.sp
+When the port is already taken, you can expect to see an \fBUV_EADDRINUSE\fP
+error from either \fI\%uv_tcp_bind()\fP, \fBuv_listen()\fP or
+\fI\%uv_tcp_connect()\fP\&. That is, a successful call to this function does
+not guarantee that the call to \fBuv_listen()\fP or \fI\%uv_tcp_connect()\fP
+will succeed as well.
+.sp
+\fIflags\fP can contain \fBUV_TCP_IPV6ONLY\fP, in which case dual\-stack support
+is disabled and only IPv6 is used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_getsockname(const uv_tcp_t*\fI\ handle\fP, struct sockaddr*\fI\ name\fP, int*\fI\ namelen\fP)
+Get the current address to which the handle is bound. \fIname\fP must point to
+a valid and big enough chunk of memory, \fBstruct sockaddr_storage\fP is
+recommended for IPv4 and IPv6 support.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_getpeername(const uv_tcp_t*\fI\ handle\fP, struct sockaddr*\fI\ name\fP, int*\fI\ namelen\fP)
+Get the address of the peer connected to the handle. \fIname\fP must point to
+a valid and big enough chunk of memory, \fBstruct sockaddr_storage\fP is
+recommended for IPv4 and IPv6 support.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_connect(uv_connect_t*\fI\ req\fP, uv_tcp_t*\fI\ handle\fP, const struct sockaddr*\fI\ addr\fP, uv_connect_cb\fI\ cb\fP)
+Establish an IPv4 or IPv6 TCP connection. Provide an initialized TCP handle
+and an uninitialized \fBuv_connect_t\fP\&. \fIaddr\fP should point to an
+initialized \fBstruct sockaddr_in\fP or \fBstruct sockaddr_in6\fP\&.
+.sp
+On Windows if the \fIaddr\fP is initialized to point to an unspecified address
+(\fB0.0.0.0\fP or \fB::\fP) it will be changed to point to \fBlocalhost\fP\&.
+This is done to match the behavior of Linux systems.
+.sp
+The callback is made when the connection has been established or when a
+connection error happened.
+.sp
+Changed in version 1.19.0: added \fB0.0.0.0\fP and \fB::\fP to \fBlocalhost\fP
+mapping
+
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_stream_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tcp_close_reset(uv_tcp_t*\fI\ handle\fP, uv_close_cb\fI\ close_cb\fP)
+Resets a TCP connection by sending a RST packet. This is accomplished by
+setting the \fISO_LINGER\fP socket option with a linger interval of zero and
+then calling \fBuv_close()\fP\&.
+Due to some platform inconsistencies, mixing of \fBuv_shutdown()\fP and
+\fI\%uv_tcp_close_reset()\fP calls is not allowed.
+.sp
+New in version 1.32.0.
+
+.UNINDENT
+.SS \fI\%uv_pipe_t\fP \-\-\- Pipe handle
+.sp
+Pipe handles provide an abstraction over streaming files on Unix (including
+local domain sockets, pipes, and FIFOs) and named pipes on Windows.
+.sp
+\fI\%uv_pipe_t\fP is a \(aqsubclass\(aq of \fBuv_stream_t\fP\&.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_pipe_t
+Pipe handle type.
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B int uv_pipe_t.ipc
+Whether this pipe is suitable for handle passing between processes.
+Only a connected pipe that will be passing the handles should have this flag
+set, not the listening pipe that uv_accept is called on.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_stream_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_pipe_init(uv_loop_t*\fI\ loop\fP, uv_pipe_t*\fI\ handle\fP, int\fI\ ipc\fP)
+Initialize a pipe handle. The \fIipc\fP argument is a boolean to indicate if
+this pipe will be used for handle passing between processes (which may
+change the bytes on the wire). Only a connected pipe that will be
+passing the handles should have this flag set, not the listening pipe
+that uv_accept is called on.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_pipe_open(uv_pipe_t*\fI\ handle\fP, uv_file\fI\ file\fP)
+Open an existing file descriptor or HANDLE as a pipe.
+.sp
+Changed in version 1.2.1: the file descriptor is set to non\-blocking mode.
+
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+The passed file descriptor or HANDLE is not checked for its type, but
+it\(aqs required that it represents a valid pipe.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_pipe_bind(uv_pipe_t*\fI\ handle\fP, const char*\fI\ name\fP)
+Bind the pipe to a file path (Unix) or a name (Windows).
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Paths on Unix get truncated to \fBsizeof(sockaddr_un.sun_path)\fP bytes, typically between
+92 and 108 bytes.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_pipe_connect(uv_connect_t*\fI\ req\fP, uv_pipe_t*\fI\ handle\fP, const char*\fI\ name\fP, uv_connect_cb\fI\ cb\fP)
+Connect to the Unix domain socket or the named pipe.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Paths on Unix get truncated to \fBsizeof(sockaddr_un.sun_path)\fP bytes, typically between
+92 and 108 bytes.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_pipe_getsockname(const uv_pipe_t*\fI\ handle\fP, char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Get the name of the Unix domain socket or the named pipe.
+.sp
+A preallocated buffer must be provided. The size parameter holds the length
+of the buffer and it\(aqs set to the number of bytes written to the buffer on
+output. If the buffer is not big enough \fBUV_ENOBUFS\fP will be returned and
+len will contain the required size.
+.sp
+Changed in version 1.3.0: the returned length no longer includes the terminating null byte,
+and the buffer is not null terminated.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_pipe_getpeername(const uv_pipe_t*\fI\ handle\fP, char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Get the name of the Unix domain socket or the named pipe to which the handle
+is connected.
+.sp
+A preallocated buffer must be provided. The size parameter holds the length
+of the buffer and it\(aqs set to the number of bytes written to the buffer on
+output. If the buffer is not big enough \fBUV_ENOBUFS\fP will be returned and
+len will contain the required size.
+.sp
+New in version 1.3.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_pipe_pending_instances(uv_pipe_t*\fI\ handle\fP, int\fI\ count\fP)
+Set the number of pending pipe instance handles when the pipe server is
+waiting for connections.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+This setting applies to Windows only.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_pipe_pending_count(uv_pipe_t*\fI\ handle\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_handle_type uv_pipe_pending_type(uv_pipe_t*\fI\ handle\fP)
+Used to receive handles over IPC pipes.
+.sp
+First \- call \fI\%uv_pipe_pending_count()\fP, if it\(aqs > 0 then initialize
+a handle of the given \fItype\fP, returned by \fI\%uv_pipe_pending_type()\fP
+and call \fBuv_accept(pipe, handle)\fP\&.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_stream_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_pipe_chmod(uv_pipe_t*\fI\ handle\fP, int\fI\ flags\fP)
+Alters pipe permissions, allowing it to be accessed from processes run by
+different users. Makes the pipe writable or readable by all users. Mode can
+be \fBUV_WRITABLE\fP, \fBUV_READABLE\fP or \fBUV_WRITABLE | UV_READABLE\fP\&. This
+function is blocking.
+.sp
+New in version 1.16.0.
+
+.UNINDENT
+.SS \fI\%uv_tty_t\fP \-\-\- TTY handle
+.sp
+TTY handles represent a stream for the console.
+.sp
+\fI\%uv_tty_t\fP is a \(aqsubclass\(aq of \fBuv_stream_t\fP\&.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_tty_t
+TTY handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_tty_mode_t
+New in version 1.2.0.
+
+.sp
+TTY mode type:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef enum {
+ /* Initial/normal terminal mode */
+ UV_TTY_MODE_NORMAL,
+ /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
+ UV_TTY_MODE_RAW,
+ /* Binary\-safe I/O mode for IPC (Unix\-only) */
+ UV_TTY_MODE_IO
+} uv_tty_mode_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_tty_vtermstate_t
+.TP
+.B Console virtual terminal mode type:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef enum {
+ /*
+ * The console supports handling of virtual terminal sequences
+ * (Windows10 new console, ConEmu)
+ */
+ UV_TTY_SUPPORTED,
+ /* The console cannot process virtual terminal sequences. (Legacy
+ * console)
+ */
+ UV_TTY_UNSUPPORTED
+} uv_tty_vtermstate_t
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_stream_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_tty_init(uv_loop_t*\fI\ loop\fP, uv_tty_t*\fI\ handle\fP, uv_file\fI\ fd\fP, int\fI\ unused\fP)
+Initialize a new TTY stream with the given file descriptor. Usually the
+file descriptor will be:
+.INDENT 7.0
+.IP \(bu 2
+0 = stdin
+.IP \(bu 2
+1 = stdout
+.IP \(bu 2
+2 = stderr
+.UNINDENT
+.sp
+On Unix this function will determine the path of the fd of the terminal
+using \fI\%ttyname_r(3)\fP, open it, and use it if the passed file descriptor
+refers to a TTY. This lets libuv put the tty in non\-blocking mode without
+affecting other processes that share the tty.
+.sp
+This function is not thread safe on systems that don\(aqt support
+ioctl TIOCGPTN or TIOCPTYGNAME, for instance OpenBSD and Solaris.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+If reopening the TTY fails, libuv falls back to blocking writes.
+.UNINDENT
+.UNINDENT
+.sp
+Changed in version 1.23.1:: the \fIreadable\fP parameter is now unused and ignored.
+The correct value will now be auto\-detected from the kernel.
+
+.sp
+Changed in version 1.9.0:: the path of the TTY is determined by
+\fI\%ttyname_r(3)\fP\&. In earlier versions libuv opened
+\fI/dev/tty\fP instead.
+
+.sp
+Changed in version 1.5.0:: trying to initialize a TTY stream with a file
+descriptor that refers to a file returns \fIUV_EINVAL\fP
+on UNIX.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tty_set_mode(uv_tty_t*\fI\ handle\fP, uv_tty_mode_t\fI\ mode\fP)
+Changed in version 1.2.0:: the mode is specified as a
+\fI\%uv_tty_mode_t\fP value.
+
+.sp
+Set the TTY using the specified terminal mode.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tty_reset_mode(void)
+To be called when the program exits. Resets TTY settings to default
+values for the next process to take over.
+.sp
+This function is async signal\-safe on Unix platforms but can fail with error
+code \fBUV_EBUSY\fP if you call it when execution is inside
+\fI\%uv_tty_set_mode()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tty_get_winsize(uv_tty_t*\fI\ handle\fP, int*\fI\ width\fP, int*\fI\ height\fP)
+Gets the current Window size. On success it returns 0.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_stream_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_tty_set_vterm_state(uv_tty_vtermstate_t\fI\ state\fP)
+Controls whether console virtual terminal sequences are processed by libuv
+or console.
+Useful in particular for enabling ConEmu support of ANSI X3.64 and Xterm
+256 colors. Otherwise Windows10 consoles are usually detected automatically.
+.sp
+This function is only meaningful on Windows systems. On Unix it is silently
+ignored.
+.sp
+New in version 1.33.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_tty_get_vterm_state(uv_tty_vtermstate_t*\fI\ state\fP)
+Get the current state of whether console virtual terminal sequences are
+handled by libuv or the console.
+.sp
+This function is not implemented on Unix, where it returns \fBUV_ENOTSUP\fP\&.
+.sp
+New in version 1.33.0.
+
+.UNINDENT
+.SS \fI\%uv_udp_t\fP \-\-\- UDP handle
+.sp
+UDP handles encapsulate UDP communication for both clients and servers.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_udp_t
+UDP handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_udp_send_t
+UDP send request type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_udp_flags
+Flags used in \fI\%uv_udp_bind()\fP and \fI\%uv_udp_recv_cb\fP\&..
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+enum uv_udp_flags {
+ /* Disables dual stack mode. */
+ UV_UDP_IPV6ONLY = 1,
+ /*
+ * Indicates message was truncated because read buffer was too small. The
+ * remainder was discarded by the OS. Used in uv_udp_recv_cb.
+ */
+ UV_UDP_PARTIAL = 2,
+ /*
+ * Indicates if SO_REUSEADDR will be set when binding the handle in
+ * uv_udp_bind.
+ * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
+ * Unix platforms, it sets the SO_REUSEADDR flag. What that means is that
+ * multiple threads or processes can bind to the same address without error
+ * (provided they all set the flag) but only the last one to bind will receive
+ * any traffic, in effect "stealing" the port from the previous listener.
+ */
+ UV_UDP_REUSEADDR = 4,
+ /*
+ * Indicates that the message was received by recvmmsg, so the buffer provided
+ * must not be freed by the recv_cb callback.
+ */
+ UV_UDP_MMSG_CHUNK = 8,
+ /*
+ * Indicates that recvmmsg should be used, if available.
+ */
+ UV_UDP_RECVMMSG = 256
+};
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_udp_send_cb)(uv_udp_send_t*\fI\ req\fP, int\fI\ status\fP)
+Type definition for callback passed to \fI\%uv_udp_send()\fP, which is
+called after the data was sent.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_udp_recv_cb)(uv_udp_t*\fI\ handle\fP, ssize_t\fI\ nread\fP, const uv_buf_t*\fI\ buf\fP, const struct sockaddr*\fI\ addr\fP, unsigned\fI\ flags\fP)
+Type definition for callback passed to \fI\%uv_udp_recv_start()\fP, which
+is called when the endpoint receives data.
+.INDENT 7.0
+.IP \(bu 2
+\fIhandle\fP: UDP handle
+.IP \(bu 2
+\fInread\fP: Number of bytes that have been received.
+0 if there is no more data to read. Note that 0 may also mean that an
+empty datagram was received (in this case \fIaddr\fP is not NULL). < 0 if
+a transmission error was detected.
+.IP \(bu 2
+\fIbuf\fP: \fBuv_buf_t\fP with the received data.
+.IP \(bu 2
+\fIaddr\fP: \fBstruct sockaddr*\fP containing the address of the sender.
+Can be NULL. Valid for the duration of the callback only.
+.IP \(bu 2
+\fIflags\fP: One or more or\(aqed UV_UDP_* constants.
+.UNINDENT
+.sp
+The callee is responsible for freeing the buffer, libuv does not reuse it.
+The buffer may be a null buffer (where \fIbuf\->base\fP == NULL and \fIbuf\->len\fP == 0)
+on error.
+.sp
+When using \fI\%recvmmsg(2)\fP, chunks will have the \fIUV_UDP_MMSG_CHUNK\fP flag set,
+those must not be freed. There will be a final callback with \fInread\fP set to 0,
+\fIaddr\fP set to NULL and the buffer pointing at the initially allocated data with
+the \fIUV_UDP_MMSG_CHUNK\fP flag cleared. This is a good chance for the callee to
+free the provided buffer.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+The receive callback will be called with \fInread\fP == 0 and \fIaddr\fP == NULL when there is
+nothing to read, and with \fInread\fP == 0 and \fIaddr\fP != NULL when an empty UDP packet is
+received.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_membership
+Membership type for a multicast address.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef enum {
+ UV_LEAVE_GROUP = 0,
+ UV_JOIN_GROUP
+} uv_membership;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B size_t uv_udp_t.send_queue_size
+Number of bytes queued for sending. This field strictly shows how much
+information is currently queued.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B size_t uv_udp_t.send_queue_count
+Number of send requests currently in the queue awaiting to be processed.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_udp_t* uv_udp_send_t.handle
+UDP handle where this send request is taking place.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_udp_init(uv_loop_t*\fI\ loop\fP, uv_udp_t*\fI\ handle\fP)
+Initialize a new UDP handle. The actual socket is created lazily.
+Returns 0 on success.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_init_ex(uv_loop_t*\fI\ loop\fP, uv_udp_t*\fI\ handle\fP, unsigned int\fI\ flags\fP)
+Initialize the handle with the specified flags. The lower 8 bits of the \fIflags\fP
+parameter are used as the socket domain. A socket will be created for the given domain.
+If the specified domain is \fBAF_UNSPEC\fP no socket is created, just like \fI\%uv_udp_init()\fP\&.
+.sp
+The remaining bits can be used to set one of these flags:
+.INDENT 7.0
+.IP \(bu 2
+\fIUV_UDP_RECVMMSG\fP: if set, and the platform supports it, \fI\%recvmmsg(2)\fP will
+be used.
+.UNINDENT
+.sp
+New in version 1.7.0.
+
+.sp
+Changed in version 1.37.0: added the \fIUV_UDP_RECVMMSG\fP flag.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_open(uv_udp_t*\fI\ handle\fP, uv_os_sock_t\fI\ sock\fP)
+Opens an existing file descriptor or Windows SOCKET as a UDP handle.
+.sp
+Unix only:
+The only requirement of the \fIsock\fP argument is that it follows the datagram
+contract (works in unconnected mode, supports sendmsg()/recvmsg(), etc).
+In other words, other datagram\-type sockets like raw sockets or netlink
+sockets can also be passed to this function.
+.sp
+Changed in version 1.2.1: the file descriptor is set to non\-blocking mode.
+
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+The passed file descriptor or SOCKET is not checked for its type, but
+it\(aqs required that it represents a valid datagram socket.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_bind(uv_udp_t*\fI\ handle\fP, const struct sockaddr*\fI\ addr\fP, unsigned int\fI\ flags\fP)
+Bind the UDP handle to an IP address and port.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBaddr\fP \-\- \fIstruct sockaddr_in\fP or \fIstruct sockaddr_in6\fP
+with the address and port to bind to.
+.IP \(bu 2
+\fBflags\fP \-\- Indicate how the socket will be bound,
+\fBUV_UDP_IPV6ONLY\fP and \fBUV_UDP_REUSEADDR\fP are supported.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_connect(uv_udp_t*\fI\ handle\fP, const struct sockaddr*\fI\ addr\fP)
+Associate the UDP handle to a remote address and port, so every
+message sent by this handle is automatically sent to that destination.
+Calling this function with a \fINULL\fP \fIaddr\fP disconnects the handle.
+Trying to call \fIuv_udp_connect()\fP on an already connected handle will result
+in an \fIUV_EISCONN\fP error. Trying to disconnect a handle that is not
+connected will return an \fIUV_ENOTCONN\fP error.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBaddr\fP \-\- \fIstruct sockaddr_in\fP or \fIstruct sockaddr_in6\fP
+with the address and port to associate to.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.sp
+New in version 1.27.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_getpeername(const uv_udp_t*\fI\ handle\fP, struct sockaddr*\fI\ name\fP, int*\fI\ namelen\fP)
+Get the remote IP and port of the UDP handle on connected UDP handles.
+On unconnected handles, it returns \fIUV_ENOTCONN\fP\&.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP and bound.
+.IP \(bu 2
+\fBname\fP \-\- Pointer to the structure to be filled with the address data.
+In order to support IPv4 and IPv6 \fIstruct sockaddr_storage\fP should be
+used.
+.IP \(bu 2
+\fBnamelen\fP \-\- On input it indicates the data of the \fIname\fP field. On
+output it indicates how much of it was filled.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure
+.UNINDENT
+.sp
+New in version 1.27.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_getsockname(const uv_udp_t*\fI\ handle\fP, struct sockaddr*\fI\ name\fP, int*\fI\ namelen\fP)
+Get the local IP and port of the UDP handle.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP and bound.
+.IP \(bu 2
+\fBname\fP \-\- Pointer to the structure to be filled with the address data.
+In order to support IPv4 and IPv6 \fIstruct sockaddr_storage\fP should be
+used.
+.IP \(bu 2
+\fBnamelen\fP \-\- On input it indicates the data of the \fIname\fP field. On
+output it indicates how much of it was filled.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_set_membership(uv_udp_t*\fI\ handle\fP, const char*\fI\ multicast_addr\fP, const char*\fI\ interface_addr\fP, uv_membership\fI\ membership\fP)
+Set membership for a multicast address
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBmulticast_addr\fP \-\- Multicast address to set membership for.
+.IP \(bu 2
+\fBinterface_addr\fP \-\- Interface address.
+.IP \(bu 2
+\fBmembership\fP \-\- Should be \fBUV_JOIN_GROUP\fP or \fBUV_LEAVE_GROUP\fP\&.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_set_source_membership(uv_udp_t*\fI\ handle\fP, const char*\fI\ multicast_addr\fP, const char*\fI\ interface_addr\fP, const char*\fI\ source_addr\fP, uv_membership\fI\ membership\fP)
+Set membership for a source\-specific multicast group.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBmulticast_addr\fP \-\- Multicast address to set membership for.
+.IP \(bu 2
+\fBinterface_addr\fP \-\- Interface address.
+.IP \(bu 2
+\fBsource_addr\fP \-\- Source address.
+.IP \(bu 2
+\fBmembership\fP \-\- Should be \fBUV_JOIN_GROUP\fP or \fBUV_LEAVE_GROUP\fP\&.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.sp
+New in version 1.32.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_set_multicast_loop(uv_udp_t*\fI\ handle\fP, int\fI\ on\fP)
+Set IP multicast loop flag. Makes multicast packets loop back to
+local sockets.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBon\fP \-\- 1 for on, 0 for off.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_set_multicast_ttl(uv_udp_t*\fI\ handle\fP, int\fI\ ttl\fP)
+Set the multicast ttl.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBttl\fP \-\- 1 through 255.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_set_multicast_interface(uv_udp_t*\fI\ handle\fP, const char*\fI\ interface_addr\fP)
+Set the multicast interface to send or receive data on.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBinterface_addr\fP \-\- interface address.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_set_broadcast(uv_udp_t*\fI\ handle\fP, int\fI\ on\fP)
+Set broadcast on or off.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBon\fP \-\- 1 for on, 0 for off.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_set_ttl(uv_udp_t*\fI\ handle\fP, int\fI\ ttl\fP)
+Set the time to live.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBttl\fP \-\- 1 through 255.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_send(uv_udp_send_t*\fI\ req\fP, uv_udp_t*\fI\ handle\fP, const uv_buf_t\fI\ bufs[]\fP, unsigned int\fI\ nbufs\fP, const struct sockaddr*\fI\ addr\fP, uv_udp_send_cb\fI\ send_cb\fP)
+Send data over the UDP socket. If the socket has not previously been bound
+with \fI\%uv_udp_bind()\fP it will be bound to 0.0.0.0
+(the "all interfaces" IPv4 address) and a random port number.
+.sp
+On Windows if the \fIaddr\fP is initialized to point to an unspecified address
+(\fB0.0.0.0\fP or \fB::\fP) it will be changed to point to \fBlocalhost\fP\&.
+This is done to match the behavior of Linux systems.
+.sp
+For connected UDP handles, \fIaddr\fP must be set to \fINULL\fP, otherwise it will
+return \fIUV_EISCONN\fP error.
+.sp
+For connectionless UDP handles, \fIaddr\fP cannot be \fINULL\fP, otherwise it will
+return \fIUV_EDESTADDRREQ\fP error.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBreq\fP \-\- UDP request handle. Need not be initialized.
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBbufs\fP \-\- List of buffers to send.
+.IP \(bu 2
+\fBnbufs\fP \-\- Number of buffers in \fIbufs\fP\&.
+.IP \(bu 2
+\fBaddr\fP \-\- \fIstruct sockaddr_in\fP or \fIstruct sockaddr_in6\fP with the
+address and port of the remote peer.
+.IP \(bu 2
+\fBsend_cb\fP \-\- Callback to invoke when the data has been sent out.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.sp
+Changed in version 1.19.0: added \fB0.0.0.0\fP and \fB::\fP to \fBlocalhost\fP
+mapping
+
+.sp
+Changed in version 1.27.0: added support for connected sockets
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_try_send(uv_udp_t*\fI\ handle\fP, const uv_buf_t\fI\ bufs[]\fP, unsigned int\fI\ nbufs\fP, const struct sockaddr*\fI\ addr\fP)
+Same as \fI\%uv_udp_send()\fP, but won\(aqt queue a send request if it can\(aqt
+be completed immediately.
+.sp
+For connected UDP handles, \fIaddr\fP must be set to \fINULL\fP, otherwise it will
+return \fIUV_EISCONN\fP error.
+.sp
+For connectionless UDP handles, \fIaddr\fP cannot be \fINULL\fP, otherwise it will
+return \fIUV_EDESTADDRREQ\fP error.
+.INDENT 7.0
+.TP
+.B Returns
+>= 0: number of bytes sent (it matches the given buffer size).
+< 0: negative error code (\fBUV_EAGAIN\fP is returned when the message
+can\(aqt be sent immediately).
+.UNINDENT
+.sp
+Changed in version 1.27.0: added support for connected sockets
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_recv_start(uv_udp_t*\fI\ handle\fP, uv_alloc_cb\fI\ alloc_cb\fP, uv_udp_recv_cb\fI\ recv_cb\fP)
+Prepare for receiving data. If the socket has not previously been bound
+with \fI\%uv_udp_bind()\fP it is bound to 0.0.0.0 (the "all interfaces"
+IPv4 address) and a random port number.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.IP \(bu 2
+\fBalloc_cb\fP \-\- Callback to invoke when temporary storage is needed.
+.IP \(bu 2
+\fBrecv_cb\fP \-\- Callback to invoke with received data.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.sp
+Changed in version 1.35.0: added support for \fI\%recvmmsg(2)\fP on supported platforms).
+The use of this feature requires a buffer larger than
+2 * 64KB to be passed to \fIalloc_cb\fP\&.
+
+.sp
+Changed in version 1.37.0: \fI\%recvmmsg(2)\fP support is no longer enabled implicitly,
+it must be explicitly requested by passing the \fIUV_UDP_RECVMMSG\fP flag to
+\fI\%uv_udp_init_ex()\fP\&.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_udp_recv_stop(uv_udp_t*\fI\ handle\fP)
+Stop listening for incoming datagrams.
+.INDENT 7.0
+.TP
+.B Parameters
+.INDENT 7.0
+.IP \(bu 2
+\fBhandle\fP \-\- UDP handle. Should have been initialized with
+\fI\%uv_udp_init()\fP\&.
+.UNINDENT
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B size_t uv_udp_get_send_queue_size(const uv_udp_t*\fI\ handle\fP)
+Returns \fIhandle\->send_queue_size\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B size_t uv_udp_get_send_queue_count(const uv_udp_t*\fI\ handle\fP)
+Returns \fIhandle\->send_queue_count\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_fs_event_t\fP \-\-\- FS Event handle
+.sp
+FS Event handles allow the user to monitor a given path for changes, for example,
+if the file was renamed or there was a generic change in it. This handle uses
+the best backend for the job on each platform.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+For AIX, the non default IBM bos.ahafs package has to be installed.
+The AIX Event Infrastructure file system (ahafs) has some limitations:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+ahafs tracks monitoring per process and is not thread safe. A separate process
+must be spawned for each monitor for the same event.
+.IP \(bu 2
+Events for file modification (writing to a file) are not received if only the
+containing folder is watched.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+See \fI\%documentation\fP for more details.
+.sp
+The z/OS file system events monitoring infrastructure does not notify of file
+creation/deletion within a directory that is being monitored.
+See the \fI\%IBM Knowledge centre\fP for more details.
+.UNINDENT
+.UNINDENT
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_fs_event_t
+FS Event handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_fs_event_cb)(uv_fs_event_t*\fI\ handle\fP, const char*\fI\ filename\fP, int\fI\ events\fP, int\fI\ status\fP)
+Callback passed to \fI\%uv_fs_event_start()\fP which will be called repeatedly
+after the handle is started. If the handle was started with a directory the
+\fIfilename\fP parameter will be a relative path to a file contained in the directory.
+The \fIevents\fP parameter is an ORed mask of \fI\%uv_fs_event\fP elements.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_fs_event
+Event types that \fI\%uv_fs_event_t\fP handles monitor.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+enum uv_fs_event {
+ UV_RENAME = 1,
+ UV_CHANGE = 2
+};
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_fs_event_flags
+Flags that can be passed to \fI\%uv_fs_event_start()\fP to control its
+behavior.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+enum uv_fs_event_flags {
+ /*
+ * By default, if the fs event watcher is given a directory name, we will
+ * watch for all events in that directory. This flags overrides this behavior
+ * and makes fs_event report only changes to the directory entry itself. This
+ * flag does not affect individual files watched.
+ * This flag is currently not implemented yet on any backend.
+ */
+ UV_FS_EVENT_WATCH_ENTRY = 1,
+ /*
+ * By default uv_fs_event will try to use a kernel interface such as inotify
+ * or kqueue to detect events. This may not work on remote file systems such
+ * as NFS mounts. This flag makes fs_event fall back to calling stat() on a
+ * regular interval.
+ * This flag is currently not implemented yet on any backend.
+ */
+ UV_FS_EVENT_STAT = 2,
+ /*
+ * By default, event watcher, when watching directory, is not registering
+ * (is ignoring) changes in its subdirectories.
+ * This flag will override this behaviour on platforms that support it.
+ */
+ UV_FS_EVENT_RECURSIVE = 4
+};
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_fs_event_init(uv_loop_t*\fI\ loop\fP, uv_fs_event_t*\fI\ handle\fP)
+Initialize the handle.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_event_start(uv_fs_event_t*\fI\ handle\fP, uv_fs_event_cb\fI\ cb\fP, const char*\fI\ path\fP, unsigned int\fI\ flags\fP)
+Start the handle with the given callback, which will watch the specified
+\fIpath\fP for changes. \fIflags\fP can be an ORed mask of \fI\%uv_fs_event_flags\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Currently the only supported flag is \fBUV_FS_EVENT_RECURSIVE\fP and
+only on OSX and Windows.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_event_stop(uv_fs_event_t*\fI\ handle\fP)
+Stop the handle, the callback will no longer be called.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_event_getpath(uv_fs_event_t*\fI\ handle\fP, char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Get the path being monitored by the handle. The buffer must be preallocated
+by the user. Returns 0 on success or an error code < 0 in case of failure.
+On success, \fIbuffer\fP will contain the path and \fIsize\fP its length. If the buffer
+is not big enough \fIUV_ENOBUFS\fP will be returned and \fIsize\fP will be set to
+the required size, including the null terminator.
+.sp
+Changed in version 1.3.0: the returned length no longer includes the terminating null byte,
+and the buffer is not null terminated.
+
+.sp
+Changed in version 1.9.0: the returned length includes the terminating null
+byte on \fIUV_ENOBUFS\fP, and the buffer is null terminated
+on success.
+
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS \fI\%uv_fs_poll_t\fP \-\-\- FS Poll handle
+.sp
+FS Poll handles allow the user to monitor a given path for changes. Unlike
+\fBuv_fs_event_t\fP, fs poll handles use \fIstat\fP to detect when a file has
+changed so they can work on file systems where fs event handles can\(aqt.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_fs_poll_t
+FS Poll handle type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_fs_poll_cb)(uv_fs_poll_t*\fI\ handle\fP, int\fI\ status\fP, const uv_stat_t*\fI\ prev\fP, const uv_stat_t*\fI\ curr\fP)
+Callback passed to \fI\%uv_fs_poll_start()\fP which will be called repeatedly
+after the handle is started, when any change happens to the monitored path.
+.sp
+The callback is invoked with \fIstatus < 0\fP if \fIpath\fP does not exist
+or is inaccessible. The watcher is \fInot\fP stopped but your callback is
+not called again until something changes (e.g. when the file is created
+or the error reason changes).
+.sp
+When \fIstatus == 0\fP, the callback receives pointers to the old and new
+\fBuv_stat_t\fP structs. They are valid for the duration of the
+callback only.
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_fs_poll_init(uv_loop_t*\fI\ loop\fP, uv_fs_poll_t*\fI\ handle\fP)
+Initialize the handle.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_poll_start(uv_fs_poll_t*\fI\ handle\fP, uv_fs_poll_cb\fI\ poll_cb\fP, const char*\fI\ path\fP, unsigned int\fI\ interval\fP)
+Check the file at \fIpath\fP for changes every \fIinterval\fP milliseconds.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+For maximum portability, use multi\-second intervals. Sub\-second intervals will not detect
+all changes on many file systems.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_poll_stop(uv_fs_poll_t*\fI\ handle\fP)
+Stop the handle, the callback will no longer be called.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_poll_getpath(uv_fs_poll_t*\fI\ handle\fP, char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Get the path being monitored by the handle. The buffer must be preallocated
+by the user. Returns 0 on success or an error code < 0 in case of failure.
+On success, \fIbuffer\fP will contain the path and \fIsize\fP its length. If the buffer
+is not big enough \fIUV_ENOBUFS\fP will be returned and \fIsize\fP will be set to
+the required size.
+.sp
+Changed in version 1.3.0: the returned length no longer includes the terminating null byte,
+and the buffer is not null terminated.
+
+.sp
+Changed in version 1.9.0: the returned length includes the terminating null
+byte on \fIUV_ENOBUFS\fP, and the buffer is null terminated
+on success.
+
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_handle_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS File system operations
+.sp
+libuv provides a wide variety of cross\-platform sync and async file system
+operations. All functions defined in this document take a callback, which is
+allowed to be NULL. If the callback is NULL the request is completed synchronously,
+otherwise it will be performed asynchronously.
+.sp
+All file operations are run on the threadpool. See threadpool for information
+on the threadpool size.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+On Windows \fIuv_fs_*\fP functions use utf\-8 encoding.
+.UNINDENT
+.UNINDENT
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_fs_t
+File system request type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_timespec_t
+Portable equivalent of \fBstruct timespec\fP\&.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct {
+ long tv_sec;
+ long tv_nsec;
+} uv_timespec_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stat_t
+Portable equivalent of \fBstruct stat\fP\&.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct {
+ uint64_t st_dev;
+ uint64_t st_mode;
+ uint64_t st_nlink;
+ uint64_t st_uid;
+ uint64_t st_gid;
+ uint64_t st_rdev;
+ uint64_t st_ino;
+ uint64_t st_size;
+ uint64_t st_blksize;
+ uint64_t st_blocks;
+ uint64_t st_flags;
+ uint64_t st_gen;
+ uv_timespec_t st_atim;
+ uv_timespec_t st_mtim;
+ uv_timespec_t st_ctim;
+ uv_timespec_t st_birthtim;
+} uv_stat_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_fs_type
+File system request type.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef enum {
+ UV_FS_UNKNOWN = \-1,
+ UV_FS_CUSTOM,
+ UV_FS_OPEN,
+ UV_FS_CLOSE,
+ UV_FS_READ,
+ UV_FS_WRITE,
+ UV_FS_SENDFILE,
+ UV_FS_STAT,
+ UV_FS_LSTAT,
+ UV_FS_FSTAT,
+ UV_FS_FTRUNCATE,
+ UV_FS_UTIME,
+ UV_FS_FUTIME,
+ UV_FS_ACCESS,
+ UV_FS_CHMOD,
+ UV_FS_FCHMOD,
+ UV_FS_FSYNC,
+ UV_FS_FDATASYNC,
+ UV_FS_UNLINK,
+ UV_FS_RMDIR,
+ UV_FS_MKDIR,
+ UV_FS_MKDTEMP,
+ UV_FS_RENAME,
+ UV_FS_SCANDIR,
+ UV_FS_LINK,
+ UV_FS_SYMLINK,
+ UV_FS_READLINK,
+ UV_FS_CHOWN,
+ UV_FS_FCHOWN,
+ UV_FS_REALPATH,
+ UV_FS_COPYFILE,
+ UV_FS_LCHOWN,
+ UV_FS_OPENDIR,
+ UV_FS_READDIR,
+ UV_FS_CLOSEDIR,
+ UV_FS_MKSTEMP,
+ UV_FS_LUTIME
+} uv_fs_type;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_statfs_t
+Reduced cross platform equivalent of \fBstruct statfs\fP\&.
+Used in \fI\%uv_fs_statfs()\fP\&.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_statfs_s {
+ uint64_t f_type;
+ uint64_t f_bsize;
+ uint64_t f_blocks;
+ uint64_t f_bfree;
+ uint64_t f_bavail;
+ uint64_t f_files;
+ uint64_t f_ffree;
+ uint64_t f_spare[4];
+} uv_statfs_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_dirent_t
+Cross platform (reduced) equivalent of \fBstruct dirent\fP\&.
+Used in \fI\%uv_fs_scandir_next()\fP\&.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef enum {
+ UV_DIRENT_UNKNOWN,
+ UV_DIRENT_FILE,
+ UV_DIRENT_DIR,
+ UV_DIRENT_LINK,
+ UV_DIRENT_FIFO,
+ UV_DIRENT_SOCKET,
+ UV_DIRENT_CHAR,
+ UV_DIRENT_BLOCK
+} uv_dirent_type_t;
+
+typedef struct uv_dirent_s {
+ const char* name;
+ uv_dirent_type_t type;
+} uv_dirent_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_dir_t
+Data type used for streaming directory iteration.
+Used by \fI\%uv_fs_opendir()\fP, \fI\%uv_fs_readdir()\fP, and
+\fI\%uv_fs_closedir()\fP\&. \fIdirents\fP represents a user provided array of
+\fIuv_dirent_t\(gas used to hold results. \(ganentries\fP is the user provided maximum
+array size of \fIdirents\fP\&.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_dir_s {
+ uv_dirent_t* dirents;
+ size_t nentries;
+} uv_dir_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B uv_loop_t* uv_fs_t.loop
+Loop that started this request and where completion will be reported.
+Readonly.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_fs_type uv_fs_t.fs_type
+FS request type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B const char* uv_fs_t.path
+Path affecting the request.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B ssize_t uv_fs_t.result
+Result of the request. < 0 means error, success otherwise. On requests such
+as \fI\%uv_fs_read()\fP or \fI\%uv_fs_write()\fP it indicates the amount of
+data that was read or written, respectively.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stat_t uv_fs_t.statbuf
+Stores the result of \fI\%uv_fs_stat()\fP and other stat requests.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_fs_t.ptr
+Stores the result of \fI\%uv_fs_readlink()\fP and
+\fI\%uv_fs_realpath()\fP and serves as an alias to \fIstatbuf\fP\&.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_req_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B void uv_fs_req_cleanup(uv_fs_t*\fI\ req\fP)
+Cleanup request. Must be called after a request is finished to deallocate
+any memory libuv might have allocated.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_close(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%close(2)\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_open(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, int\fI\ flags\fP, int\fI\ mode\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%open(2)\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows libuv uses \fICreateFileW\fP and thus the file is always opened
+in binary mode. Because of this the O_BINARY and O_TEXT flags are not
+supported.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_read(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, const uv_buf_t\fI\ bufs[]\fP, unsigned int\fI\ nbufs\fP, int64_t\fI\ offset\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%preadv(2)\fP\&.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows, under non\-MSVC environments (e.g. when GCC or Clang is used
+to build libuv), files opened using \fBUV_FS_O_FILEMAP\fP may cause a fatal
+crash if the memory mapped read operation fails.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_unlink(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%unlink(2)\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_write(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, const uv_buf_t\fI\ bufs[]\fP, unsigned int\fI\ nbufs\fP, int64_t\fI\ offset\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%pwritev(2)\fP\&.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows, under non\-MSVC environments (e.g. when GCC or Clang is used
+to build libuv), files opened using \fBUV_FS_O_FILEMAP\fP may cause a fatal
+crash if the memory mapped write operation fails.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_mkdir(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, int\fI\ mode\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%mkdir(2)\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fImode\fP is currently not implemented on Windows.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_mkdtemp(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ tpl\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%mkdtemp(3)\fP\&. The result can be found as a null terminated string at \fIreq\->path\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_mkstemp(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ tpl\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%mkstemp(3)\fP\&. The created file path can be found as a null terminated string at \fIreq\->path\fP\&.
+The file descriptor can be found as an integer at \fIreq\->result\fP\&.
+.sp
+New in version 1.34.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_rmdir(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%rmdir(2)\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_opendir(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_fs_cb\fI\ cb\fP)
+Opens \fIpath\fP as a directory stream. On success, a \fIuv_dir_t\fP is allocated
+and returned via \fIreq\->ptr\fP\&. This memory is not freed by
+\fIuv_fs_req_cleanup()\fP, although \fIreq\->ptr\fP is set to \fINULL\fP\&. The allocated
+memory must be freed by calling \fIuv_fs_closedir()\fP\&. On failure, no memory
+is allocated.
+.sp
+The contents of the directory can be iterated over by passing the resulting
+\fIuv_dir_t\fP to \fIuv_fs_readdir()\fP\&.
+.sp
+New in version 1.28.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_closedir(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_dir_t*\fI\ dir\fP, uv_fs_cb\fI\ cb\fP)
+Closes the directory stream represented by \fIdir\fP and frees the memory
+allocated by \fIuv_fs_opendir()\fP\&.
+.sp
+New in version 1.28.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_readdir(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_dir_t*\fI\ dir\fP, uv_fs_cb\fI\ cb\fP)
+Iterates over the directory stream, \fIdir\fP, returned by a successful
+\fIuv_fs_opendir()\fP call. Prior to invoking \fIuv_fs_readdir()\fP, the caller
+must set \fIdir\->dirents\fP and \fIdir\->nentries\fP, representing the array of
+\fI\%uv_dirent_t\fP elements used to hold the read directory entries and
+its size.
+.sp
+On success, the result is an integer >= 0 representing the number of entries
+read from the stream.
+.sp
+New in version 1.28.0.
+
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIuv_fs_readdir()\fP is not thread safe.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function does not return the "." and ".." entries.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On success this function allocates memory that must be freed using
+\fIuv_fs_req_cleanup()\fP\&. \fIuv_fs_req_cleanup()\fP must be called before
+closing the directory with \fIuv_fs_closedir()\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_scandir(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, int\fI\ flags\fP, uv_fs_cb\fI\ cb\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_scandir_next(uv_fs_t*\fI\ req\fP, uv_dirent_t*\fI\ ent\fP)
+Equivalent to \fI\%scandir(3)\fP, with a slightly different API. Once the callback
+for the request is called, the user can use \fI\%uv_fs_scandir_next()\fP to
+get \fIent\fP populated with the next directory entry data. When there are no
+more entries \fBUV_EOF\fP will be returned.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Unlike \fIscandir(3)\fP, this function does not return the "." and ".." entries.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Linux, getting the type of an entry is only supported by some file systems (btrfs, ext2,
+ext3 and ext4 at the time of this writing), check the \fI\%getdents(2)\fP man page.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_stat(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_fs_cb\fI\ cb\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_fstat(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, uv_fs_cb\fI\ cb\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_lstat(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%stat(2)\fP, \fI\%fstat(2)\fP and \fI\%lstat(2)\fP respectively.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_statfs(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%statfs(2)\fP\&. On success, a \fIuv_statfs_t\fP is allocated
+and returned via \fIreq\->ptr\fP\&. This memory is freed by \fIuv_fs_req_cleanup()\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Any fields in the resulting \fIuv_statfs_t\fP that are not supported by the
+underlying operating system are set to zero.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.31.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_rename(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, const char*\fI\ new_path\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%rename(2)\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_fsync(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%fsync(2)\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+For AIX, \fIuv_fs_fsync\fP returns \fIUV_EBADF\fP on file descriptors referencing
+non regular files.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_fdatasync(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%fdatasync(2)\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_ftruncate(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, int64_t\fI\ offset\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%ftruncate(2)\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_copyfile(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, const char*\fI\ new_path\fP, int\fI\ flags\fP, uv_fs_cb\fI\ cb\fP)
+Copies a file from \fIpath\fP to \fInew_path\fP\&. Supported \fIflags\fP are described below.
+.INDENT 7.0
+.IP \(bu 2
+\fIUV_FS_COPYFILE_EXCL\fP: If present, \fIuv_fs_copyfile()\fP will fail with
+\fIUV_EEXIST\fP if the destination path already exists. The default behavior
+is to overwrite the destination if it exists.
+.IP \(bu 2
+\fIUV_FS_COPYFILE_FICLONE\fP: If present, \fIuv_fs_copyfile()\fP will attempt to
+create a copy\-on\-write reflink. If the underlying platform does not
+support copy\-on\-write, or an error occurs while attempting to use
+copy\-on\-write, a fallback copy mechanism based on
+\fI\%uv_fs_sendfile()\fP is used.
+.IP \(bu 2
+\fIUV_FS_COPYFILE_FICLONE_FORCE\fP: If present, \fIuv_fs_copyfile()\fP will
+attempt to create a copy\-on\-write reflink. If the underlying platform does
+not support copy\-on\-write, or an error occurs while attempting to use
+copy\-on\-write, then an error is returned.
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+If the destination path is created, but an error occurs while copying
+the data, then the destination path is removed. There is a brief window
+of time between closing and removing the file where another process
+could access the file.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.14.0.
+
+.sp
+Changed in version 1.20.0: \fIUV_FS_COPYFILE_FICLONE\fP and
+\fIUV_FS_COPYFILE_FICLONE_FORCE\fP are supported.
+
+.sp
+Changed in version 1.33.0: If an error occurs while using
+\fIUV_FS_COPYFILE_FICLONE_FORCE\fP, that error is returned. Previously,
+all errors were mapped to \fIUV_ENOTSUP\fP\&.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_sendfile(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ out_fd\fP, uv_file\fI\ in_fd\fP, int64_t\fI\ in_offset\fP, size_t\fI\ length\fP, uv_fs_cb\fI\ cb\fP)
+Limited equivalent to \fI\%sendfile(2)\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_access(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, int\fI\ mode\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%access(2)\fP on Unix. Windows uses \fBGetFileAttributesW()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_chmod(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, int\fI\ mode\fP, uv_fs_cb\fI\ cb\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_fchmod(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, int\fI\ mode\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%chmod(2)\fP and \fI\%fchmod(2)\fP respectively.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_utime(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, double\fI\ atime\fP, double\fI\ mtime\fP, uv_fs_cb\fI\ cb\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_futime(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, double\fI\ atime\fP, double\fI\ mtime\fP, uv_fs_cb\fI\ cb\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_lutime(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, double\fI\ atime\fP, double\fI\ mtime\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%utime(2)\fP, \fI\%futimes(3)\fP and \fI\%lutimes(3)\fP respectively.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+z/OS: \fIuv_fs_lutime()\fP is not implemented for z/OS. It can still be called but will return
+\fBUV_ENOSYS\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+AIX: \fIuv_fs_futime()\fP and \fIuv_fs_lutime()\fP functions only work for AIX 7.1 and newer.
+They can still be called on older versions but will return \fBUV_ENOSYS\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+Changed in version 1.10.0: sub\-second precission is supported on Windows
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_link(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, const char*\fI\ new_path\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%link(2)\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_symlink(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, const char*\fI\ new_path\fP, int\fI\ flags\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%symlink(2)\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows the \fIflags\fP parameter can be specified to control how the symlink will
+be created:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+\fBUV_FS_SYMLINK_DIR\fP: indicates that \fIpath\fP points to a directory.
+.IP \(bu 2
+\fBUV_FS_SYMLINK_JUNCTION\fP: request that the symlink is created
+using junction points.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_readlink(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%readlink(2)\fP\&.
+The resulting string is stored in \fIreq\->ptr\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_realpath(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%realpath(3)\fP on Unix. Windows uses \fI\%GetFinalPathNameByHandle\fP\&.
+The resulting string is stored in \fIreq\->ptr\fP\&.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function has certain platform\-specific caveats that were discovered when used in Node.
+.INDENT 0.0
+.IP \(bu 2
+macOS and other BSDs: this function will fail with UV_ELOOP if more than 32 symlinks are
+found while resolving the given path. This limit is hardcoded and cannot be sidestepped.
+.IP \(bu 2
+Windows: while this function works in the common case, there are a number of corner cases
+where it doesn\(aqt:
+.INDENT 2.0
+.IP \(bu 2
+Paths in ramdisk volumes created by tools which sidestep the Volume Manager (such as ImDisk)
+cannot be resolved.
+.IP \(bu 2
+Inconsistent casing when using drive letters.
+.IP \(bu 2
+Resolved path bypasses subst\(aqd drives.
+.UNINDENT
+.UNINDENT
+.sp
+While this function can still be used, it\(aqs not recommended if scenarios such as the
+above need to be supported.
+.sp
+The background story and some more details on these issues can be checked
+\fI\%here\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function is not implemented on Windows XP and Windows Server 2003.
+On these systems, UV_ENOSYS is returned.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.8.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_chown(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_uid_t\fI\ uid\fP, uv_gid_t\fI\ gid\fP, uv_fs_cb\fI\ cb\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_fchown(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, uv_file\fI\ file\fP, uv_uid_t\fI\ uid\fP, uv_gid_t\fI\ gid\fP, uv_fs_cb\fI\ cb\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_lchown(uv_loop_t*\fI\ loop\fP, uv_fs_t*\fI\ req\fP, const char*\fI\ path\fP, uv_uid_t\fI\ uid\fP, uv_gid_t\fI\ gid\fP, uv_fs_cb\fI\ cb\fP)
+Equivalent to \fI\%chown(2)\fP, \fI\%fchown(2)\fP and \fI\%lchown(2)\fP respectively.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+These functions are not implemented on Windows.
+.UNINDENT
+.UNINDENT
+.sp
+Changed in version 1.21.0: implemented uv_fs_lchown
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_fs_type uv_fs_get_type(const uv_fs_t*\fI\ req\fP)
+Returns \fIreq\->fs_type\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B ssize_t uv_fs_get_result(const uv_fs_t*\fI\ req\fP)
+Returns \fIreq\->result\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_fs_get_system_error(const uv_fs_t*\fI\ req\fP)
+Returns the platform specific error code \- \fIGetLastError()\fP value on Windows
+and \fI\-(req\->result)\fP on other platforms.
+.sp
+New in version 1.38.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_fs_get_ptr(const uv_fs_t*\fI\ req\fP)
+Returns \fIreq\->ptr\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B const char* uv_fs_get_path(const uv_fs_t*\fI\ req\fP)
+Returns \fIreq\->path\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_stat_t* uv_fs_get_statbuf(uv_fs_t*\fI\ req\fP)
+Returns \fI&req\->statbuf\fP\&.
+.sp
+New in version 1.19.0.
+
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_req_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS Helper functions
+.INDENT 0.0
+.TP
+.B uv_os_fd_t uv_get_osfhandle(int\fI\ fd\fP)
+For a file descriptor in the C runtime, get the OS\-dependent handle.
+On UNIX, returns the \fBfd\fP intact. On Windows, this calls \fI\%_get_osfhandle\fP\&.
+Note that the return value is still owned by the C runtime,
+any attempts to close it or to use it after closing the fd may lead to malfunction.
+.INDENT 7.0
+.INDENT 3.5
+New in version 1.12.0.
+
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_open_osfhandle(uv_os_fd_t\fI\ os_fd\fP)
+For a OS\-dependent handle, get the file descriptor in the C runtime.
+On UNIX, returns the \fBos_fd\fP intact. On Windows, this calls \fI\%_open_osfhandle\fP\&.
+Note that the return value is still owned by the CRT,
+any attempts to close it or to use it after closing the handle may lead to malfunction.
+.INDENT 7.0
+.INDENT 3.5
+New in version 1.23.0.
+
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS File open constants
+.INDENT 0.0
+.TP
+.B UV_FS_O_APPEND
+The file is opened in append mode. Before each write, the file offset is
+positioned at the end of the file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_CREAT
+The file is created if it does not already exist.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_DIRECT
+File I/O is done directly to and from user\-space buffers, which must be
+aligned. Buffer size and address should be a multiple of the physical sector
+size of the block device.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_DIRECT\fP is supported on Linux, and on Windows via
+\fI\%FILE_FLAG_NO_BUFFERING\fP\&.
+\fIUV_FS_O_DIRECT\fP is not supported on macOS.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_DIRECTORY
+If the path is not a directory, fail the open.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_DIRECTORY\fP is not supported on Windows.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_DSYNC
+The file is opened for synchronous I/O. Write operations will complete once
+all data and a minimum of metadata are flushed to disk.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_DSYNC\fP is supported on Windows via
+\fI\%FILE_FLAG_WRITE_THROUGH\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_EXCL
+If the \fIO_CREAT\fP flag is set and the file already exists, fail the open.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+In general, the behavior of \fIO_EXCL\fP is undefined if it is used without
+\fIO_CREAT\fP\&. There is one exception: on Linux 2.6 and later, \fIO_EXCL\fP can
+be used without \fIO_CREAT\fP if pathname refers to a block device. If the
+block device is in use by the system (e.g., mounted), the open will fail
+with the error \fIEBUSY\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_EXLOCK
+Atomically obtain an exclusive lock.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_EXLOCK\fP is only supported on macOS and Windows.
+.UNINDENT
+.UNINDENT
+.sp
+Changed in version 1.17.0: support is added for Windows.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_FILEMAP
+Use a memory file mapping to access the file. When using this flag, the
+file cannot be open multiple times concurrently.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_FILEMAP\fP is only supported on Windows.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_NOATIME
+Do not update the file access time when the file is read.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_NOATIME\fP is not supported on Windows.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_NOCTTY
+If the path identifies a terminal device, opening the path will not cause
+that terminal to become the controlling terminal for the process (if the
+process does not already have one).
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_NOCTTY\fP is not supported on Windows.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_NOFOLLOW
+If the path is a symbolic link, fail the open.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_NOFOLLOW\fP is not supported on Windows.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_NONBLOCK
+Open the file in nonblocking mode if possible.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_NONBLOCK\fP is not supported on Windows.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_RANDOM
+Access is intended to be random. The system can use this as a hint to
+optimize file caching.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_RANDOM\fP is only supported on Windows via
+\fI\%FILE_FLAG_RANDOM_ACCESS\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_RDONLY
+Open the file for read\-only access.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_RDWR
+Open the file for read\-write access.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_SEQUENTIAL
+Access is intended to be sequential from beginning to end. The system can
+use this as a hint to optimize file caching.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_SEQUENTIAL\fP is only supported on Windows via
+\fI\%FILE_FLAG_SEQUENTIAL_SCAN\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_SHORT_LIVED
+The file is temporary and should not be flushed to disk if possible.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_SHORT_LIVED\fP is only supported on Windows via
+\fI\%FILE_ATTRIBUTE_TEMPORARY\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_SYMLINK
+Open the symbolic link itself rather than the resource it points to.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_SYNC
+The file is opened for synchronous I/O. Write operations will complete once
+all data and all metadata are flushed to disk.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_SYNC\fP is supported on Windows via
+\fI\%FILE_FLAG_WRITE_THROUGH\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_TEMPORARY
+The file is temporary and should not be flushed to disk if possible.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIUV_FS_O_TEMPORARY\fP is only supported on Windows via
+\fI\%FILE_ATTRIBUTE_TEMPORARY\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_TRUNC
+If the file exists and is a regular file, and the file is opened
+successfully for write access, its length shall be truncated to zero.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_FS_O_WRONLY
+Open the file for write\-only access.
+.UNINDENT
+.SS Thread pool work scheduling
+.sp
+libuv provides a threadpool which can be used to run user code and get notified
+in the loop thread. This thread pool is internally used to run all file system
+operations, as well as getaddrinfo and getnameinfo requests.
+.sp
+Its default size is 4, but it can be changed at startup time by setting the
+\fBUV_THREADPOOL_SIZE\fP environment variable to any value (the absolute maximum
+is 1024).
+.sp
+Changed in version 1.30.0: the maximum UV_THREADPOOL_SIZE allowed was increased from 128 to 1024.
+
+.sp
+The threadpool is global and shared across all event loops. When a particular
+function makes use of the threadpool (i.e. when using \fI\%uv_queue_work()\fP)
+libuv preallocates and initializes the maximum number of threads allowed by
+\fBUV_THREADPOOL_SIZE\fP\&. This causes a relatively minor memory overhead
+(~1MB for 128 threads) but increases the performance of threading at runtime.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Note that even though a global thread pool which is shared across all events
+loops is used, the functions are not thread safe.
+.UNINDENT
+.UNINDENT
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_work_t
+Work request type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_work_cb)(uv_work_t*\fI\ req\fP)
+Callback passed to \fI\%uv_queue_work()\fP which will be run on the thread
+pool.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_after_work_cb)(uv_work_t*\fI\ req\fP, int\fI\ status\fP)
+Callback passed to \fI\%uv_queue_work()\fP which will be called on the loop
+thread after the work on the threadpool has been completed. If the work
+was cancelled using \fBuv_cancel()\fP \fIstatus\fP will be \fBUV_ECANCELED\fP\&.
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B uv_loop_t* uv_work_t.loop
+Loop that started this request and where completion will be reported.
+Readonly.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_req_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_queue_work(uv_loop_t*\fI\ loop\fP, uv_work_t*\fI\ req\fP, uv_work_cb\fI\ work_cb\fP, uv_after_work_cb\fI\ after_work_cb\fP)
+Initializes a work request which will run the given \fIwork_cb\fP in a thread
+from the threadpool. Once \fIwork_cb\fP is completed, \fIafter_work_cb\fP will be
+called on the loop thread.
+.sp
+This request can be cancelled with \fBuv_cancel()\fP\&.
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_req_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS DNS utility functions
+.sp
+libuv provides asynchronous variants of \fIgetaddrinfo\fP and \fIgetnameinfo\fP\&.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_getaddrinfo_t
+\fIgetaddrinfo\fP request type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t*\fI\ req\fP, int\fI\ status\fP, struct addrinfo*\fI\ res\fP)
+Callback which will be called with the getaddrinfo request result once
+complete. In case it was cancelled, \fIstatus\fP will have a value of
+\fBUV_ECANCELED\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_getnameinfo_t
+\fIgetnameinfo\fP request type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_getnameinfo_cb)(uv_getnameinfo_t*\fI\ req\fP, int\fI\ status\fP, const char*\fI\ hostname\fP, const char*\fI\ service\fP)
+Callback which will be called with the getnameinfo request result once
+complete. In case it was cancelled, \fIstatus\fP will have a value of
+\fBUV_ECANCELED\fP\&.
+.UNINDENT
+.SS Public members
+.INDENT 0.0
+.TP
+.B uv_loop_t* uv_getaddrinfo_t.loop
+Loop that started this getaddrinfo request and where completion will be
+reported. Readonly.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B struct addrinfo* uv_getaddrinfo_t.addrinfo
+Pointer to a \fIstruct addrinfo\fP containing the result. Must be freed by the user
+with \fI\%uv_freeaddrinfo()\fP\&.
+.sp
+Changed in version 1.3.0: the field is declared as public.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_loop_t* uv_getnameinfo_t.loop
+Loop that started this getnameinfo request and where completion will be
+reported. Readonly.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B char[NI_MAXHOST] uv_getnameinfo_t.host
+Char array containing the resulting host. It\(aqs null terminated.
+.sp
+Changed in version 1.3.0: the field is declared as public.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B char[NI_MAXSERV] uv_getnameinfo_t.service
+Char array containing the resulting service. It\(aqs null terminated.
+.sp
+Changed in version 1.3.0: the field is declared as public.
+
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_req_t\fP members also apply.
+.UNINDENT
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_getaddrinfo(uv_loop_t*\fI\ loop\fP, uv_getaddrinfo_t*\fI\ req\fP, uv_getaddrinfo_cb\fI\ getaddrinfo_cb\fP, const char*\fI\ node\fP, const char*\fI\ service\fP, const struct addrinfo*\fI\ hints\fP)
+Asynchronous \fI\%getaddrinfo(3)\fP\&.
+.sp
+Either node or service may be NULL but not both.
+.sp
+\fIhints\fP is a pointer to a struct addrinfo with additional address type
+constraints, or NULL. Consult \fIman \-s 3 getaddrinfo\fP for more details.
+.sp
+Returns 0 on success or an error code < 0 on failure. If successful, the
+callback will get called sometime in the future with the lookup result,
+which is either:
+.INDENT 7.0
+.IP \(bu 2
+status == 0, the res argument points to a valid \fIstruct addrinfo\fP, or
+.IP \(bu 2
+status < 0, the res argument is NULL. See the UV_EAI_* constants.
+.UNINDENT
+.sp
+Call \fI\%uv_freeaddrinfo()\fP to free the addrinfo structure.
+.sp
+Changed in version 1.3.0: the callback parameter is now allowed to be NULL,
+in which case the request will run \fBsynchronously\fP\&.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_freeaddrinfo(struct addrinfo*\fI\ ai\fP)
+Free the struct addrinfo. Passing NULL is allowed and is a no\-op.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_getnameinfo(uv_loop_t*\fI\ loop\fP, uv_getnameinfo_t*\fI\ req\fP, uv_getnameinfo_cb\fI\ getnameinfo_cb\fP, const struct sockaddr*\fI\ addr\fP, int\fI\ flags\fP)
+Asynchronous \fI\%getnameinfo(3)\fP\&.
+.sp
+Returns 0 on success or an error code < 0 on failure. If successful, the
+callback will get called sometime in the future with the lookup result.
+Consult \fIman \-s 3 getnameinfo\fP for more details.
+.sp
+Changed in version 1.3.0: the callback parameter is now allowed to be NULL,
+in which case the request will run \fBsynchronously\fP\&.
+
+.UNINDENT
+.sp
+\fBSEE ALSO:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_req_t\fP API functions also apply.
+.UNINDENT
+.UNINDENT
+.SS Shared library handling
+.sp
+libuv provides cross platform utilities for loading shared libraries and
+retrieving symbols from them, using the following API.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_lib_t
+Shared library data type.
+.UNINDENT
+.SS Public members
+.sp
+N/A
+.SS API
+.INDENT 0.0
+.TP
+.B int uv_dlopen(const char*\fI\ filename\fP, uv_lib_t*\fI\ lib\fP)
+Opens a shared library. The filename is in utf\-8. Returns 0 on success and
+\-1 on error. Call \fI\%uv_dlerror()\fP to get the error message.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_dlclose(uv_lib_t*\fI\ lib\fP)
+Close the shared library.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_dlsym(uv_lib_t*\fI\ lib\fP, const char*\fI\ name\fP, void**\fI\ ptr\fP)
+Retrieves a data pointer from a dynamic library. It is legal for a symbol
+to map to NULL. Returns 0 on success and \-1 if the symbol was not found.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B const char* uv_dlerror(const uv_lib_t*\fI\ lib\fP)
+Returns the last uv_dlopen() or uv_dlsym() error message.
+.UNINDENT
+.SS Threading and synchronization utilities
+.sp
+libuv provides cross\-platform implementations for multiple threading and
+synchronization primitives. The API largely follows the pthreads API.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_thread_t
+Thread data type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_thread_cb)(void*\fI\ arg\fP)
+Callback that is invoked to initialize thread execution. \fIarg\fP is the same
+value that was passed to \fI\%uv_thread_create()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_key_t
+Thread\-local key data type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_once_t
+Once\-only initializer data type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_mutex_t
+Mutex data type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_rwlock_t
+Read\-write lock data type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_sem_t
+Semaphore data type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_cond_t
+Condition data type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_barrier_t
+Barrier data type.
+.UNINDENT
+.SS API
+.SS Threads
+.INDENT 0.0
+.TP
+.B uv_thread_options_t
+Options for spawning a new thread (passed to \fI\%uv_thread_create_ex()\fP).
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_thread_options_s {
+ enum {
+ UV_THREAD_NO_FLAGS = 0x00,
+ UV_THREAD_HAS_STACK_SIZE = 0x01
+ } flags;
+ size_t stack_size;
+} uv_thread_options_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+More fields may be added to this struct at any time, so its exact
+layout and size should not be relied upon.
+.sp
+New in version 1.26.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_thread_create(uv_thread_t*\fI\ tid\fP, uv_thread_cb\fI\ entry\fP, void*\fI\ arg\fP)
+Changed in version 1.4.1: returns a UV_E* error code on failure
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_thread_create_ex(uv_thread_t*\fI\ tid\fP, const uv_thread_options_t*\fI\ params\fP, uv_thread_cb\fI\ entry\fP, void*\fI\ arg\fP)
+Like \fI\%uv_thread_create()\fP, but additionally specifies options for creating a new thread.
+.sp
+If \fIUV_THREAD_HAS_STACK_SIZE\fP is set, \fIstack_size\fP specifies a stack size for the new thread.
+\fI0\fP indicates that the default value should be used, i.e. behaves as if the flag was not set.
+Other values will be rounded up to the nearest page boundary.
+.sp
+New in version 1.26.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_thread_t uv_thread_self(void)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_thread_join(uv_thread_t\fI\ *tid\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_thread_equal(const uv_thread_t*\fI\ t1\fP, const uv_thread_t*\fI\ t2\fP)
+.UNINDENT
+.SS Thread\-local storage
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The total thread\-local storage size may be limited. That is, it may not be possible to
+create many TLS keys.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_key_create(uv_key_t*\fI\ key\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_key_delete(uv_key_t*\fI\ key\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* uv_key_get(uv_key_t*\fI\ key\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_key_set(uv_key_t*\fI\ key\fP, void*\fI\ value\fP)
+.UNINDENT
+.SS Once\-only initialization
+.sp
+Runs a function once and only once. Concurrent calls to \fI\%uv_once()\fP with the
+same guard will block all callers except one (it\(aqs unspecified which one).
+The guard should be initialized statically with the UV_ONCE_INIT macro.
+.INDENT 0.0
+.TP
+.B void uv_once(uv_once_t*\fI\ guard\fP, void (\fI*callback\fP)(void))
+.UNINDENT
+.SS Mutex locks
+.sp
+Functions return 0 on success or an error code < 0 (unless the
+return type is void, of course).
+.INDENT 0.0
+.TP
+.B int uv_mutex_init(uv_mutex_t*\fI\ handle\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_mutex_init_recursive(uv_mutex_t*\fI\ handle\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_mutex_destroy(uv_mutex_t*\fI\ handle\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_mutex_lock(uv_mutex_t*\fI\ handle\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_mutex_trylock(uv_mutex_t*\fI\ handle\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_mutex_unlock(uv_mutex_t*\fI\ handle\fP)
+.UNINDENT
+.SS Read\-write locks
+.sp
+Functions return 0 on success or an error code < 0 (unless the
+return type is void, of course).
+.INDENT 0.0
+.TP
+.B int uv_rwlock_init(uv_rwlock_t*\fI\ rwlock\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_rwlock_destroy(uv_rwlock_t*\fI\ rwlock\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_rwlock_rdlock(uv_rwlock_t*\fI\ rwlock\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_rwlock_tryrdlock(uv_rwlock_t*\fI\ rwlock\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_rwlock_rdunlock(uv_rwlock_t*\fI\ rwlock\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_rwlock_wrlock(uv_rwlock_t*\fI\ rwlock\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_rwlock_trywrlock(uv_rwlock_t*\fI\ rwlock\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_rwlock_wrunlock(uv_rwlock_t*\fI\ rwlock\fP)
+.UNINDENT
+.SS Semaphores
+.sp
+Functions return 0 on success or an error code < 0 (unless the
+return type is void, of course).
+.INDENT 0.0
+.TP
+.B int uv_sem_init(uv_sem_t*\fI\ sem\fP, unsigned int\fI\ value\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_sem_destroy(uv_sem_t*\fI\ sem\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_sem_post(uv_sem_t*\fI\ sem\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_sem_wait(uv_sem_t*\fI\ sem\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_sem_trywait(uv_sem_t*\fI\ sem\fP)
+.UNINDENT
+.SS Conditions
+.sp
+Functions return 0 on success or an error code < 0 (unless the
+return type is void, of course).
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+Callers should be prepared to deal with spurious wakeups on \fI\%uv_cond_wait()\fP
+and \fI\%uv_cond_timedwait()\fP\&.
+.IP 2. 3
+The timeout parameter for \fI\%uv_cond_timedwait()\fP is relative to the time
+at which function is called.
+.IP 3. 3
+On z/OS, the timeout parameter for \fI\%uv_cond_timedwait()\fP is converted to an
+absolute system time at which the wait expires. If the current system clock time
+passes the absolute time calculated before the condition is signaled, an ETIMEDOUT
+error results. After the wait begins, the wait time is not affected by changes
+to the system clock.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_cond_init(uv_cond_t*\fI\ cond\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_cond_destroy(uv_cond_t*\fI\ cond\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_cond_signal(uv_cond_t*\fI\ cond\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_cond_broadcast(uv_cond_t*\fI\ cond\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_cond_wait(uv_cond_t*\fI\ cond\fP, uv_mutex_t*\fI\ mutex\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_cond_timedwait(uv_cond_t*\fI\ cond\fP, uv_mutex_t*\fI\ mutex\fP, uint64_t\fI\ timeout\fP)
+.UNINDENT
+.SS Barriers
+.sp
+Functions return 0 on success or an error code < 0 (unless the
+return type is void, of course).
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+\fI\%uv_barrier_wait()\fP returns a value > 0 to an arbitrarily chosen "serializer" thread
+to facilitate cleanup, i.e.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+if (uv_barrier_wait(&barrier) > 0)
+ uv_barrier_destroy(&barrier);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_barrier_init(uv_barrier_t*\fI\ barrier\fP, unsigned int\fI\ count\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_barrier_destroy(uv_barrier_t*\fI\ barrier\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_barrier_wait(uv_barrier_t*\fI\ barrier\fP)
+.UNINDENT
+.SS Miscellaneous utilities
+.sp
+This section contains miscellaneous functions that don\(aqt really belong in any
+other section.
+.SS Data types
+.INDENT 0.0
+.TP
+.B uv_buf_t
+Buffer data type.
+.INDENT 7.0
+.TP
+.B char* uv_buf_t.base
+Pointer to the base of the buffer.
+.UNINDENT
+.INDENT 7.0
+.TP
+.B size_t uv_buf_t.len
+Total bytes in the buffer.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows this field is ULONG.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* (*uv_malloc_func)(size_t\fI\ size\fP)
+Replacement function for \fI\%malloc(3)\fP\&.
+See \fI\%uv_replace_allocator()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* (*uv_realloc_func)(void*\fI\ ptr\fP, size_t\fI\ size\fP)
+Replacement function for \fI\%realloc(3)\fP\&.
+See \fI\%uv_replace_allocator()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void* (*uv_calloc_func)(size_t\fI\ count\fP, size_t\fI\ size\fP)
+Replacement function for \fI\%calloc(3)\fP\&.
+See \fI\%uv_replace_allocator()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_free_func)(void*\fI\ ptr\fP)
+Replacement function for \fI\%free(3)\fP\&.
+See \fI\%uv_replace_allocator()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void (*uv_random_cb)(uv_random_t*\fI\ req\fP, int\fI\ status\fP, void*\fI\ buf\fP, size_t\fI\ buflen\fP)
+Callback passed to \fI\%uv_random()\fP\&. \fIstatus\fP is non\-zero in case of
+error. The \fIbuf\fP pointer is the same pointer that was passed to
+\fI\%uv_random()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_file
+Cross platform representation of a file handle.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_os_sock_t
+Cross platform representation of a socket handle.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_os_fd_t
+Abstract representation of a file descriptor. On Unix systems this is a
+\fItypedef\fP of \fIint\fP and on Windows a \fIHANDLE\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_pid_t
+Cross platform representation of a \fIpid_t\fP\&.
+.sp
+New in version 1.16.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_timeval_t
+Data type for storing times.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct {
+ long tv_sec;
+ long tv_usec;
+} uv_timeval_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_timeval64_t
+Alternative data type for storing times.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct {
+ int64_t tv_sec;
+ int32_t tv_usec;
+} uv_timeval64_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_rusage_t
+Data type for resource usage results.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct {
+ uv_timeval_t ru_utime; /* user CPU time used */
+ uv_timeval_t ru_stime; /* system CPU time used */
+ uint64_t ru_maxrss; /* maximum resident set size */
+ uint64_t ru_ixrss; /* integral shared memory size (X) */
+ uint64_t ru_idrss; /* integral unshared data size (X) */
+ uint64_t ru_isrss; /* integral unshared stack size (X) */
+ uint64_t ru_minflt; /* page reclaims (soft page faults) (X) */
+ uint64_t ru_majflt; /* page faults (hard page faults) */
+ uint64_t ru_nswap; /* swaps (X) */
+ uint64_t ru_inblock; /* block input operations */
+ uint64_t ru_oublock; /* block output operations */
+ uint64_t ru_msgsnd; /* IPC messages sent (X) */
+ uint64_t ru_msgrcv; /* IPC messages received (X) */
+ uint64_t ru_nsignals; /* signals received (X) */
+ uint64_t ru_nvcsw; /* voluntary context switches (X) */
+ uint64_t ru_nivcsw; /* involuntary context switches (X) */
+} uv_rusage_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Members marked with \fI(X)\fP are unsupported on Windows.
+See \fI\%getrusage(2)\fP for supported fields on Unix
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_cpu_info_t
+Data type for CPU information.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_cpu_info_s {
+ char* model;
+ int speed;
+ struct uv_cpu_times_s {
+ uint64_t user; /* milliseconds */
+ uint64_t nice; /* milliseconds */
+ uint64_t sys; /* milliseconds */
+ uint64_t idle; /* milliseconds */
+ uint64_t irq; /* milliseconds */
+ } cpu_times;
+} uv_cpu_info_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_interface_address_t
+Data type for interface addresses.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_interface_address_s {
+ char* name;
+ char phys_addr[6];
+ int is_internal;
+ union {
+ struct sockaddr_in address4;
+ struct sockaddr_in6 address6;
+ } address;
+ union {
+ struct sockaddr_in netmask4;
+ struct sockaddr_in6 netmask6;
+ } netmask;
+} uv_interface_address_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_passwd_t
+Data type for password file information.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_passwd_s {
+ char* username;
+ long uid;
+ long gid;
+ char* shell;
+ char* homedir;
+} uv_passwd_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_utsname_t
+Data type for operating system name and version information.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_utsname_s {
+ char sysname[256];
+ char release[256];
+ char version[256];
+ char machine[256];
+} uv_utsname_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_env_item_t
+Data type for environment variable storage.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_env_item_s {
+ char* name;
+ char* value;
+} uv_env_item_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_random_t
+Random data request type.
+.UNINDENT
+.SS API
+.INDENT 0.0
+.TP
+.B uv_handle_type uv_guess_handle(uv_file\fI\ file\fP)
+Used to detect what type of stream should be used with a given file
+descriptor. Usually this will be used during initialization to guess the
+type of the stdio streams.
+.sp
+For \fI\%isatty(3)\fP equivalent functionality use this function and test
+for \fBUV_TTY\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_replace_allocator(uv_malloc_func\fI\ malloc_func\fP, uv_realloc_func\fI\ realloc_func\fP, uv_calloc_func\fI\ calloc_func\fP, uv_free_func\fI\ free_func\fP)
+New in version 1.6.0.
+
+.sp
+Override the use of the standard library\(aqs \fI\%malloc(3)\fP,
+\fI\%calloc(3)\fP, \fI\%realloc(3)\fP, \fI\%free(3)\fP, memory allocation
+functions.
+.sp
+This function must be called before any other libuv function is called or
+after all resources have been freed and thus libuv doesn\(aqt reference
+any allocated memory chunk.
+.sp
+On success, it returns 0, if any of the function pointers is NULL it
+returns UV_EINVAL.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+There is no protection against changing the allocator multiple
+times. If the user changes it they are responsible for making
+sure the allocator is changed while no memory was allocated with
+the previous allocator, or that they are compatible.
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+Allocator must be thread\-safe.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_library_shutdown(void);
+New in version 1.38.0.
+
+.sp
+Release any global state that libuv is holding onto. Libuv will normally
+do so automatically when it is unloaded but it can be instructed to perform
+cleanup manually.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+Only call \fBuv_library_shutdown()\fP once.
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+Don\(aqt call \fBuv_library_shutdown()\fP when there are
+still event loops or I/O requests active.
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+Don\(aqt call libuv functions after calling
+\fBuv_library_shutdown()\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_buf_t uv_buf_init(char*\fI\ base\fP, unsigned int\fI\ len\fP)
+Constructor for \fI\%uv_buf_t\fP\&.
+.sp
+Due to platform differences the user cannot rely on the ordering of the
+\fIbase\fP and \fIlen\fP members of the uv_buf_t struct. The user is responsible for
+freeing \fIbase\fP after the uv_buf_t is done. Return struct passed by value.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B char** uv_setup_args(int\fI\ argc\fP, char**\fI\ argv\fP)
+Store the program arguments. Required for getting / setting the process title.
+Libuv may take ownership of the memory that \fIargv\fP points to. This function
+should be called exactly once, at program start\-up.
+.sp
+Example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+argv = uv_setup_args(argc, argv); /* May return a copy of argv. */
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_get_process_title(char*\fI\ buffer\fP, size_t\fI\ size\fP)
+Gets the title of the current process. You \fImust\fP call \fIuv_setup_args\fP
+before calling this function. If \fIbuffer\fP is \fINULL\fP or \fIsize\fP is zero,
+\fIUV_EINVAL\fP is returned. If \fIsize\fP cannot accommodate the process title and
+terminating \fINULL\fP character, the function returns \fIUV_ENOBUFS\fP\&.
+.sp
+Changed in version 1.18.1: now thread\-safe on all supported platforms.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_set_process_title(const char*\fI\ title\fP)
+Sets the current process title. You \fImust\fP call \fIuv_setup_args\fP before
+calling this function. On platforms with a fixed size buffer for the process
+title the contents of \fItitle\fP will be copied to the buffer and truncated if
+larger than the available space. Other platforms will return \fIUV_ENOMEM\fP if
+they cannot allocate enough space to duplicate the contents of \fItitle\fP\&.
+.sp
+Changed in version 1.18.1: now thread\-safe on all supported platforms.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_resident_set_memory(size_t*\fI\ rss\fP)
+Gets the resident set size (RSS) for the current process.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_uptime(double*\fI\ uptime\fP)
+Gets the current system uptime.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_getrusage(uv_rusage_t*\fI\ rusage\fP)
+Gets the resource usage measures for the current process.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows not all fields are set, the unsupported fields are filled with zeroes.
+See \fI\%uv_rusage_t\fP for more details.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_pid_t uv_os_getpid(void)
+Returns the current process ID.
+.sp
+New in version 1.18.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uv_pid_t uv_os_getppid(void)
+Returns the parent process ID.
+.sp
+New in version 1.16.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_cpu_info(uv_cpu_info_t**\fI\ cpu_infos\fP, int*\fI\ count\fP)
+Gets information about the CPUs on the system. The \fIcpu_infos\fP array will
+have \fIcount\fP elements and needs to be freed with \fI\%uv_free_cpu_info()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_free_cpu_info(uv_cpu_info_t*\fI\ cpu_infos\fP, int\fI\ count\fP)
+Frees the \fIcpu_infos\fP array previously allocated with \fI\%uv_cpu_info()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_interface_addresses(uv_interface_address_t**\fI\ addresses\fP, int*\fI\ count\fP)
+Gets address information about the network interfaces on the system. An
+array of \fIcount\fP elements is allocated and returned in \fIaddresses\fP\&. It must
+be freed by the user, calling \fI\%uv_free_interface_addresses()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_free_interface_addresses(uv_interface_address_t*\fI\ addresses\fP, int\fI\ count\fP)
+Free an array of \fI\%uv_interface_address_t\fP which was returned by
+\fI\%uv_interface_addresses()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_loadavg(double\fI\ avg[3]\fP)
+Gets the load average. See: \fI\%https://en.wikipedia.org/wiki/Load_(computing)\fP
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Returns [0,0,0] on Windows (i.e., it\(aqs not implemented).
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_ip4_addr(const char*\fI\ ip\fP, int\fI\ port\fP, struct sockaddr_in*\fI\ addr\fP)
+Convert a string containing an IPv4 addresses to a binary structure.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_ip6_addr(const char*\fI\ ip\fP, int\fI\ port\fP, struct sockaddr_in6*\fI\ addr\fP)
+Convert a string containing an IPv6 addresses to a binary structure.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_ip4_name(const struct sockaddr_in*\fI\ src\fP, char*\fI\ dst\fP, size_t\fI\ size\fP)
+Convert a binary structure containing an IPv4 address to a string.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_ip6_name(const struct sockaddr_in6*\fI\ src\fP, char*\fI\ dst\fP, size_t\fI\ size\fP)
+Convert a binary structure containing an IPv6 address to a string.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_inet_ntop(int\fI\ af\fP, const void*\fI\ src\fP, char*\fI\ dst\fP, size_t\fI\ size\fP)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_inet_pton(int\fI\ af\fP, const char*\fI\ src\fP, void*\fI\ dst\fP)
+Cross\-platform IPv6\-capable implementation of \fI\%inet_ntop(3)\fP
+and \fI\%inet_pton(3)\fP\&. On success they return 0. In case of error
+the target \fIdst\fP pointer is unmodified.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B UV_IF_NAMESIZE
+Maximum IPv6 interface identifier name length. Defined as
+\fIIFNAMSIZ\fP on Unix and \fIIF_NAMESIZE\fP on Linux and Windows.
+.sp
+New in version 1.16.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_if_indextoname(unsigned int\fI\ ifindex\fP, char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+IPv6\-capable implementation of \fI\%if_indextoname(3)\fP\&. When called,
+\fI*size\fP indicates the length of the \fIbuffer\fP, which is used to store the
+result.
+On success, zero is returned, \fIbuffer\fP contains the interface name, and
+\fI*size\fP represents the string length of the \fIbuffer\fP, excluding the NUL
+terminator byte from \fI*size\fP\&. On error, a negative result is
+returned. If \fIbuffer\fP is not large enough to hold the result,
+\fIUV_ENOBUFS\fP is returned, and \fI*size\fP represents the necessary size in
+bytes, including the NUL terminator byte into the \fI*size\fP\&.
+.sp
+On Unix, the returned interface name can be used directly as an
+interface identifier in scoped IPv6 addresses, e.g.
+\fIfe80::abc:def1:2345%en0\fP\&.
+.sp
+On Windows, the returned interface cannot be used as an interface
+identifier, as Windows uses numerical interface identifiers, e.g.
+\fIfe80::abc:def1:2345%5\fP\&.
+.sp
+To get an interface identifier in a cross\-platform compatible way,
+use \fIuv_if_indextoiid()\fP\&.
+.sp
+Example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+char ifname[UV_IF_NAMESIZE];
+size_t size = sizeof(ifname);
+uv_if_indextoname(sin6\->sin6_scope_id, ifname, &size);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.16.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_if_indextoiid(unsigned int\fI\ ifindex\fP, char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Retrieves a network interface identifier suitable for use in an IPv6 scoped
+address. On Windows, returns the numeric \fIifindex\fP as a string. On all other
+platforms, \fIuv_if_indextoname()\fP is called. The result is written to
+\fIbuffer\fP, with \fI*size\fP indicating the length of \fIbuffer\fP\&. If \fIbuffer\fP is not
+large enough to hold the result, then \fIUV_ENOBUFS\fP is returned, and \fI*size\fP
+represents the size, including the NUL byte, required to hold the
+result.
+.sp
+See \fIuv_if_indextoname\fP for further details.
+.sp
+New in version 1.16.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_exepath(char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Gets the executable path.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_cwd(char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Gets the current working directory, and stores it in \fIbuffer\fP\&. If the
+current working directory is too large to fit in \fIbuffer\fP, this function
+returns \fIUV_ENOBUFS\fP, and sets \fIsize\fP to the required length, including the
+null terminator.
+.sp
+Changed in version 1.1.0: On Unix the path no longer ends in a slash.
+
+.sp
+Changed in version 1.9.0: the returned length includes the terminating null
+byte on \fIUV_ENOBUFS\fP, and the buffer is null terminated
+on success.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_chdir(const char*\fI\ dir\fP)
+Changes the current working directory.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_homedir(char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Gets the current user\(aqs home directory. On Windows, \fIuv_os_homedir()\fP first
+checks the \fIUSERPROFILE\fP environment variable using
+\fIGetEnvironmentVariableW()\fP\&. If \fIUSERPROFILE\fP is not set,
+\fIGetUserProfileDirectoryW()\fP is called. On all other operating systems,
+\fIuv_os_homedir()\fP first checks the \fIHOME\fP environment variable using
+\fI\%getenv(3)\fP\&. If \fIHOME\fP is not set, \fI\%getpwuid_r(3)\fP is called. The
+user\(aqs home directory is stored in \fIbuffer\fP\&. When \fIuv_os_homedir()\fP is
+called, \fIsize\fP indicates the maximum size of \fIbuffer\fP\&. On success \fIsize\fP is set
+to the string length of \fIbuffer\fP\&. On \fIUV_ENOBUFS\fP failure \fIsize\fP is set to the
+required length for \fIbuffer\fP, including the null byte.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIuv_os_homedir()\fP is not thread safe.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.6.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_tmpdir(char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Gets the temp directory. On Windows, \fIuv_os_tmpdir()\fP uses \fIGetTempPathW()\fP\&.
+On all other operating systems, \fIuv_os_tmpdir()\fP uses the first environment
+variable found in the ordered list \fITMPDIR\fP, \fITMP\fP, \fITEMP\fP, and \fITEMPDIR\fP\&.
+If none of these are found, the path \fI"/tmp"\fP is used, or, on Android,
+\fI"/data/local/tmp"\fP is used. The temp directory is stored in \fIbuffer\fP\&. When
+\fIuv_os_tmpdir()\fP is called, \fIsize\fP indicates the maximum size of \fIbuffer\fP\&.
+On success \fIsize\fP is set to the string length of \fIbuffer\fP (which does not
+include the terminating null). On \fIUV_ENOBUFS\fP failure \fIsize\fP is set to the
+required length for \fIbuffer\fP, including the null byte.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+\fIuv_os_tmpdir()\fP is not thread safe.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.9.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_get_passwd(uv_passwd_t*\fI\ pwd\fP)
+Gets a subset of the password file entry for the current effective uid (not
+the real uid). The populated data includes the username, euid, gid, shell,
+and home directory. On non\-Windows systems, all data comes from
+\fI\%getpwuid_r(3)\fP\&. On Windows, uid and gid are set to \-1 and have no
+meaning, and shell is \fINULL\fP\&. After successfully calling this function, the
+memory allocated to \fIpwd\fP needs to be freed with
+\fI\%uv_os_free_passwd()\fP\&.
+.sp
+New in version 1.9.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_os_free_passwd(uv_passwd_t*\fI\ pwd\fP)
+Frees the \fIpwd\fP memory previously allocated with \fI\%uv_os_get_passwd()\fP\&.
+.sp
+New in version 1.9.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uint64_t uv_get_free_memory(void)
+Gets memory information (in bytes).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uint64_t uv_get_total_memory(void)
+Gets memory information (in bytes).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uint64_t uv_get_constrained_memory(void)
+Gets the amount of memory available to the process (in bytes) based on
+limits imposed by the OS. If there is no such constraint, or the constraint
+is unknown, \fI0\fP is returned. Note that it is not unusual for this value to
+be less than or greater than \fI\%uv_get_total_memory()\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function currently only returns a non\-zero value on Linux, based
+on cgroups if it is present.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.29.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B uint64_t uv_hrtime(void)
+Returns the current high\-resolution real time. This is expressed in
+nanoseconds. It is relative to an arbitrary time in the past. It is not
+related to the time of day and therefore not subject to clock drift. The
+primary use is for measuring performance between intervals.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+Not every platform can support nanosecond resolution; however, this value will always
+be in nanoseconds.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_print_all_handles(uv_loop_t*\fI\ loop\fP, FILE*\fI\ stream\fP)
+Prints all handles associated with the given \fIloop\fP to the given \fIstream\fP\&.
+.sp
+Example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_print_all_handles(uv_default_loop(), stderr);
+/*
+[\-\-I] signal 0x1a25ea8
+[\-AI] async 0x1a25cf0
+[R\-\-] idle 0x1a7a8c8
+*/
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The format is \fI[flags] handle\-type handle\-address\fP\&. For \fIflags\fP:
+.INDENT 7.0
+.IP \(bu 2
+\fIR\fP is printed for a handle that is referenced
+.IP \(bu 2
+\fIA\fP is printed for a handle that is active
+.IP \(bu 2
+\fII\fP is printed for a handle that is internal
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function is meant for ad hoc debugging, there is no API/ABI
+stability guarantees.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.8.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_print_active_handles(uv_loop_t*\fI\ loop\fP, FILE*\fI\ stream\fP)
+This is the same as \fI\%uv_print_all_handles()\fP except only active handles
+are printed.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function is meant for ad hoc debugging, there is no API/ABI
+stability guarantees.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.8.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_environ(uv_env_item_t**\fI\ envitems\fP, int*\fI\ count\fP)
+Retrieves all environment variables. This function will allocate memory
+which must be freed by calling \fBuv_os_free_environ()\fP\&.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function is not thread safe.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.31.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_os_free_environ(uv_env_item_t* envitems, int count);
+Frees the memory allocated for the environment variables by
+\fI\%uv_os_environ()\fP\&.
+.sp
+New in version 1.31.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_getenv(const char*\fI\ name\fP, char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Retrieves the environment variable specified by \fIname\fP, copies its value
+into \fIbuffer\fP, and sets \fIsize\fP to the string length of the value. When
+calling this function, \fIsize\fP must be set to the amount of storage available
+in \fIbuffer\fP, including the null terminator. If the environment variable
+exceeds the storage available in \fIbuffer\fP, \fIUV_ENOBUFS\fP is returned, and
+\fIsize\fP is set to the amount of storage required to hold the value. If no
+matching environment variable exists, \fIUV_ENOENT\fP is returned.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function is not thread safe.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.12.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_setenv(const char*\fI\ name\fP, const char*\fI\ value\fP)
+Creates or updates the environment variable specified by \fIname\fP with
+\fIvalue\fP\&.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function is not thread safe.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.12.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_unsetenv(const char*\fI\ name\fP)
+Deletes the environment variable specified by \fIname\fP\&. If no such environment
+variable exists, this function returns successfully.
+.sp
+\fBWARNING:\fP
+.INDENT 7.0
+.INDENT 3.5
+This function is not thread safe.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.12.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_gethostname(char*\fI\ buffer\fP, size_t*\fI\ size\fP)
+Returns the hostname as a null\-terminated string in \fIbuffer\fP, and sets
+\fIsize\fP to the string length of the hostname. When calling this function,
+\fIsize\fP must be set to the amount of storage available in \fIbuffer\fP, including
+the null terminator. If the hostname exceeds the storage available in
+\fIbuffer\fP, \fIUV_ENOBUFS\fP is returned, and \fIsize\fP is set to the amount of
+storage required to hold the value.
+.sp
+New in version 1.12.0.
+
+.sp
+Changed in version 1.26.0: \fIUV_MAXHOSTNAMESIZE\fP is available and represents
+the maximum \fIbuffer\fP size required to store a
+hostname and terminating \fInul\fP character.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_getpriority(uv_pid_t\fI\ pid\fP, int*\fI\ priority\fP)
+Retrieves the scheduling priority of the process specified by \fIpid\fP\&. The
+returned value of \fIpriority\fP is between \-20 (high priority) and 19 (low
+priority).
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows, the returned priority will equal one of the \fIUV_PRIORITY\fP
+constants.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.23.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_setpriority(uv_pid_t\fI\ pid\fP, int\fI\ priority\fP)
+Sets the scheduling priority of the process specified by \fIpid\fP\&. The
+\fIpriority\fP value range is between \-20 (high priority) and 19 (low priority).
+The constants \fIUV_PRIORITY_LOW\fP, \fIUV_PRIORITY_BELOW_NORMAL\fP,
+\fIUV_PRIORITY_NORMAL\fP, \fIUV_PRIORITY_ABOVE_NORMAL\fP, \fIUV_PRIORITY_HIGH\fP, and
+\fIUV_PRIORITY_HIGHEST\fP are also provided for convenience.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows, this function utilizes \fISetPriorityClass()\fP\&. The \fIpriority\fP
+argument is mapped to a Windows priority class. When retrieving the
+process priority, the result will equal one of the \fIUV_PRIORITY\fP
+constants, and not necessarily the exact value of \fIpriority\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Windows, setting \fIPRIORITY_HIGHEST\fP will only work for elevated user,
+for others it will be silently reduced to \fIPRIORITY_HIGH\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On IBM i PASE, the highest process priority is \-10. The constant
+\fIUV_PRIORITY_HIGHEST\fP is \-10, \fIUV_PRIORITY_HIGH\fP is \-7,
+\fIUV_PRIORITY_ABOVE_NORMAL\fP is \-4, \fIUV_PRIORITY_NORMAL\fP is 0,
+\fIUV_PRIORITY_BELOW_NORMAL\fP is 15 and \fIUV_PRIORITY_LOW\fP is 39.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On IBM i PASE, you are not allowed to change your priority unless you
+have the *JOBCTL special authority (even to lower it).
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.23.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_os_uname(uv_utsname_t*\fI\ buffer\fP)
+Retrieves system information in \fIbuffer\fP\&. The populated data includes the
+operating system name, release, version, and machine. On non\-Windows
+systems, \fIuv_os_uname()\fP is a thin wrapper around \fI\%uname(2)\fP\&. Returns
+zero on success, and a non\-zero error value otherwise.
+.sp
+New in version 1.25.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_gettimeofday(uv_timeval64_t*\fI\ tv\fP)
+Cross\-platform implementation of \fI\%gettimeofday(2)\fP\&. The timezone
+argument to \fIgettimeofday()\fP is not supported, as it is considered obsolete.
+.sp
+New in version 1.28.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B int uv_random(uv_loop_t*\fI\ loop\fP, uv_random_t*\fI\ req\fP, void*\fI\ buf\fP, size_t\fI\ buflen\fP, unsigned int\fI\ flags\fP, uv_random_cb\fI\ cb\fP)
+Fill \fIbuf\fP with exactly \fIbuflen\fP cryptographically strong random bytes
+acquired from the system CSPRNG. \fIflags\fP is reserved for future extension
+and must currently be 0.
+.sp
+Short reads are not possible. When less than \fIbuflen\fP random bytes are
+available, a non\-zero error value is returned or passed to the callback.
+.sp
+The synchronous version may block indefinitely when not enough entropy
+is available. The asynchronous version may not ever finish when the system
+is low on entropy.
+.sp
+Sources of entropy:
+.INDENT 7.0
+.IP \(bu 2
+Windows: \fIRtlGenRandom <https://docs.microsoft.com/en\-us/windows/desktop/api/ntsecapi/nf\-ntsecapi\-rtlgenrandom>_\fP\&.
+.IP \(bu 2
+Linux, Android: \fI\%getrandom(2)\fP if available, or \fI\%urandom(4)\fP
+after reading from \fI/dev/random\fP once, or the \fIKERN_RANDOM\fP
+\fI\%sysctl(2)\fP\&.
+.IP \(bu 2
+FreeBSD: \fIgetrandom(2) <https://www.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2>_\fP,
+or \fI/dev/urandom\fP after reading from \fI/dev/random\fP once.
+.IP \(bu 2
+NetBSD: \fIKERN_ARND\fP \fIsysctl(3) <https://netbsd.gw.com/cgi\-bin/man\-cgi?sysctl+3+NetBSD\-current>_\fP
+.IP \(bu 2
+macOS, OpenBSD: \fIgetentropy(2) <https://man.openbsd.org/getentropy.2>_\fP
+if available, or \fI/dev/urandom\fP after reading from \fI/dev/random\fP once.
+.IP \(bu 2
+AIX: \fI/dev/random\fP\&.
+.IP \(bu 2
+IBM i: \fI/dev/urandom\fP\&.
+.IP \(bu 2
+Other UNIX: \fI/dev/urandom\fP after reading from \fI/dev/random\fP once.
+.UNINDENT
+.INDENT 7.0
+.TP
+.B Returns
+0 on success, or an error code < 0 on failure. The contents of
+\fIbuf\fP is undefined after an error.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+When using the synchronous version, both \fIloop\fP and \fIreq\fP parameters
+are not used and can be set to \fINULL\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+New in version 1.33.0.
+
+.UNINDENT
+.INDENT 0.0
+.TP
+.B void uv_sleep(unsigned int\fI\ msec\fP)
+Causes the calling thread to sleep for \fImsec\fP milliseconds.
+.sp
+New in version 1.34.0.
+
+.UNINDENT
+.SS User guide
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+The contents of this guide have been recently incorporated into the libuv documentation
+and it hasn\(aqt gone through thorough review yet. If you spot a mistake please file an
+issue, or better yet, open a pull request!
+.UNINDENT
+.UNINDENT
+.SS Introduction
+.sp
+This \(aqbook\(aq is a small set of tutorials about using \fI\%libuv\fP as
+a high performance evented I/O library which offers the same API on Windows and Unix.
+.sp
+It is meant to cover the main areas of libuv, but is not a comprehensive
+reference discussing every function and data structure. The \fI\%official libuv
+documentation\fP may be consulted for full details.
+.sp
+This book is still a work in progress, so sections may be incomplete, but
+I hope you will enjoy it as it grows.
+.SS Who this book is for
+.sp
+If you are reading this book, you are either:
+.INDENT 0.0
+.IP 1. 3
+a systems programmer, creating low\-level programs such as daemons or network
+services and clients. You have found that the event loop approach is well
+suited for your application and decided to use libuv.
+.IP 2. 3
+a node.js module writer, who wants to wrap platform APIs
+written in C or C++ with a set of (a)synchronous APIs that are exposed to
+JavaScript. You will use libuv purely in the context of node.js. For
+this you will require some other resources as the book does not cover parts
+specific to v8/node.js.
+.UNINDENT
+.sp
+This book assumes that you are comfortable with the C programming language.
+.SS Background
+.sp
+The \fI\%node.js\fP project began in 2009 as a JavaScript environment decoupled
+from the browser. Using Google\(aqs \fI\%V8\fP and Marc Lehmann\(aqs \fI\%libev\fP, node.js
+combined a model of I/O \-\- evented \-\- with a language that was well suited to
+the style of programming; due to the way it had been shaped by browsers. As
+node.js grew in popularity, it was important to make it work on Windows, but
+libev ran only on Unix. The Windows equivalent of kernel event notification
+mechanisms like kqueue or (e)poll is IOCP. libuv was an abstraction around libev
+or IOCP depending on the platform, providing users an API based on libev.
+In the node\-v0.9.0 version of libuv \fI\%libev was removed\fP\&.
+.sp
+Since then libuv has continued to mature and become a high quality standalone
+library for system programming. Users outside of node.js include Mozilla\(aqs
+\fI\%Rust\fP programming language, and a \fI\%variety\fP of language bindings.
+.sp
+This book and the code is based on libuv version \fI\%v1.3.0\fP\&.
+.SS Code
+.sp
+All the code from this book is included as part of the source of the book on
+Github. \fI\%Clone\fP/\fI\%Download\fP the book, then build libuv:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+cd libuv
+\&./autogen.sh
+\&./configure
+make
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+There is no need to \fBmake install\fP\&. To build the examples run \fBmake\fP in the
+\fBcode/\fP directory.
+.SS Basics of libuv
+.sp
+libuv enforces an \fBasynchronous\fP, \fBevent\-driven\fP style of programming. Its
+core job is to provide an event loop and callback based notifications of I/O
+and other activities. libuv offers core utilities like timers, non\-blocking
+networking support, asynchronous file system access, child processes and more.
+.SS Event loops
+.sp
+In event\-driven programming, an application expresses interest in certain events
+and respond to them when they occur. The responsibility of gathering events
+from the operating system or monitoring other sources of events is handled by
+libuv, and the user can register callbacks to be invoked when an event occurs.
+The event\-loop usually keeps running \fIforever\fP\&. In pseudocode:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+while there are still events to process:
+ e = get the next event
+ if there is a callback associated with e:
+ call the callback
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Some examples of events are:
+.INDENT 0.0
+.IP \(bu 2
+File is ready for writing
+.IP \(bu 2
+A socket has data ready to be read
+.IP \(bu 2
+A timer has timed out
+.UNINDENT
+.sp
+This event loop is encapsulated by \fBuv_run()\fP \-\- the end\-all function when using
+libuv.
+.sp
+The most common activity of systems programs is to deal with input and output,
+rather than a lot of number\-crunching. The problem with using conventional
+input/output functions (\fBread\fP, \fBfprintf\fP, etc.) is that they are
+\fBblocking\fP\&. The actual write to a hard disk or reading from a network, takes
+a disproportionately long time compared to the speed of the processor. The
+functions don\(aqt return until the task is done, so that your program is doing
+nothing. For programs which require high performance this is a major roadblock
+as other activities and other I/O operations are kept waiting.
+.sp
+One of the standard solutions is to use threads. Each blocking I/O operation is
+started in a separate thread (or in a thread pool). When the blocking function
+gets invoked in the thread, the processor can schedule another thread to run,
+which actually needs the CPU.
+.sp
+The approach followed by libuv uses another style, which is the \fBasynchronous,
+non\-blocking\fP style. Most modern operating systems provide event notification
+subsystems. For example, a normal \fBread\fP call on a socket would block until
+the sender actually sent something. Instead, the application can request the
+operating system to watch the socket and put an event notification in the
+queue. The application can inspect the events at its convenience (perhaps doing
+some number crunching before to use the processor to the maximum) and grab the
+data. It is \fBasynchronous\fP because the application expressed interest at one
+point, then used the data at another point (in time and space). It is
+\fBnon\-blocking\fP because the application process was free to do other tasks.
+This fits in well with libuv\(aqs event\-loop approach, since the operating system
+events can be treated as just another libuv event. The non\-blocking ensures
+that other events can continue to be handled as fast as they come in [1]\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+How the I/O is run in the background is not of our concern, but due to the
+way our computer hardware works, with the thread as the basic unit of the
+processor, libuv and OSes will usually run background/worker threads and/or
+polling to perform tasks in a non\-blocking manner.
+.UNINDENT
+.UNINDENT
+.sp
+Bert Belder, one of the libuv core developers has a small video explaining the
+architecture of libuv and its background. If you have no prior experience with
+either libuv or libev, it is a quick, useful watch.
+.sp
+libuv\(aqs event loop is explained in more detail in the \fI\%documentation\fP\&.
+.SS Hello World
+.sp
+With the basics out of the way, let\(aqs write our first libuv program. It does
+nothing, except start a loop which will exit immediately.
+.sp
+helloworld/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+#include <stdlib.h>
+#include <uv.h>
+
+int main() {
+ uv_loop_t *loop = malloc(sizeof(uv_loop_t));
+ uv_loop_init(loop);
+
+ printf("Now quitting.\en");
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ uv_loop_close(loop);
+ free(loop);
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+This program quits immediately because it has no events to process. A libuv
+event loop has to be told to watch out for events using the various API
+functions.
+.sp
+Starting with libuv v1.0, users should allocate the memory for the loops before
+initializing it with \fBuv_loop_init(uv_loop_t *)\fP\&. This allows you to plug in
+custom memory management. Remember to de\-initialize the loop using
+\fBuv_loop_close(uv_loop_t *)\fP and then delete the storage. The examples never
+close loops since the program quits after the loop ends and the system will
+reclaim memory. Production grade projects, especially long running systems
+programs, should take care to release correctly.
+.SS Default loop
+.sp
+A default loop is provided by libuv and can be accessed using
+\fBuv_default_loop()\fP\&. You should use this loop if you only want a single
+loop.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+node.js uses the default loop as its main loop. If you are writing bindings
+you should be aware of this.
+.UNINDENT
+.UNINDENT
+.SS Error handling
+.sp
+Initialization functions or synchronous functions which may fail return a negative number on error. Async functions that may fail will pass a status parameter to their callbacks. The error messages are defined as \fBUV_E*\fP \fI\%constants\fP\&.
+.sp
+You can use the \fBuv_strerror(int)\fP and \fBuv_err_name(int)\fP functions
+to get a \fBconst char *\fP describing the error or the error name respectively.
+.sp
+I/O read callbacks (such as for files and sockets) are passed a parameter \fBnread\fP\&. If \fBnread\fP is less than 0, there was an error (UV_EOF is the end of file error, which you may want to handle differently).
+.SS Handles and Requests
+.sp
+libuv works by the user expressing interest in particular events. This is
+usually done by creating a \fBhandle\fP to an I/O device, timer or process.
+Handles are opaque structs named as \fBuv_TYPE_t\fP where type signifies what the
+handle is used for.
+.sp
+libuv watchers
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+/* Handle types. */
+typedef struct uv_loop_s uv_loop_t;
+typedef struct uv_handle_s uv_handle_t;
+typedef struct uv_dir_s uv_dir_t;
+typedef struct uv_stream_s uv_stream_t;
+typedef struct uv_tcp_s uv_tcp_t;
+typedef struct uv_udp_s uv_udp_t;
+typedef struct uv_pipe_s uv_pipe_t;
+typedef struct uv_tty_s uv_tty_t;
+typedef struct uv_poll_s uv_poll_t;
+typedef struct uv_timer_s uv_timer_t;
+typedef struct uv_prepare_s uv_prepare_t;
+typedef struct uv_check_s uv_check_t;
+typedef struct uv_idle_s uv_idle_t;
+typedef struct uv_async_s uv_async_t;
+typedef struct uv_process_s uv_process_t;
+typedef struct uv_fs_event_s uv_fs_event_t;
+typedef struct uv_fs_poll_s uv_fs_poll_t;
+typedef struct uv_signal_s uv_signal_t;
+
+/* Request types. */
+typedef struct uv_req_s uv_req_t;
+typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
+typedef struct uv_getnameinfo_s uv_getnameinfo_t;
+typedef struct uv_shutdown_s uv_shutdown_t;
+typedef struct uv_write_s uv_write_t;
+typedef struct uv_connect_s uv_connect_t;
+typedef struct uv_udp_send_s uv_udp_send_t;
+typedef struct uv_fs_s uv_fs_t;
+typedef struct uv_work_s uv_work_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Handles represent long\-lived objects. Async operations on such handles are
+identified using \fBrequests\fP\&. A request is short\-lived (usually used across
+only one callback) and usually indicates one I/O operation on a handle.
+Requests are used to preserve context between the initiation and the callback
+of individual actions. For example, an UDP socket is represented by
+a \fBuv_udp_t\fP, while individual writes to the socket use a \fBuv_udp_send_t\fP
+structure that is passed to the callback after the write is done.
+.sp
+Handles are setup by a corresponding:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_TYPE_init(uv_loop_t *, uv_TYPE_t *)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+function.
+.sp
+Callbacks are functions which are called by libuv whenever an event the watcher
+is interested in has taken place. Application specific logic will usually be
+implemented in the callback. For example, an IO watcher\(aqs callback will receive
+the data read from a file, a timer callback will be triggered on timeout and so
+on.
+.SS Idling
+.sp
+Here is an example of using an idle handle. The callback is called once on
+every turn of the event loop. A use case for idle handles is discussed in
+utilities\&. Let us use an idle watcher to look at the watcher life cycle
+and see how \fBuv_run()\fP will now block because a watcher is present. The idle
+watcher is stopped when the count is reached and \fBuv_run()\fP exits since no
+event watchers are active.
+.sp
+idle\-basic/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+#include <uv.h>
+
+int64_t counter = 0;
+
+void wait_for_a_while(uv_idle_t* handle) {
+ counter++;
+
+ if (counter >= 10e6)
+ uv_idle_stop(handle);
+}
+
+int main() {
+ uv_idle_t idler;
+
+ uv_idle_init(uv_default_loop(), &idler);
+ uv_idle_start(&idler, wait_for_a_while);
+
+ printf("Idling...\en");
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ uv_loop_close(uv_default_loop());
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Storing context
+.sp
+In callback based programming style you\(aqll often want to pass some \(aqcontext\(aq \-\-
+application specific information \-\- between the call site and the callback. All
+handles and requests have a \fBvoid* data\fP member which you can set to the
+context and cast back in the callback. This is a common pattern used throughout
+the C library ecosystem. In addition \fBuv_loop_t\fP also has a similar data
+member.
+
+.sp
+.ce
+----
+
+.ce 0
+.sp
+.IP [1] 5
+Depending on the capacity of the hardware of course.
+.SS Filesystem
+.sp
+Simple filesystem read/write is achieved using the \fBuv_fs_*\fP functions and the
+\fBuv_fs_t\fP struct.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The libuv filesystem operations are different from socket operations\&. Socket operations use the non\-blocking operations provided
+by the operating system. Filesystem operations use blocking functions
+internally, but invoke these functions in a \fI\%thread pool\fP and notify
+watchers registered with the event loop when application interaction is
+required.
+.UNINDENT
+.UNINDENT
+.sp
+All filesystem functions have two forms \- \fIsynchronous\fP and \fIasynchronous\fP\&.
+.sp
+The \fIsynchronous\fP forms automatically get called (and \fBblock\fP) if the
+callback is null. The return value of functions is a libuv error code\&. This is usually only useful for synchronous calls.
+The \fIasynchronous\fP form is called when a callback is passed and the return
+value is 0.
+.SS Reading/Writing files
+.sp
+A file descriptor is obtained using
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBflags\fP and \fBmode\fP are standard
+\fI\%Unix flags\fP\&.
+libuv takes care of converting to the appropriate Windows flags.
+.sp
+File descriptors are closed using
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Filesystem operation callbacks have the signature:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void callback(uv_fs_t* req);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Let\(aqs see a simple implementation of \fBcat\fP\&. We start with registering
+a callback for when the file is opened:
+.sp
+uvcat/main.c \- opening a file
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void on_open(uv_fs_t *req) {
+ // The request passed to the callback is the same as the one the call setup
+ // function was passed.
+ assert(req == &open_req);
+ if (req\->result >= 0) {
+ iov = uv_buf_init(buffer, sizeof(buffer));
+ uv_fs_read(uv_default_loop(), &read_req, req\->result,
+ &iov, 1, \-1, on_read);
+ }
+ else {
+ fprintf(stderr, "error opening file: %s\en", uv_strerror((int)req\->result));
+ }
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The \fBresult\fP field of a \fBuv_fs_t\fP is the file descriptor in case of the
+\fBuv_fs_open\fP callback. If the file is successfully opened, we start reading it.
+.sp
+uvcat/main.c \- read callback
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void on_read(uv_fs_t *req) {
+ if (req\->result < 0) {
+ fprintf(stderr, "Read error: %s\en", uv_strerror(req\->result));
+ }
+ else if (req\->result == 0) {
+ uv_fs_t close_req;
+ // synchronous
+ uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
+ }
+ else if (req\->result > 0) {
+ iov.len = req\->result;
+ uv_fs_write(uv_default_loop(), &write_req, 1, &iov, 1, \-1, on_write);
+ }
+}
+
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+In the case of a read call, you should pass an \fIinitialized\fP buffer which will
+be filled with data before the read callback is triggered. The \fBuv_fs_*\fP
+operations map almost directly to certain POSIX functions, so EOF is indicated
+in this case by \fBresult\fP being 0. In the case of streams or pipes, the
+\fBUV_EOF\fP constant would have been passed as a status instead.
+.sp
+Here you see a common pattern when writing asynchronous programs. The
+\fBuv_fs_close()\fP call is performed synchronously. \fIUsually tasks which are
+one\-off, or are done as part of the startup or shutdown stage are performed
+synchronously, since we are interested in fast I/O when the program is going
+about its primary task and dealing with multiple I/O sources\fP\&. For solo tasks
+the performance difference usually is negligible and may lead to simpler code.
+.sp
+Filesystem writing is similarly simple using \fBuv_fs_write()\fP\&. \fIYour callback
+will be triggered after the write is complete\fP\&. In our case the callback
+simply drives the next read. Thus read and write proceed in lockstep via
+callbacks.
+.sp
+uvcat/main.c \- write callback
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+void on_write(uv_fs_t *req) {
+ if (req\->result < 0) {
+ fprintf(stderr, "Write error: %s\en", uv_strerror((int)req\->result));
+ }
+ else {
+ uv_fs_read(uv_default_loop(), &read_req, open_req.result, &iov, 1, \-1, on_read);
+ }
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+Due to the way filesystems and disk drives are configured for performance,
+a write that \(aqsucceeds\(aq may not be committed to disk yet.
+.UNINDENT
+.UNINDENT
+.sp
+We set the dominos rolling in \fBmain()\fP:
+.sp
+uvcat/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int main(int argc, char **argv) {
+ uv_fs_open(uv_default_loop(), &open_req, argv[1], O_RDONLY, 0, on_open);
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ uv_fs_req_cleanup(&open_req);
+ uv_fs_req_cleanup(&read_req);
+ uv_fs_req_cleanup(&write_req);
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBuv_fs_req_cleanup()\fP function must always be called on filesystem
+requests to free internal memory allocations in libuv.
+.UNINDENT
+.UNINDENT
+.SS Filesystem operations
+.sp
+All the standard filesystem operations like \fBunlink\fP, \fBrmdir\fP, \fBstat\fP are
+supported asynchronously and have intuitive argument order. They follow the
+same patterns as the read/write/open calls, returning the result in the
+\fBuv_fs_t.result\fP field. The full list:
+.sp
+Filesystem operations
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
+int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb);
+int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
+int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
+int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
+int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
+int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb);
+int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb);
+int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent);
+int uv_fs_opendir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb);
+int uv_fs_closedir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb);
+int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
+int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
+int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
+int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
+int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb);
+int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb);
+int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
+int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
+int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
+int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb);
+int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
+int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
+int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb);
+int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
+int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
+int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Buffers and Streams
+.sp
+The basic I/O handle in libuv is the stream (\fBuv_stream_t\fP). TCP sockets, UDP
+sockets, and pipes for file I/O and IPC are all treated as stream subclasses.
+.sp
+Streams are initialized using custom functions for each subclass, then operated
+upon using
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);
+int uv_read_stop(uv_stream_t*);
+int uv_write(uv_write_t* req, uv_stream_t* handle,
+ const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The stream based functions are simpler to use than the filesystem ones and
+libuv will automatically keep reading from a stream when \fBuv_read_start()\fP is
+called once, until \fBuv_read_stop()\fP is called.
+.sp
+The discrete unit of data is the buffer \-\- \fBuv_buf_t\fP\&. This is simply
+a collection of a pointer to bytes (\fBuv_buf_t.base\fP) and the length
+(\fBuv_buf_t.len\fP). The \fBuv_buf_t\fP is lightweight and passed around by value.
+What does require management is the actual bytes, which have to be allocated
+and freed by the application.
+.sp
+\fBERROR:\fP
+.INDENT 0.0
+.INDENT 3.5
+THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER**
+.UNINDENT
+.UNINDENT
+.sp
+To demonstrate streams we will need to use \fBuv_pipe_t\fP\&. This allows streaming
+local files [2]\&. Here is a simple tee utility using libuv. Doing all operations
+asynchronously shows the power of evented I/O. The two writes won\(aqt block each
+other, but we have to be careful to copy over the buffer data to ensure we don\(aqt
+free a buffer until it has been written.
+.sp
+The program is to be executed as:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+\&./uvtee <output_file>
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+We start off opening pipes on the files we require. libuv pipes to a file are
+opened as bidirectional by default.
+.sp
+uvtee/main.c \- read on pipes
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+int main(int argc, char **argv) {
+ loop = uv_default_loop();
+
+ uv_pipe_init(loop, &stdin_pipe, 0);
+ uv_pipe_open(&stdin_pipe, 0);
+
+ uv_pipe_init(loop, &stdout_pipe, 0);
+ uv_pipe_open(&stdout_pipe, 1);
+
+ uv_fs_t file_req;
+ int fd = uv_fs_open(loop, &file_req, argv[1], O_CREAT | O_RDWR, 0644, NULL);
+ uv_pipe_init(loop, &file_pipe, 0);
+ uv_pipe_open(&file_pipe, fd);
+
+ uv_read_start((uv_stream_t*)&stdin_pipe, alloc_buffer, read_stdin);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The third argument of \fBuv_pipe_init()\fP should be set to 1 for IPC using named
+pipes. This is covered in processes\&. The \fBuv_pipe_open()\fP call
+associates the pipe with the file descriptor, in this case \fB0\fP (standard
+input).
+.sp
+We start monitoring \fBstdin\fP\&. The \fBalloc_buffer\fP callback is invoked as new
+buffers are required to hold incoming data. \fBread_stdin\fP will be called with
+these buffers.
+.sp
+uvtee/main.c \- reading buffers
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
+ *buf = uv_buf_init((char*) malloc(suggested_size), suggested_size);
+}
+
+void read_stdin(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
+ if (nread < 0){
+ if (nread == UV_EOF){
+ // end of file
+ uv_close((uv_handle_t *)&stdin_pipe, NULL);
+ uv_close((uv_handle_t *)&stdout_pipe, NULL);
+ uv_close((uv_handle_t *)&file_pipe, NULL);
+ }
+ } else if (nread > 0) {
+ write_data((uv_stream_t *)&stdout_pipe, nread, *buf, on_stdout_write);
+ write_data((uv_stream_t *)&file_pipe, nread, *buf, on_file_write);
+ }
+
+ // OK to free buffer as write_data copies it.
+ if (buf\->base)
+ free(buf\->base);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The standard \fBmalloc\fP is sufficient here, but you can use any memory allocation
+scheme. For example, node.js uses its own slab allocator which associates
+buffers with V8 objects.
+.sp
+The read callback \fBnread\fP parameter is less than 0 on any error. This error
+might be EOF, in which case we close all the streams, using the generic close
+function \fBuv_close()\fP which deals with the handle based on its internal type.
+Otherwise \fBnread\fP is a non\-negative number and we can attempt to write that
+many bytes to the output streams. Finally remember that buffer allocation and
+deallocation is application responsibility, so we free the data.
+.sp
+The allocation callback may return a buffer with length zero if it fails to
+allocate memory. In this case, the read callback is invoked with error
+UV_ENOBUFS. libuv will continue to attempt to read the stream though, so you
+must explicitly call \fBuv_close()\fP if you want to stop when allocation fails.
+.sp
+The read callback may be called with \fBnread = 0\fP, indicating that at this
+point there is nothing to be read. Most applications will just ignore this.
+.sp
+uvtee/main.c \- Write to pipe
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct {
+ uv_write_t req;
+ uv_buf_t buf;
+} write_req_t;
+
+void free_write_req(uv_write_t *req) {
+ write_req_t *wr = (write_req_t*) req;
+ free(wr\->buf.base);
+ free(wr);
+}
+
+void on_stdout_write(uv_write_t *req, int status) {
+ free_write_req(req);
+}
+
+void on_file_write(uv_write_t *req, int status) {
+ free_write_req(req);
+}
+
+void write_data(uv_stream_t *dest, size_t size, uv_buf_t buf, uv_write_cb cb) {
+ write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
+ req\->buf = uv_buf_init((char*) malloc(size), size);
+ memcpy(req\->buf.base, buf.base, size);
+ uv_write((uv_write_t*) req, (uv_stream_t*)dest, &req\->buf, 1, cb);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBwrite_data()\fP makes a copy of the buffer obtained from read. This buffer
+does not get passed through to the write callback trigged on write completion. To
+get around this we wrap a write request and a buffer in \fBwrite_req_t\fP and
+unwrap it in the callbacks. We make a copy so we can free the two buffers from
+the two calls to \fBwrite_data\fP independently of each other. While acceptable
+for a demo program like this, you\(aqll probably want smarter memory management,
+like reference counted buffers or a pool of buffers in any major application.
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+If your program is meant to be used with other programs it may knowingly or
+unknowingly be writing to a pipe. This makes it susceptible to \fI\%aborting on
+receiving a SIGPIPE\fP\&. It is a good idea to insert:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+signal(SIGPIPE, SIG_IGN)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+in the initialization stages of your application.
+.UNINDENT
+.UNINDENT
+.SS File change events
+.sp
+All modern operating systems provide APIs to put watches on individual files or
+directories and be informed when the files are modified. libuv wraps common
+file change notification libraries [1]\&. This is one of the more
+inconsistent parts of libuv. File change notification systems are themselves
+extremely varied across platforms so getting everything working everywhere is
+difficult. To demonstrate, I\(aqm going to build a simple utility which runs
+a command whenever any of the watched files change:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+\&./onchange <command> <file1> [file2] ...
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The file change notification is started using \fBuv_fs_event_init()\fP:
+.sp
+onchange/main.c \- The setup
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int main(int argc, char **argv) {
+ if (argc <= 2) {
+ fprintf(stderr, "Usage: %s <command> <file1> [file2 ...]\en", argv[0]);
+ return 1;
+ }
+
+ loop = uv_default_loop();
+ command = argv[1];
+
+ while (argc\-\- > 2) {
+ fprintf(stderr, "Adding watch on %s\en", argv[argc]);
+ uv_fs_event_t *fs_event_req = malloc(sizeof(uv_fs_event_t));
+ uv_fs_event_init(loop, fs_event_req);
+ // The recursive flag watches subdirectories too.
+ uv_fs_event_start(fs_event_req, run_command, argv[argc], UV_FS_EVENT_RECURSIVE);
+ }
+
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The third argument is the actual file or directory to monitor. The last
+argument, \fBflags\fP, can be:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+/*
+* Flags to be passed to uv_fs_event_start().
+*/
+enum uv_fs_event_flags {
+ UV_FS_EVENT_WATCH_ENTRY = 1,
+ UV_FS_EVENT_STAT = 2,
+ UV_FS_EVENT_RECURSIVE = 4
+};
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBUV_FS_EVENT_WATCH_ENTRY\fP and \fBUV_FS_EVENT_STAT\fP don\(aqt do anything (yet).
+\fBUV_FS_EVENT_RECURSIVE\fP will start watching subdirectories as well on
+supported platforms.
+.sp
+The callback will receive the following arguments:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+\fBuv_fs_event_t *handle\fP \- The handle. The \fBpath\fP field of the handle
+is the file on which the watch was set.
+.IP 2. 3
+\fBconst char *filename\fP \- If a directory is being monitored, this is the
+file which was changed. Only non\-\fBnull\fP on Linux and Windows. May be \fBnull\fP
+even on those platforms.
+.IP 3. 3
+.INDENT 3.0
+.TP
+.B \fBint flags\fP \- one of \fBUV_RENAME\fP or \fBUV_CHANGE\fP, or a bitwise OR of
+both.
+.UNINDENT
+.IP 4. 3
+\fBint status\fP \- Currently 0.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+In our example we simply print the arguments and run the command using
+\fBsystem()\fP\&.
+.sp
+onchange/main.c \- file change notification callback
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void run_command(uv_fs_event_t *handle, const char *filename, int events, int status) {
+ char path[1024];
+ size_t size = 1023;
+ // Does not handle error if path is longer than 1023.
+ uv_fs_event_getpath(handle, path, &size);
+ path[size] = \(aq\e0\(aq;
+
+ fprintf(stderr, "Change detected in %s: ", path);
+ if (events & UV_RENAME)
+ fprintf(stderr, "renamed");
+ if (events & UV_CHANGE)
+ fprintf(stderr, "changed");
+
+ fprintf(stderr, " %s\en", filename ? filename : "");
+ system(command);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+
+.sp
+.ce
+----
+
+.ce 0
+.sp
+.IP [1] 5
+inotify on Linux, FSEvents on Darwin, kqueue on BSDs,
+ReadDirectoryChangesW on Windows, event ports on Solaris, unsupported on Cygwin
+.IP [2] 5
+see pipes
+.SS Networking
+.sp
+Networking in libuv is not much different from directly using the BSD socket
+interface, some things are easier, all are non\-blocking, but the concepts stay
+the same. In addition libuv offers utility functions to abstract the annoying,
+repetitive and low\-level tasks like setting up sockets using the BSD socket
+structures, DNS lookup, and tweaking various socket parameters.
+.sp
+The \fBuv_tcp_t\fP and \fBuv_udp_t\fP structures are used for network I/O.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The code samples in this chapter exist to show certain libuv APIs. They are
+not examples of good quality code. They leak memory and don\(aqt always close
+connections properly.
+.UNINDENT
+.UNINDENT
+.SS TCP
+.sp
+TCP is a connection oriented, stream protocol and is therefore based on the
+libuv streams infrastructure.
+.SS Server
+.sp
+Server sockets proceed by:
+.INDENT 0.0
+.IP 1. 3
+\fBuv_tcp_init\fP the TCP handle.
+.IP 2. 3
+\fBuv_tcp_bind\fP it.
+.IP 3. 3
+Call \fBuv_listen\fP on the handle to have a callback invoked whenever a new
+connection is established by a client.
+.IP 4. 3
+Use \fBuv_accept\fP to accept the connection.
+.IP 5. 3
+Use stream operations to communicate with the
+client.
+.UNINDENT
+.sp
+Here is a simple echo server
+.sp
+tcp\-echo\-server/main.c \- The listen socket
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ uv_close((uv_handle_t*) client, on_close);
+ }
+}
+
+int main() {
+ loop = uv_default_loop();
+
+ uv_tcp_t server;
+ uv_tcp_init(loop, &server);
+
+ uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr);
+
+ uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0);
+ int r = uv_listen((uv_stream_t*) &server, DEFAULT_BACKLOG, on_new_connection);
+ if (r) {
+ fprintf(stderr, "Listen error %s\en", uv_strerror(r));
+ return 1;
+ }
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+You can see the utility function \fBuv_ip4_addr\fP being used to convert from
+a human readable IP address, port pair to the sockaddr_in structure required by
+the BSD socket APIs. The reverse can be obtained using \fBuv_ip4_name\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+There are \fBuv_ip6_*\fP analogues for the ip4 functions.
+.UNINDENT
+.UNINDENT
+.sp
+Most of the setup functions are synchronous since they are CPU\-bound.
+\fBuv_listen\fP is where we return to libuv\(aqs callback style. The second
+arguments is the backlog queue \-\- the maximum length of queued connections.
+.sp
+When a connection is initiated by clients, the callback is required to set up
+a handle for the client socket and associate the handle using \fBuv_accept\fP\&.
+In this case we also establish interest in reading from this stream.
+.sp
+tcp\-echo\-server/main.c \- Accepting the client
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+ free(buf\->base);
+}
+
+void on_new_connection(uv_stream_t *server, int status) {
+ if (status < 0) {
+ fprintf(stderr, "New connection error %s\en", uv_strerror(status));
+ // error!
+ return;
+ }
+
+ uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
+ uv_tcp_init(loop, client);
+ if (uv_accept(server, (uv_stream_t*) client) == 0) {
+ uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
+ }
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The remaining set of functions is very similar to the streams example and can
+be found in the code. Just remember to call \fBuv_close\fP when the socket isn\(aqt
+required. This can be done even in the \fBuv_listen\fP callback if you are not
+interested in accepting the connection.
+.SS Client
+.sp
+Where you do bind/listen/accept on the server, on the client side it\(aqs simply
+a matter of calling \fBuv_tcp_connect\fP\&. The same \fBuv_connect_cb\fP style
+callback of \fBuv_listen\fP is used by \fBuv_tcp_connect\fP\&. Try:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_tcp_t* socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
+uv_tcp_init(loop, socket);
+
+uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
+
+struct sockaddr_in dest;
+uv_ip4_addr("127.0.0.1", 80, &dest);
+
+uv_tcp_connect(connect, socket, (const struct sockaddr*)&dest, on_connect);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+where \fBon_connect\fP will be called after the connection is established. The
+callback receives the \fBuv_connect_t\fP struct, which has a member \fB\&.handle\fP
+pointing to the socket.
+.SS UDP
+.sp
+The \fI\%User Datagram Protocol\fP offers connectionless, unreliable network
+communication. Hence libuv doesn\(aqt offer a stream. Instead libuv provides
+non\-blocking UDP support via the \fIuv_udp_t\fP handle (for receiving) and
+\fIuv_udp_send_t\fP request (for sending) and related functions. That said, the
+actual API for reading/writing is very similar to normal stream reads. To look
+at how UDP can be used, the example shows the first stage of obtaining an IP
+address from a \fI\%DHCP\fP server \-\- DHCP Discover.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+You will have to run \fIudp\-dhcp\fP as \fBroot\fP since it uses well known port
+numbers below 1024.
+.UNINDENT
+.UNINDENT
+.sp
+udp\-dhcp/main.c \- Setup and send UDP packets
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+uv_loop_t *loop;
+uv_udp_t send_socket;
+uv_udp_t recv_socket;
+
+int main() {
+ loop = uv_default_loop();
+
+ uv_udp_init(loop, &recv_socket);
+ struct sockaddr_in recv_addr;
+ uv_ip4_addr("0.0.0.0", 68, &recv_addr);
+ uv_udp_bind(&recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
+ uv_udp_recv_start(&recv_socket, alloc_buffer, on_read);
+
+ uv_udp_init(loop, &send_socket);
+ struct sockaddr_in broadcast_addr;
+ uv_ip4_addr("0.0.0.0", 0, &broadcast_addr);
+ uv_udp_bind(&send_socket, (const struct sockaddr *)&broadcast_addr, 0);
+ uv_udp_set_broadcast(&send_socket, 1);
+
+ uv_udp_send_t send_req;
+ uv_buf_t discover_msg = make_discover_msg();
+
+ struct sockaddr_in send_addr;
+ uv_ip4_addr("255.255.255.255", 67, &send_addr);
+ uv_udp_send(&send_req, &send_socket, &discover_msg, 1, (const struct sockaddr *)&send_addr, on_send);
+
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The IP address \fB0.0.0.0\fP is used to bind to all interfaces. The IP
+address \fB255.255.255.255\fP is a broadcast address meaning that packets
+will be sent to all interfaces on the subnet. port \fB0\fP means that the OS
+randomly assigns a port.
+.UNINDENT
+.UNINDENT
+.sp
+First we setup the receiving socket to bind on all interfaces on port 68 (DHCP
+client) and start a read on it. This will read back responses from any DHCP
+server that replies. We use the UV_UDP_REUSEADDR flag to play nice with any
+other system DHCP clients that are running on this computer on the same port.
+Then we setup a similar send socket and use \fBuv_udp_send\fP to send
+a \fIbroadcast message\fP on port 67 (DHCP server).
+.sp
+It is \fBnecessary\fP to set the broadcast flag, otherwise you will get an
+\fBEACCES\fP error [1]\&. The exact message being sent is not relevant to this
+book and you can study the code if you are interested. As usual the read and
+write callbacks will receive a status code of < 0 if something went wrong.
+.sp
+Since UDP sockets are not connected to a particular peer, the read callback
+receives an extra parameter about the sender of the packet.
+.sp
+\fBnread\fP may be zero if there is no more data to be read. If \fBaddr\fP is NULL,
+it indicates there is nothing to read (the callback shouldn\(aqt do anything), if
+not NULL, it indicates that an empty datagram was received from the host at
+\fBaddr\fP\&. The \fBflags\fP parameter may be \fBUV_UDP_PARTIAL\fP if the buffer
+provided by your allocator was not large enough to hold the data. \fIIn this case
+the OS will discard the data that could not fit\fP (That\(aqs UDP for you!).
+.sp
+udp\-dhcp/main.c \- Reading packets
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void on_read(uv_udp_t *req, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags) {
+ if (nread < 0) {
+ fprintf(stderr, "Read error %s\en", uv_err_name(nread));
+ uv_close((uv_handle_t*) req, NULL);
+ free(buf\->base);
+ return;
+ }
+
+ char sender[17] = { 0 };
+ uv_ip4_name((const struct sockaddr_in*) addr, sender, 16);
+ fprintf(stderr, "Recv from %s\en", sender);
+
+ // ... DHCP specific code
+ unsigned int *as_integer = (unsigned int*)buf\->base;
+ unsigned int ipbin = ntohl(as_integer[4]);
+ unsigned char ip[4] = {0};
+ int i;
+ for (i = 0; i < 4; i++)
+ ip[i] = (ipbin >> i*8) & 0xff;
+ fprintf(stderr, "Offered IP %d.%d.%d.%d\en", ip[3], ip[2], ip[1], ip[0]);
+
+ free(buf\->base);
+ uv_udp_recv_stop(req);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS UDP Options
+.SS Time\-to\-live
+.sp
+The TTL of packets sent on the socket can be changed using \fBuv_udp_set_ttl\fP\&.
+.SS IPv6 stack only
+.sp
+IPv6 sockets can be used for both IPv4 and IPv6 communication. If you want to
+restrict the socket to IPv6 only, pass the \fBUV_UDP_IPV6ONLY\fP flag to
+\fBuv_udp_bind\fP [2]\&.
+.SS Multicast
+.sp
+A socket can (un)subscribe to a multicast group using:
+.sp
+where \fBmembership\fP is \fBUV_JOIN_GROUP\fP or \fBUV_LEAVE_GROUP\fP\&.
+.sp
+The concepts of multicasting are nicely explained in \fI\%this guide\fP\&.
+.sp
+Local loopback of multicast packets is enabled by default [3], use
+\fBuv_udp_set_multicast_loop\fP to switch it off.
+.sp
+The packet time\-to\-live for multicast packets can be changed using
+\fBuv_udp_set_multicast_ttl\fP\&.
+.SS Querying DNS
+.sp
+libuv provides asynchronous DNS resolution. For this it provides its own
+\fBgetaddrinfo\fP replacement [4]\&. In the callback you can
+perform normal socket operations on the retrieved addresses. Let\(aqs connect to
+Freenode to see an example of DNS resolution.
+.sp
+dns/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+int main() {
+ loop = uv_default_loop();
+
+ struct addrinfo hints;
+ hints.ai_family = PF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = 0;
+
+ uv_getaddrinfo_t resolver;
+ fprintf(stderr, "irc.freenode.net is... ");
+ int r = uv_getaddrinfo(loop, &resolver, on_resolved, "irc.freenode.net", "6667", &hints);
+
+ if (r) {
+ fprintf(stderr, "getaddrinfo call error %s\en", uv_err_name(r));
+ return 1;
+ }
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+If \fBuv_getaddrinfo\fP returns non\-zero, something went wrong in the setup and
+your callback won\(aqt be invoked at all. All arguments can be freed immediately
+after \fBuv_getaddrinfo\fP returns. The \fIhostname\fP, \fIservname\fP and \fIhints\fP
+structures are documented in \fI\%the getaddrinfo man page\fP\&. The
+callback can be \fBNULL\fP in which case the function will run synchronously.
+.sp
+In the resolver callback, you can pick any IP from the linked list of \fBstruct
+addrinfo(s)\fP\&. This also demonstrates \fBuv_tcp_connect\fP\&. It is necessary to
+call \fBuv_freeaddrinfo\fP in the callback.
+.sp
+dns/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+void on_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res) {
+ if (status < 0) {
+ fprintf(stderr, "getaddrinfo callback error %s\en", uv_err_name(status));
+ return;
+ }
+
+ char addr[17] = {\(aq\e0\(aq};
+ uv_ip4_name((struct sockaddr_in*) res\->ai_addr, addr, 16);
+ fprintf(stderr, "%s\en", addr);
+
+ uv_connect_t *connect_req = (uv_connect_t*) malloc(sizeof(uv_connect_t));
+ uv_tcp_t *socket = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
+ uv_tcp_init(loop, socket);
+
+ uv_tcp_connect(connect_req, socket, (const struct sockaddr*) res\->ai_addr, on_connect);
+
+ uv_freeaddrinfo(res);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+libuv also provides the inverse \fI\%uv_getnameinfo\fP\&.
+.SS Network interfaces
+.sp
+Information about the system\(aqs network interfaces can be obtained through libuv
+using \fBuv_interface_addresses\fP\&. This simple program just prints out all the
+interface details so you get an idea of the fields that are available. This is
+useful to allow your service to bind to IP addresses when it starts.
+.sp
+interfaces/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+#include <uv.h>
+
+int main() {
+ char buf[512];
+ uv_interface_address_t *info;
+ int count, i;
+
+ uv_interface_addresses(&info, &count);
+ i = count;
+
+ printf("Number of interfaces: %d\en", count);
+ while (i\-\-) {
+ uv_interface_address_t interface = info[i];
+
+ printf("Name: %s\en", interface.name);
+ printf("Internal? %s\en", interface.is_internal ? "Yes" : "No");
+
+ if (interface.address.address4.sin_family == AF_INET) {
+ uv_ip4_name(&interface.address.address4, buf, sizeof(buf));
+ printf("IPv4 address: %s\en", buf);
+ }
+ else if (interface.address.address4.sin_family == AF_INET6) {
+ uv_ip6_name(&interface.address.address6, buf, sizeof(buf));
+ printf("IPv6 address: %s\en", buf);
+ }
+
+ printf("\en");
+ }
+
+ uv_free_interface_addresses(info, count);
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBis_internal\fP is true for loopback interfaces. Note that if a physical
+interface has multiple IPv4/IPv6 addresses, the name will be reported multiple
+times, with each address being reported once.
+
+.sp
+.ce
+----
+
+.ce 0
+.sp
+.IP [1] 5
+\fI\%https://beej.us/guide/bgnet/html/#broadcast\-packetshello\-world\fP
+.IP [2] 5
+on Windows only supported on Windows Vista and later.
+.IP [3] 5
+\fI\%https://www.tldp.org/HOWTO/Multicast\-HOWTO\-6.html#ss6.1\fP
+.IP [4] 5
+libuv use the system \fBgetaddrinfo\fP in the libuv threadpool. libuv
+v0.8.0 and earlier also included \fI\%c\-ares\fP as an alternative, but this has been
+removed in v0.9.0.
+.SS Threads
+.sp
+Wait a minute? Why are we on threads? Aren\(aqt event loops supposed to be \fBthe
+way\fP to do \fIweb\-scale programming\fP? Well... no. Threads are still the medium in
+which processors do their jobs. Threads are therefore mighty useful sometimes, even
+though you might have to wade through various synchronization primitives.
+.sp
+Threads are used internally to fake the asynchronous nature of all of the system
+calls. libuv also uses threads to allow you, the application, to perform a task
+asynchronously that is actually blocking, by spawning a thread and collecting
+the result when it is done.
+.sp
+Today there are two predominant thread libraries: the Windows threads
+implementation and POSIX\(aqs \fI\%pthreads(7)\fP\&. libuv\(aqs thread API is analogous to
+the pthreads API and often has similar semantics.
+.sp
+A notable aspect of libuv\(aqs thread facilities is that it is a self contained
+section within libuv. Whereas other features intimately depend on the event
+loop and callback principles, threads are complete agnostic, they block as
+required, signal errors directly via return values, and, as shown in the
+\fI\%first example\fP, don\(aqt even require a running
+event loop.
+.sp
+libuv\(aqs thread API is also very limited since the semantics and syntax of
+threads are different on all platforms, with different levels of completeness.
+.sp
+This chapter makes the following assumption: \fBThere is only one event loop,
+running in one thread (the main thread)\fP\&. No other thread interacts
+with the event loop (except using \fBuv_async_send\fP).
+.SS Core thread operations
+.sp
+There isn\(aqt much here, you just start a thread using \fBuv_thread_create()\fP and
+wait for it to close using \fBuv_thread_join()\fP\&.
+.sp
+thread\-create/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int main() {
+ int tracklen = 10;
+ uv_thread_t hare_id;
+ uv_thread_t tortoise_id;
+ uv_thread_create(&hare_id, hare, &tracklen);
+ uv_thread_create(&tortoise_id, tortoise, &tracklen);
+
+ uv_thread_join(&hare_id);
+ uv_thread_join(&tortoise_id);
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBTIP:\fP
+.INDENT 0.0
+.INDENT 3.5
+\fBuv_thread_t\fP is just an alias for \fBpthread_t\fP on Unix, but this is an
+implementation detail, avoid depending on it to always be true.
+.UNINDENT
+.UNINDENT
+.sp
+The second parameter is the function which will serve as the entry point for
+the thread, the last parameter is a \fBvoid *\fP argument which can be used to pass
+custom parameters to the thread. The function \fBhare\fP will now run in a separate
+thread, scheduled pre\-emptively by the operating system:
+.sp
+thread\-create/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void hare(void *arg) {
+ int tracklen = *((int *) arg);
+ while (tracklen) {
+ tracklen\-\-;
+ sleep(1);
+ fprintf(stderr, "Hare ran another step\en");
+ }
+ fprintf(stderr, "Hare done running!\en");
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Unlike \fBpthread_join()\fP which allows the target thread to pass back a value to
+the calling thread using a second parameter, \fBuv_thread_join()\fP does not. To
+send values use \fI\%Inter\-thread communication\fP\&.
+.SS Synchronization Primitives
+.sp
+This section is purposely spartan. This book is not about threads, so I only
+catalogue any surprises in the libuv APIs here. For the rest you can look at
+the \fI\%pthreads(7)\fP man pages.
+.SS Mutexes
+.sp
+The mutex functions are a \fBdirect\fP map to the pthread equivalents.
+.sp
+libuv mutex functions
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int uv_mutex_init(uv_mutex_t* handle);
+int uv_mutex_init_recursive(uv_mutex_t* handle);
+void uv_mutex_destroy(uv_mutex_t* handle);
+void uv_mutex_lock(uv_mutex_t* handle);
+int uv_mutex_trylock(uv_mutex_t* handle);
+void uv_mutex_unlock(uv_mutex_t* handle);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The \fBuv_mutex_init()\fP, \fBuv_mutex_init_recursive()\fP and \fBuv_mutex_trylock()\fP
+functions will return 0 on success, and an error code otherwise.
+.sp
+If \fIlibuv\fP has been compiled with debugging enabled, \fBuv_mutex_destroy()\fP,
+\fBuv_mutex_lock()\fP and \fBuv_mutex_unlock()\fP will \fBabort()\fP on error.
+Similarly \fBuv_mutex_trylock()\fP will abort if the error is anything \fIother
+than\fP \fBEAGAIN\fP or \fBEBUSY\fP\&.
+.sp
+Recursive mutexes are supported, but you should not rely on them. Also, they
+should not be used with \fBuv_cond_t\fP variables.
+.sp
+The default BSD mutex implementation will raise an error if a thread which has
+locked a mutex attempts to lock it again. For example, a construct like:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_mutex_init(a_mutex);
+uv_mutex_lock(a_mutex);
+uv_thread_create(thread_id, entry, (void *)a_mutex);
+uv_mutex_lock(a_mutex);
+// more things here
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+can be used to wait until another thread initializes some stuff and then
+unlocks \fBa_mutex\fP but will lead to your program crashing if in debug mode, or
+return an error in the second call to \fBuv_mutex_lock()\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Mutexes on Windows are always recursive.
+.UNINDENT
+.UNINDENT
+.SS Locks
+.sp
+Read\-write locks are a more granular access mechanism. Two readers can access
+shared memory at the same time. A writer may not acquire the lock when it is
+held by a reader. A reader or writer may not acquire a lock when a writer is
+holding it. Read\-write locks are frequently used in databases. Here is a toy
+example.
+.sp
+locks/main.c \- simple rwlocks
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+#include <uv.h>
+
+uv_barrier_t blocker;
+uv_rwlock_t numlock;
+int shared_num;
+
+void reader(void *n)
+{
+ int num = *(int *)n;
+ int i;
+ for (i = 0; i < 20; i++) {
+ uv_rwlock_rdlock(&numlock);
+ printf("Reader %d: acquired lock\en", num);
+ printf("Reader %d: shared num = %d\en", num, shared_num);
+ uv_rwlock_rdunlock(&numlock);
+ printf("Reader %d: released lock\en", num);
+ }
+ uv_barrier_wait(&blocker);
+}
+
+void writer(void *n)
+{
+ int num = *(int *)n;
+ int i;
+ for (i = 0; i < 20; i++) {
+ uv_rwlock_wrlock(&numlock);
+ printf("Writer %d: acquired lock\en", num);
+ shared_num++;
+ printf("Writer %d: incremented shared num = %d\en", num, shared_num);
+ uv_rwlock_wrunlock(&numlock);
+ printf("Writer %d: released lock\en", num);
+ }
+ uv_barrier_wait(&blocker);
+}
+
+int main()
+{
+ uv_barrier_init(&blocker, 4);
+
+ shared_num = 0;
+ uv_rwlock_init(&numlock);
+
+ uv_thread_t threads[3];
+
+ int thread_nums[] = {1, 2, 1};
+ uv_thread_create(&threads[0], reader, &thread_nums[0]);
+ uv_thread_create(&threads[1], reader, &thread_nums[1]);
+
+ uv_thread_create(&threads[2], writer, &thread_nums[2]);
+
+ uv_barrier_wait(&blocker);
+ uv_barrier_destroy(&blocker);
+
+ uv_rwlock_destroy(&numlock);
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Run this and observe how the readers will sometimes overlap. In case of
+multiple writers, schedulers will usually give them higher priority, so if you
+add two writers, you\(aqll see that both writers tend to finish first before the
+readers get a chance again.
+.sp
+We also use barriers in the above example so that the main thread can wait for
+all readers and writers to indicate they have ended.
+.SS Others
+.sp
+libuv also supports \fI\%semaphores\fP, \fI\%condition variables\fP and \fI\%barriers\fP with APIs
+very similar to their pthread counterparts.
+.sp
+In addition, libuv provides a convenience function \fBuv_once()\fP\&. Multiple
+threads can attempt to call \fBuv_once()\fP with a given guard and a function
+pointer, \fBonly the first one will win, the function will be called once and
+only once\fP:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+/* Initialize guard */
+static uv_once_t once_only = UV_ONCE_INIT;
+
+int i = 0;
+
+void increment() {
+ i++;
+}
+
+void thread1() {
+ /* ... work */
+ uv_once(once_only, increment);
+}
+
+void thread2() {
+ /* ... work */
+ uv_once(once_only, increment);
+}
+
+int main() {
+ /* ... spawn threads */
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+After all threads are done, \fBi == 1\fP\&.
+.sp
+libuv v0.11.11 onwards also added a \fBuv_key_t\fP struct and \fI\%api\fP for
+thread\-local storage.
+.SS libuv work queue
+.sp
+\fBuv_queue_work()\fP is a convenience function that allows an application to run
+a task in a separate thread, and have a callback that is triggered when the
+task is done. A seemingly simple function, what makes \fBuv_queue_work()\fP
+tempting is that it allows potentially any third\-party libraries to be used
+with the event\-loop paradigm. When you use event loops, it is \fIimperative to
+make sure that no function which runs periodically in the loop thread blocks
+when performing I/O or is a serious CPU hog\fP, because this means that the loop
+slows down and events are not being handled at full capacity.
+.sp
+However, a lot of existing code out there features blocking functions (for example
+a routine which performs I/O under the hood) to be used with threads if you
+want responsiveness (the classic \(aqone thread per client\(aq server model), and
+getting them to play with an event loop library generally involves rolling your
+own system of running the task in a separate thread. libuv just provides
+a convenient abstraction for this.
+.sp
+Here is a simple example inspired by \fI\%node.js is cancer\fP\&. We are going to
+calculate fibonacci numbers, sleeping a bit along the way, but run it in
+a separate thread so that the blocking and CPU bound task does not prevent the
+event loop from performing other activities.
+.sp
+queue\-work/main.c \- lazy fibonacci
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void fib(uv_work_t *req) {
+ int n = *(int *) req\->data;
+ if (random() % 2)
+ sleep(1);
+ else
+ sleep(3);
+ long fib = fib_(n);
+ fprintf(stderr, "%dth fibonacci is %lu\en", n, fib);
+}
+
+void after_fib(uv_work_t *req, int status) {
+ fprintf(stderr, "Done calculating %dth fibonacci\en", *(int *) req\->data);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The actual task function is simple, nothing to show that it is going to be
+run in a separate thread. The \fBuv_work_t\fP structure is the clue. You can pass
+arbitrary data through it using the \fBvoid* data\fP field and use it to
+communicate to and from the thread. But be sure you are using proper locks if
+you are changing things while both threads may be running.
+.sp
+The trigger is \fBuv_queue_work\fP:
+.sp
+queue\-work/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int main() {
+ loop = uv_default_loop();
+
+ int data[FIB_UNTIL];
+ uv_work_t req[FIB_UNTIL];
+ int i;
+ for (i = 0; i < FIB_UNTIL; i++) {
+ data[i] = i;
+ req[i].data = (void *) &data[i];
+ uv_queue_work(loop, &req[i], fib, after_fib);
+ }
+
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The thread function will be launched in a separate thread, passed the
+\fBuv_work_t\fP structure and once the function returns, the \fIafter\fP function
+will be called on the thread the event loop is running in. It will be passed
+the same structure.
+.sp
+For writing wrappers to blocking libraries, a common pattern
+is to use a baton to exchange data.
+.sp
+Since libuv version \fI0.9.4\fP an additional function, \fBuv_cancel()\fP, is
+available. This allows you to cancel tasks on the libuv work queue. Only tasks
+that \fIare yet to be started\fP can be cancelled. If a task has \fIalready started
+executing, or it has finished executing\fP, \fBuv_cancel()\fP \fBwill fail\fP\&.
+.sp
+\fBuv_cancel()\fP is useful to cleanup pending tasks if the user requests
+termination. For example, a music player may queue up multiple directories to
+be scanned for audio files. If the user terminates the program, it should quit
+quickly and not wait until all pending requests are run.
+.sp
+Let\(aqs modify the fibonacci example to demonstrate \fBuv_cancel()\fP\&. We first set
+up a signal handler for termination.
+.sp
+queue\-cancel/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int main() {
+ loop = uv_default_loop();
+
+ int data[FIB_UNTIL];
+ int i;
+ for (i = 0; i < FIB_UNTIL; i++) {
+ data[i] = i;
+ fib_reqs[i].data = (void *) &data[i];
+ uv_queue_work(loop, &fib_reqs[i], fib, after_fib);
+ }
+
+ uv_signal_t sig;
+ uv_signal_init(loop, &sig);
+ uv_signal_start(&sig, signal_handler, SIGINT);
+
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+When the user triggers the signal by pressing \fBCtrl+C\fP we send
+\fBuv_cancel()\fP to all the workers. \fBuv_cancel()\fP will return \fB0\fP for those that are already executing or finished.
+.sp
+queue\-cancel/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void signal_handler(uv_signal_t *req, int signum)
+{
+ printf("Signal received!\en");
+ int i;
+ for (i = 0; i < FIB_UNTIL; i++) {
+ uv_cancel((uv_req_t*) &fib_reqs[i]);
+ }
+ uv_signal_stop(req);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+For tasks that do get cancelled successfully, the \fIafter\fP function is called
+with \fBstatus\fP set to \fBUV_ECANCELED\fP\&.
+.sp
+queue\-cancel/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void after_fib(uv_work_t *req, int status) {
+ if (status == UV_ECANCELED)
+ fprintf(stderr, "Calculation of %d cancelled.\en", *(int *) req\->data);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBuv_cancel()\fP can also be used with \fBuv_fs_t\fP and \fBuv_getaddrinfo_t\fP
+requests. For the filesystem family of functions, \fBuv_fs_t.errorno\fP will be
+set to \fBUV_ECANCELED\fP\&.
+.sp
+\fBTIP:\fP
+.INDENT 0.0
+.INDENT 3.5
+A well designed program would have a way to terminate long running workers
+that have already started executing. Such a worker could periodically check
+for a variable that only the main process sets to signal termination.
+.UNINDENT
+.UNINDENT
+.SS Inter\-thread communication
+.sp
+Sometimes you want various threads to actually send each other messages \fIwhile\fP
+they are running. For example you might be running some long duration task in
+a separate thread (perhaps using \fBuv_queue_work\fP) but want to notify progress
+to the main thread. This is a simple example of having a download manager
+informing the user of the status of running downloads.
+.sp
+progress/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_loop_t *loop;
+uv_async_t async;
+
+int main() {
+ loop = uv_default_loop();
+
+ uv_work_t req;
+ int size = 10240;
+ req.data = (void*) &size;
+
+ uv_async_init(loop, &async, print_progress);
+ uv_queue_work(loop, &req, fake_download, after);
+
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The async thread communication works \fIon loops\fP so although any thread can be
+the message sender, only threads with libuv loops can be receivers (or rather
+the loop is the receiver). libuv will invoke the callback (\fBprint_progress\fP)
+with the async watcher whenever it receives a message.
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+It is important to realize that since the message send is \fIasync\fP, the callback
+may be invoked immediately after \fBuv_async_send\fP is called in another
+thread, or it may be invoked after some time. libuv may also combine
+multiple calls to \fBuv_async_send\fP and invoke your callback only once. The
+only guarantee that libuv makes is \-\- The callback function is called \fIat
+least once\fP after the call to \fBuv_async_send\fP\&. If you have no pending
+calls to \fBuv_async_send\fP, the callback won\(aqt be called. If you make two
+or more calls, and libuv hasn\(aqt had a chance to run the callback yet, it
+\fImay\fP invoke your callback \fIonly once\fP for the multiple invocations of
+\fBuv_async_send\fP\&. Your callback will never be called twice for just one
+event.
+.UNINDENT
+.UNINDENT
+.sp
+progress/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+double percentage;
+
+void fake_download(uv_work_t *req) {
+ int size = *((int*) req\->data);
+ int downloaded = 0;
+ while (downloaded < size) {
+ percentage = downloaded*100.0/size;
+ async.data = (void*) &percentage;
+ uv_async_send(&async);
+
+ sleep(1);
+ downloaded += (200+random())%1000; // can only download max 1000bytes/sec,
+ // but at least a 200;
+ }
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+In the download function, we modify the progress indicator and queue the message
+for delivery with \fBuv_async_send\fP\&. Remember: \fBuv_async_send\fP is also
+non\-blocking and will return immediately.
+.sp
+progress/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void print_progress(uv_async_t *handle) {
+ double percentage = *((double*) handle\->data);
+ fprintf(stderr, "Downloaded %.2f%%\en", percentage);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The callback is a standard libuv pattern, extracting the data from the watcher.
+.sp
+Finally it is important to remember to clean up the watcher.
+.sp
+progress/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void after(uv_work_t *req, int status) {
+ fprintf(stderr, "Download complete\en");
+ uv_close((uv_handle_t*) &async, NULL);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+After this example, which showed the abuse of the \fBdata\fP field, \fI\%bnoordhuis\fP
+pointed out that using the \fBdata\fP field is not thread safe, and
+\fBuv_async_send()\fP is actually only meant to wake up the event loop. Use
+a mutex or rwlock to ensure accesses are performed in the right order.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+mutexes and rwlocks \fBDO NOT\fP work inside a signal handler, whereas
+\fBuv_async_send\fP does.
+.UNINDENT
+.UNINDENT
+.sp
+One use case where \fBuv_async_send\fP is required is when interoperating with
+libraries that require thread affinity for their functionality. For example in
+node.js, a v8 engine instance, contexts and its objects are bound to the thread
+that the v8 instance was started in. Interacting with v8 data structures from
+another thread can lead to undefined results. Now consider some node.js module
+which binds a third party library. It may go something like this:
+.INDENT 0.0
+.IP 1. 3
+In node, the third party library is set up with a JavaScript callback to be
+invoked for more information:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+var lib = require(\(aqlib\(aq);
+lib.on_progress(function() {
+ console.log("Progress");
+});
+
+lib.do();
+
+// do other stuff
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 2. 3
+\fBlib.do\fP is supposed to be non\-blocking but the third party lib is
+blocking, so the binding uses \fBuv_queue_work\fP\&.
+.IP 3. 3
+The actual work being done in a separate thread wants to invoke the progress
+callback, but cannot directly call into v8 to interact with JavaScript. So
+it uses \fBuv_async_send\fP\&.
+.IP 4. 3
+The async callback, invoked in the main loop thread, which is the v8 thread,
+then interacts with v8 to invoke the JavaScript callback.
+.UNINDENT
+
+.sp
+.ce
+----
+
+.ce 0
+.sp
+.SS Processes
+.sp
+libuv offers considerable child process management, abstracting the platform
+differences and allowing communication with the child process using streams or
+named pipes.
+.sp
+A common idiom in Unix is for every process to do one thing and do it well. In
+such a case, a process often uses multiple child processes to achieve tasks
+(similar to using pipes in shells). A multi\-process model with messages
+may also be easier to reason about compared to one with threads and shared
+memory.
+.sp
+A common refrain against event\-based programs is that they cannot take
+advantage of multiple cores in modern computers. In a multi\-threaded program
+the kernel can perform scheduling and assign different threads to different
+cores, improving performance. But an event loop has only one thread. The
+workaround can be to launch multiple processes instead, with each process
+running an event loop, and each process getting assigned to a separate CPU
+core.
+.SS Spawning child processes
+.sp
+The simplest case is when you simply want to launch a process and know when it
+exits. This is achieved using \fBuv_spawn\fP\&.
+.sp
+spawn/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_loop_t *loop;
+uv_process_t child_req;
+uv_process_options_t options;
+int main() {
+ loop = uv_default_loop();
+
+ char* args[3];
+ args[0] = "mkdir";
+ args[1] = "test\-dir";
+ args[2] = NULL;
+
+ options.exit_cb = on_exit;
+ options.file = "mkdir";
+ options.args = args;
+
+ int r;
+ if ((r = uv_spawn(loop, &child_req, &options))) {
+ fprintf(stderr, "%s\en", uv_strerror(r));
+ return 1;
+ } else {
+ fprintf(stderr, "Launched process with ID %d\en", child_req.pid);
+ }
+
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+\fBoptions\fP is implicitly initialized with zeros since it is a global
+variable. If you change \fBoptions\fP to a local variable, remember to
+initialize it to null out all unused fields:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_process_options_t options = {0};
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+The \fBuv_process_t\fP struct only acts as the handle, all options are set via
+\fBuv_process_options_t\fP\&. To simply launch a process, you need to set only the
+\fBfile\fP and \fBargs\fP fields. \fBfile\fP is the program to execute. Since
+\fBuv_spawn\fP uses \fI\%execvp(3)\fP internally, there is no need to supply the full
+path. Finally as per underlying conventions, \fBthe arguments array has to be
+one larger than the number of arguments, with the last element being NULL\fP\&.
+.sp
+After the call to \fBuv_spawn\fP, \fBuv_process_t.pid\fP will contain the process
+ID of the child process.
+.sp
+The exit callback will be invoked with the \fIexit status\fP and the type of \fIsignal\fP
+which caused the exit.
+.sp
+spawn/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+void on_exit(uv_process_t *req, int64_t exit_status, int term_signal) {
+ fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\en", exit_status, term_signal);
+ uv_close((uv_handle_t*) req, NULL);
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+It is \fBrequired\fP to close the process watcher after the process exits.
+.SS Changing process parameters
+.sp
+Before the child process is launched you can control the execution environment
+using fields in \fBuv_process_options_t\fP\&.
+.SS Change execution directory
+.sp
+Set \fBuv_process_options_t.cwd\fP to the corresponding directory.
+.SS Set environment variables
+.sp
+\fBuv_process_options_t.env\fP is a null\-terminated array of strings, each of the
+form \fBVAR=VALUE\fP used to set up the environment variables for the process. Set
+this to \fBNULL\fP to inherit the environment from the parent (this) process.
+.SS Option flags
+.sp
+Setting \fBuv_process_options_t.flags\fP to a bitwise OR of the following flags,
+modifies the child process behaviour:
+.INDENT 0.0
+.IP \(bu 2
+\fBUV_PROCESS_SETUID\fP \- sets the child\(aqs execution user ID to \fBuv_process_options_t.uid\fP\&.
+.IP \(bu 2
+\fBUV_PROCESS_SETGID\fP \- sets the child\(aqs execution group ID to \fBuv_process_options_t.gid\fP\&.
+.UNINDENT
+.sp
+Changing the UID/GID is only supported on Unix, \fBuv_spawn\fP will fail on
+Windows with \fBUV_ENOTSUP\fP\&.
+.INDENT 0.0
+.IP \(bu 2
+\fBUV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS\fP \- No quoting or escaping of
+\fBuv_process_options_t.args\fP is done on Windows. Ignored on Unix.
+.IP \(bu 2
+\fBUV_PROCESS_DETACHED\fP \- Starts the child process in a new session, which
+will keep running after the parent process exits. See example below.
+.UNINDENT
+.SS Detaching processes
+.sp
+Passing the flag \fBUV_PROCESS_DETACHED\fP can be used to launch daemons, or
+child processes which are independent of the parent so that the parent exiting
+does not affect it.
+.sp
+detach/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int main() {
+ loop = uv_default_loop();
+
+ char* args[3];
+ args[0] = "sleep";
+ args[1] = "100";
+ args[2] = NULL;
+
+ options.exit_cb = NULL;
+ options.file = "sleep";
+ options.args = args;
+ options.flags = UV_PROCESS_DETACHED;
+
+ int r;
+ if ((r = uv_spawn(loop, &child_req, &options))) {
+ fprintf(stderr, "%s\en", uv_strerror(r));
+ return 1;
+ }
+ fprintf(stderr, "Launched sleep with PID %d\en", child_req.pid);
+ uv_unref((uv_handle_t*) &child_req);
+
+ return uv_run(loop, UV_RUN_DEFAULT);
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Just remember that the handle is still monitoring the child, so your program
+won\(aqt exit. Use \fBuv_unref()\fP if you want to be more \fIfire\-and\-forget\fP\&.
+.SS Sending signals to processes
+.sp
+libuv wraps the standard \fBkill(2)\fP system call on Unix and implements one
+with similar semantics on Windows, with \fIone caveat\fP: all of \fBSIGTERM\fP,
+\fBSIGINT\fP and \fBSIGKILL\fP, lead to termination of the process. The signature
+of \fBuv_kill\fP is:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_err_t uv_kill(int pid, int signum);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+For processes started using libuv, you may use \fBuv_process_kill\fP instead,
+which accepts the \fBuv_process_t\fP watcher as the first argument, rather than
+the pid. In this case, \fBremember to call\fP \fBuv_close\fP on the watcher.
+.SS Signals
+.sp
+libuv provides wrappers around Unix signals with \fI\%some Windows support\fP as well.
+.sp
+Use \fBuv_signal_init()\fP to initialize
+a handle and associate it with a loop. To listen for particular signals on
+that handler, use \fBuv_signal_start()\fP with the handler function. Each handler
+can only be associated with one signal number, with subsequent calls to
+\fBuv_signal_start()\fP overwriting earlier associations. Use \fBuv_signal_stop()\fP to
+stop watching. Here is a small example demonstrating the various possibilities:
+.sp
+signal/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <uv.h>
+
+uv_loop_t* create_loop()
+{
+ uv_loop_t *loop = malloc(sizeof(uv_loop_t));
+ if (loop) {
+ uv_loop_init(loop);
+ }
+ return loop;
+}
+
+void signal_handler(uv_signal_t *handle, int signum)
+{
+ printf("Signal received: %d\en", signum);
+ uv_signal_stop(handle);
+}
+
+// two signal handlers in one loop
+void thread1_worker(void *userp)
+{
+ uv_loop_t *loop1 = create_loop();
+
+ uv_signal_t sig1a, sig1b;
+ uv_signal_init(loop1, &sig1a);
+ uv_signal_start(&sig1a, signal_handler, SIGUSR1);
+
+ uv_signal_init(loop1, &sig1b);
+ uv_signal_start(&sig1b, signal_handler, SIGUSR1);
+
+ uv_run(loop1, UV_RUN_DEFAULT);
+}
+
+// two signal handlers, each in its own loop
+void thread2_worker(void *userp)
+{
+ uv_loop_t *loop2 = create_loop();
+ uv_loop_t *loop3 = create_loop();
+
+ uv_signal_t sig2;
+ uv_signal_init(loop2, &sig2);
+ uv_signal_start(&sig2, signal_handler, SIGUSR1);
+
+ uv_signal_t sig3;
+ uv_signal_init(loop3, &sig3);
+ uv_signal_start(&sig3, signal_handler, SIGUSR1);
+
+ while (uv_run(loop2, UV_RUN_NOWAIT) || uv_run(loop3, UV_RUN_NOWAIT)) {
+ }
+}
+
+int main()
+{
+ printf("PID %d\en", getpid());
+
+ uv_thread_t thread1, thread2;
+
+ uv_thread_create(&thread1, thread1_worker, 0);
+ uv_thread_create(&thread2, thread2_worker, 0);
+
+ uv_thread_join(&thread1);
+ uv_thread_join(&thread2);
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+\fBuv_run(loop, UV_RUN_NOWAIT)\fP is similar to \fBuv_run(loop, UV_RUN_ONCE)\fP
+in that it will process only one event. UV_RUN_ONCE blocks if there are no
+pending events, while UV_RUN_NOWAIT will return immediately. We use NOWAIT
+so that one of the loops isn\(aqt starved because the other one has no pending
+activity.
+.UNINDENT
+.UNINDENT
+.sp
+Send \fBSIGUSR1\fP to the process, and you\(aqll find the handler being invoked
+4 times, one for each \fBuv_signal_t\fP\&. The handler just stops each handle,
+so that the program exits. This sort of dispatch to all handlers is very
+useful. A server using multiple event loops could ensure that all data was
+safely saved before termination, simply by every loop adding a watcher for
+\fBSIGINT\fP\&.
+.SS Child Process I/O
+.sp
+A normal, newly spawned process has its own set of file descriptors, with 0,
+1 and 2 being \fBstdin\fP, \fBstdout\fP and \fBstderr\fP respectively. Sometimes you
+may want to share file descriptors with the child. For example, perhaps your
+applications launches a sub\-command and you want any errors to go in the log
+file, but ignore \fBstdout\fP\&. For this you\(aqd like to have \fBstderr\fP of the
+child be the same as the stderr of the parent. In this case, libuv supports
+\fIinheriting\fP file descriptors. In this sample, we invoke the test program,
+which is:
+.sp
+proc\-streams/test.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+
+int main()
+{
+ fprintf(stderr, "This is stderr\en");
+ printf("This is stdout\en");
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The actual program \fBproc\-streams\fP runs this while sharing only \fBstderr\fP\&.
+The file descriptors of the child process are set using the \fBstdio\fP field in
+\fBuv_process_options_t\fP\&. First set the \fBstdio_count\fP field to the number of
+file descriptors being set. \fBuv_process_options_t.stdio\fP is an array of
+\fBuv_stdio_container_t\fP, which is:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+typedef struct uv_stdio_container_s {
+ uv_stdio_flags flags;
+
+ union {
+ uv_stream_t* stream;
+ int fd;
+ } data;
+} uv_stdio_container_t;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+where flags can have several values. Use \fBUV_IGNORE\fP if it isn\(aqt going to be
+used. If the first three \fBstdio\fP fields are marked as \fBUV_IGNORE\fP they\(aqll
+redirect to \fB/dev/null\fP\&.
+.sp
+Since we want to pass on an existing descriptor, we\(aqll use \fBUV_INHERIT_FD\fP\&.
+Then we set the \fBfd\fP to \fBstderr\fP\&.
+.sp
+proc\-streams/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+int main() {
+ loop = uv_default_loop();
+
+ /* ... */
+
+ options.stdio_count = 3;
+ uv_stdio_container_t child_stdio[3];
+ child_stdio[0].flags = UV_IGNORE;
+ child_stdio[1].flags = UV_IGNORE;
+ child_stdio[2].flags = UV_INHERIT_FD;
+ child_stdio[2].data.fd = 2;
+ options.stdio = child_stdio;
+
+ options.exit_cb = on_exit;
+ options.file = args[0];
+ options.args = args;
+
+ int r;
+ if ((r = uv_spawn(loop, &child_req, &options))) {
+ fprintf(stderr, "%s\en", uv_strerror(r));
+ return 1;
+ }
+
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+If you run \fBproc\-stream\fP you\(aqll see that only the line "This is stderr" will
+be displayed. Try marking \fBstdout\fP as being inherited and see the output.
+.sp
+It is dead simple to apply this redirection to streams. By setting \fBflags\fP
+to \fBUV_INHERIT_STREAM\fP and setting \fBdata.stream\fP to the stream in the
+parent process, the child process can treat that stream as standard I/O. This
+can be used to implement something like \fI\%CGI\fP\&.
+.sp
+A sample CGI script/executable is:
+.sp
+cgi/tick.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+#include <unistd.h>
+
+int main() {
+ int i;
+ for (i = 0; i < 10; i++) {
+ printf("tick\en");
+ fflush(stdout);
+ sleep(1);
+ }
+ printf("BOOM!\en");
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The CGI server combines the concepts from this chapter and networking so
+that every client is sent ten ticks after which that connection is closed.
+.sp
+cgi/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+void on_new_connection(uv_stream_t *server, int status) {
+ if (status == \-1) {
+ // error!
+ return;
+ }
+
+ uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
+ uv_tcp_init(loop, client);
+ if (uv_accept(server, (uv_stream_t*) client) == 0) {
+ invoke_cgi_script(client);
+ }
+ else {
+ uv_close((uv_handle_t*) client, NULL);
+ }
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Here we simply accept the TCP connection and pass on the socket (\fIstream\fP) to
+\fBinvoke_cgi_script\fP\&.
+.sp
+cgi/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+ args[1] = NULL;
+
+ /* ... finding the executable path and setting up arguments ... */
+
+ options.stdio_count = 3;
+ uv_stdio_container_t child_stdio[3];
+ child_stdio[0].flags = UV_IGNORE;
+ child_stdio[1].flags = UV_INHERIT_STREAM;
+ child_stdio[1].data.stream = (uv_stream_t*) client;
+ child_stdio[2].flags = UV_IGNORE;
+ options.stdio = child_stdio;
+
+ options.exit_cb = cleanup_handles;
+ options.file = args[0];
+ options.args = args;
+
+ // Set this so we can close the socket after the child process exits.
+ child_req.data = (void*) client;
+ int r;
+ if ((r = uv_spawn(loop, &child_req, &options))) {
+ fprintf(stderr, "%s\en", uv_strerror(r));
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The \fBstdout\fP of the CGI script is set to the socket so that whatever our tick
+script prints, gets sent to the client. By using processes, we can offload the
+read/write buffering to the operating system, so in terms of convenience this
+is great. Just be warned that creating processes is a costly task.
+.SS Parent\-child IPC
+.sp
+A parent and child can have one or two way communication over a pipe created by
+settings \fBuv_stdio_container_t.flags\fP to a bit\-wise combination of
+\fBUV_CREATE_PIPE\fP and \fBUV_READABLE_PIPE\fP or \fBUV_WRITABLE_PIPE\fP\&. The
+read/write flag is from the perspective of the child process. In this case,
+the \fBuv_stream_t* stream\fP field must be set to point to an initialized,
+unopened \fBuv_pipe_t\fP instance.
+.SS New stdio Pipes
+.sp
+The \fBuv_pipe_t\fP structure represents more than just \fI\%pipe(7)\fP (or \fB|\fP),
+but supports any streaming file\-like objects. On Windows, the only object of
+that description is the \fI\%Named Pipe\fP\&. On Unix, this could be any of \fI\%Unix
+Domain Socket\fP, or derived from \fI\%mkfifo(1)\fP, or it could actually be a
+\fI\%pipe(7)\fP\&. When \fBuv_spawn\fP initializes a \fBuv_pipe_t\fP due to the
+\fIUV_CREATE_PIPE\fP flag, it opts for creating a \fI\%socketpair(2)\fP\&.
+.sp
+This is intended for the purpose of allowing multiple libuv processes to
+communicate with IPC. This is discussed below.
+.SS Arbitrary process IPC
+.sp
+Since domain sockets [1] can have a well known name and a location in the
+file\-system they can be used for IPC between unrelated processes. The \fI\%D\-BUS\fP
+system used by open source desktop environments uses domain sockets for event
+notification. Various applications can then react when a contact comes online
+or new hardware is detected. The MySQL server also runs a domain socket on
+which clients can interact with it.
+.sp
+When using domain sockets, a client\-server pattern is usually followed with the
+creator/owner of the socket acting as the server. After the initial setup,
+messaging is no different from TCP, so we\(aqll re\-use the echo server example.
+.sp
+pipe\-echo\-server/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void remove_sock(int sig) {
+ uv_fs_t req;
+ uv_fs_unlink(loop, &req, PIPENAME, NULL);
+ exit(0);
+}
+
+int main() {
+ loop = uv_default_loop();
+
+ uv_pipe_t server;
+ uv_pipe_init(loop, &server, 0);
+
+ signal(SIGINT, remove_sock);
+
+ int r;
+ if ((r = uv_pipe_bind(&server, PIPENAME))) {
+ fprintf(stderr, "Bind error %s\en", uv_err_name(r));
+ return 1;
+ }
+ if ((r = uv_listen((uv_stream_t*) &server, 128, on_new_connection))) {
+ fprintf(stderr, "Listen error %s\en", uv_err_name(r));
+ return 2;
+ }
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+We name the socket \fBecho.sock\fP which means it will be created in the local
+directory. This socket now behaves no different from TCP sockets as far as
+the stream API is concerned. You can test this server using \fI\%socat\fP:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ socat \- /path/to/socket
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+A client which wants to connect to a domain socket will use:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void uv_pipe_connect(uv_connect_t *req, uv_pipe_t *handle, const char *name, uv_connect_cb cb);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+where \fBname\fP will be \fBecho.sock\fP or similar. On Unix systems, \fBname\fP must
+point to a valid file (e.g. \fB/tmp/echo.sock\fP). On Windows, \fBname\fP follows a
+\fB\e\e?\epipe\eecho.sock\fP format.
+.SS Sending file descriptors over pipes
+.sp
+The cool thing about domain sockets is that file descriptors can be exchanged
+between processes by sending them over a domain socket. This allows processes
+to hand off their I/O to other processes. Applications include load\-balancing
+servers, worker processes and other ways to make optimum use of CPU. libuv only
+supports sending \fBTCP sockets or other pipes\fP over pipes for now.
+.sp
+To demonstrate, we will look at a echo server implementation that hands of
+clients to worker processes in a round\-robin fashion. This program is a bit
+involved, and while only snippets are included in the book, it is recommended
+to read the full code to really understand it.
+.sp
+The worker process is quite simple, since the file\-descriptor is handed over to
+it by the master.
+.sp
+multi\-echo\-server/worker.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+uv_loop_t *loop;
+uv_pipe_t queue;
+int main() {
+ loop = uv_default_loop();
+
+ uv_pipe_init(loop, &queue, 1 /* ipc */);
+ uv_pipe_open(&queue, 0);
+ uv_read_start((uv_stream_t*)&queue, alloc_buffer, on_new_connection);
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBqueue\fP is the pipe connected to the master process on the other end, along
+which new file descriptors get sent. It is important to set the \fBipc\fP
+argument of \fBuv_pipe_init\fP to 1 to indicate this pipe will be used for
+inter\-process communication! Since the master will write the file handle to the
+standard input of the worker, we connect the pipe to \fBstdin\fP using
+\fBuv_pipe_open\fP\&.
+.sp
+multi\-echo\-server/worker.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void on_new_connection(uv_stream_t *q, ssize_t nread, const uv_buf_t *buf) {
+ if (nread < 0) {
+ if (nread != UV_EOF)
+ fprintf(stderr, "Read error %s\en", uv_err_name(nread));
+ uv_close((uv_handle_t*) q, NULL);
+ return;
+ }
+
+ uv_pipe_t *pipe = (uv_pipe_t*) q;
+ if (!uv_pipe_pending_count(pipe)) {
+ fprintf(stderr, "No pending count\en");
+ return;
+ }
+
+ uv_handle_type pending = uv_pipe_pending_type(pipe);
+ assert(pending == UV_TCP);
+
+ uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
+ uv_tcp_init(loop, client);
+ if (uv_accept(q, (uv_stream_t*) client) == 0) {
+ uv_os_fd_t fd;
+ uv_fileno((const uv_handle_t*) client, &fd);
+ fprintf(stderr, "Worker %d: Accepted fd %d\en", getpid(), fd);
+ uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
+ }
+ else {
+ uv_close((uv_handle_t*) client, NULL);
+ }
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+First we call \fBuv_pipe_pending_count()\fP to ensure that a handle is available
+to read out. If your program could deal with different types of handles,
+\fBuv_pipe_pending_type()\fP can be used to determine the type.
+Although \fBaccept\fP seems odd in this code, it actually makes sense. What
+\fBaccept\fP traditionally does is get a file descriptor (the client) from
+another file descriptor (The listening socket). Which is exactly what we do
+here. Fetch the file descriptor (\fBclient\fP) from \fBqueue\fP\&. From this point
+the worker does standard echo server stuff.
+.sp
+Turning now to the master, let\(aqs take a look at how the workers are launched to
+allow load balancing.
+.sp
+multi\-echo\-server/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+struct child_worker {
+ uv_process_t req;
+ uv_process_options_t options;
+ uv_pipe_t pipe;
+} *workers;
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The \fBchild_worker\fP structure wraps the process, and the pipe between the
+master and the individual process.
+.sp
+multi\-echo\-server/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void setup_workers() {
+ round_robin_counter = 0;
+
+ // ...
+
+ // launch same number of workers as number of CPUs
+ uv_cpu_info_t *info;
+ int cpu_count;
+ uv_cpu_info(&info, &cpu_count);
+ uv_free_cpu_info(info, cpu_count);
+
+ child_worker_count = cpu_count;
+
+ workers = calloc(cpu_count, sizeof(struct child_worker));
+ while (cpu_count\-\-) {
+ struct child_worker *worker = &workers[cpu_count];
+ uv_pipe_init(loop, &worker\->pipe, 1);
+
+ uv_stdio_container_t child_stdio[3];
+ child_stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
+ child_stdio[0].data.stream = (uv_stream_t*) &worker\->pipe;
+ child_stdio[1].flags = UV_IGNORE;
+ child_stdio[2].flags = UV_INHERIT_FD;
+ child_stdio[2].data.fd = 2;
+
+ worker\->options.stdio = child_stdio;
+ worker\->options.stdio_count = 3;
+
+ worker\->options.exit_cb = close_process_handle;
+ worker\->options.file = args[0];
+ worker\->options.args = args;
+
+ uv_spawn(loop, &worker\->req, &worker\->options);
+ fprintf(stderr, "Started worker %d\en", worker\->req.pid);
+ }
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+In setting up the workers, we use the nifty libuv function \fBuv_cpu_info\fP to
+get the number of CPUs so we can launch an equal number of workers. Again it is
+important to initialize the pipe acting as the IPC channel with the third
+argument as 1. We then indicate that the child process\(aq \fBstdin\fP is to be
+a readable pipe (from the point of view of the child). Everything is
+straightforward till here. The workers are launched and waiting for file
+descriptors to be written to their standard input.
+.sp
+It is in \fBon_new_connection\fP (the TCP infrastructure is initialized in
+\fBmain()\fP), that we accept the client socket and pass it along to the next
+worker in the round\-robin.
+.sp
+multi\-echo\-server/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void on_new_connection(uv_stream_t *server, int status) {
+ if (status == \-1) {
+ // error!
+ return;
+ }
+
+ uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
+ uv_tcp_init(loop, client);
+ if (uv_accept(server, (uv_stream_t*) client) == 0) {
+ uv_write_t *write_req = (uv_write_t*) malloc(sizeof(uv_write_t));
+ dummy_buf = uv_buf_init("a", 1);
+ struct child_worker *worker = &workers[round_robin_counter];
+ uv_write2(write_req, (uv_stream_t*) &worker\->pipe, &dummy_buf, 1, (uv_stream_t*) client, NULL);
+ round_robin_counter = (round_robin_counter + 1) % child_worker_count;
+ }
+ else {
+ uv_close((uv_handle_t*) client, NULL);
+ }
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The \fBuv_write2\fP call handles all the abstraction and it is simply a matter of
+passing in the handle (\fBclient\fP) as the right argument. With this our
+multi\-process echo server is operational.
+.sp
+Thanks to Kyle for \fI\%pointing out\fP that \fBuv_write2()\fP requires a non\-empty
+buffer even when sending handles.
+
+.sp
+.ce
+----
+
+.ce 0
+.sp
+.IP [1] 5
+In this section domain sockets stands in for named pipes on Windows as
+well.
+.SS Advanced event loops
+.sp
+libuv provides considerable user control over event loops, and you can achieve
+interesting results by juggling multiple loops. You can also embed libuv\(aqs
+event loop into another event loop based library \-\- imagine a Qt based UI, and
+Qt\(aqs event loop driving a libuv backend which does intensive system level
+tasks.
+.SS Stopping an event loop
+.sp
+\fBuv_stop()\fP can be used to stop an event loop. The earliest the loop will
+stop running is \fIon the next iteration\fP, possibly later. This means that events
+that are ready to be processed in this iteration of the loop will still be
+processed, so \fBuv_stop()\fP can\(aqt be used as a kill switch. When \fBuv_stop()\fP
+is called, the loop \fBwon\(aqt\fP block for i/o on this iteration. The semantics of
+these things can be a bit difficult to understand, so let\(aqs look at
+\fBuv_run()\fP where all the control flow occurs.
+.sp
+src/unix/core.c \- uv_run
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+static void uv__run_closing_handles(uv_loop_t* loop) {
+ uv_handle_t* p;
+ uv_handle_t* q;
+
+ p = loop\->closing_handles;
+ loop\->closing_handles = NULL;
+
+ while (p) {
+ q = p\->next_closing;
+ uv__finish_close(p);
+ p = q;
+ }
+}
+
+
+int uv_is_closing(const uv_handle_t* handle) {
+ return uv__is_closing(handle);
+}
+
+
+int uv_backend_fd(const uv_loop_t* loop) {
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBstop_flag\fP is set by \fBuv_stop()\fP\&. Now all libuv callbacks are invoked
+within the event loop, which is why invoking \fBuv_stop()\fP in them will still
+lead to this iteration of the loop occurring. First libuv updates timers, then
+runs pending timer, idle and prepare callbacks, and invokes any pending I/O
+callbacks. If you were to call \fBuv_stop()\fP in any of them, \fBstop_flag\fP
+would be set. This causes \fBuv_backend_timeout()\fP to return \fB0\fP, which is
+why the loop does not block on I/O. If on the other hand, you called
+\fBuv_stop()\fP in one of the check handlers, I/O has already finished and is not
+affected.
+.sp
+\fBuv_stop()\fP is useful to shutdown a loop when a result has been computed or
+there is an error, without having to ensure that all handlers are stopped one
+by one.
+.sp
+Here is a simple example that stops the loop and demonstrates how the current
+iteration of the loop still takes places.
+.sp
+uvstop/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+#include <uv.h>
+
+int64_t counter = 0;
+
+void idle_cb(uv_idle_t *handle) {
+ printf("Idle callback\en");
+ counter++;
+
+ if (counter >= 5) {
+ uv_stop(uv_default_loop());
+ printf("uv_stop() called\en");
+ }
+}
+
+void prep_cb(uv_prepare_t *handle) {
+ printf("Prep callback\en");
+}
+
+int main() {
+ uv_idle_t idler;
+ uv_prepare_t prep;
+
+ uv_idle_init(uv_default_loop(), &idler);
+ uv_idle_start(&idler, idle_cb);
+
+ uv_prepare_init(uv_default_loop(), &prep);
+ uv_prepare_start(&prep, prep_cb);
+
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Utilities
+.sp
+This chapter catalogues tools and techniques which are useful for common tasks.
+The \fI\%libev man page\fP already covers some patterns which can be adopted to
+libuv through simple API changes. It also covers parts of the libuv API that
+don\(aqt require entire chapters dedicated to them.
+.SS Timers
+.sp
+Timers invoke the callback after a certain time has elapsed since the timer was
+started. libuv timers can also be set to invoke at regular intervals instead of
+just once.
+.sp
+Simple use is to init a watcher and start it with a \fBtimeout\fP, and optional \fBrepeat\fP\&.
+Timers can be stopped at any time.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_timer_t timer_req;
+
+uv_timer_init(loop, &timer_req);
+uv_timer_start(&timer_req, callback, 5000, 2000);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+will start a repeating timer, which first starts 5 seconds (the \fBtimeout\fP) after the execution
+of \fBuv_timer_start\fP, then repeats every 2 seconds (the \fBrepeat\fP). Use:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_timer_stop(&timer_req);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+to stop the timer. This can be used safely from within the callback as well.
+.sp
+The repeat interval can be modified at any time with:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_timer_set_repeat(uv_timer_t *timer, int64_t repeat);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+which will take effect \fBwhen possible\fP\&. If this function is called from
+a timer callback, it means:
+.INDENT 0.0
+.IP \(bu 2
+If the timer was non\-repeating, the timer has already been stopped. Use
+\fBuv_timer_start\fP again.
+.IP \(bu 2
+If the timer is repeating, the next timeout has already been scheduled, so
+the old repeat interval will be used once more before the timer switches to
+the new interval.
+.UNINDENT
+.sp
+The utility function:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int uv_timer_again(uv_timer_t *)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+applies \fBonly to repeating timers\fP and is equivalent to stopping the timer
+and then starting it with both initial \fBtimeout\fP and \fBrepeat\fP set to the
+old \fBrepeat\fP value. If the timer hasn\(aqt been started it fails (error code
+\fBUV_EINVAL\fP) and returns \-1.
+.sp
+An actual timer example is in the \fI\%reference count section\fP\&.
+.SS Event loop reference count
+.sp
+The event loop only runs as long as there are active handles. This system
+works by having every handle increase the reference count of the event loop
+when it is started and decreasing the reference count when stopped. It is also
+possible to manually change the reference count of handles using:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void uv_ref(uv_handle_t*);
+void uv_unref(uv_handle_t*);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+These functions can be used to allow a loop to exit even when a watcher is
+active or to use custom objects to keep the loop alive.
+.sp
+The latter can be used with interval timers. You might have a garbage collector
+which runs every X seconds, or your network service might send a heartbeat to
+others periodically, but you don\(aqt want to have to stop them along all clean
+exit paths or error scenarios. Or you want the program to exit when all your
+other watchers are done. In that case just unref the timer immediately after
+creation so that if it is the only watcher running then \fBuv_run\fP will still
+exit.
+.sp
+This is also used in node.js where some libuv methods are being bubbled up to
+the JS API. A \fBuv_handle_t\fP (the superclass of all watchers) is created per
+JS object and can be ref/unrefed.
+.sp
+ref\-timer/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_loop_t *loop;
+uv_timer_t gc_req;
+uv_timer_t fake_job_req;
+
+int main() {
+ loop = uv_default_loop();
+
+ uv_timer_init(loop, &gc_req);
+ uv_unref((uv_handle_t*) &gc_req);
+
+ uv_timer_start(&gc_req, gc, 0, 2000);
+
+ // could actually be a TCP download or something
+ uv_timer_init(loop, &fake_job_req);
+ uv_timer_start(&fake_job_req, fake_job, 9000, 0);
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+We initialize the garbage collector timer, then immediately \fBunref\fP it.
+Observe how after 9 seconds, when the fake job is done, the program
+automatically exits, even though the garbage collector is still running.
+.SS Idler pattern
+.sp
+The callbacks of idle handles are invoked once per event loop. The idle
+callback can be used to perform some very low priority activity. For example,
+you could dispatch a summary of the daily application performance to the
+developers for analysis during periods of idleness, or use the application\(aqs
+CPU time to perform SETI calculations :) An idle watcher is also useful in
+a GUI application. Say you are using an event loop for a file download. If the
+TCP socket is still being established and no other events are present your
+event loop will pause (\fBblock\fP), which means your progress bar will freeze
+and the user will face an unresponsive application. In such a case queue up and
+idle watcher to keep the UI operational.
+.sp
+idle\-compute/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_loop_t *loop;
+uv_fs_t stdin_watcher;
+uv_idle_t idler;
+char buffer[1024];
+
+int main() {
+ loop = uv_default_loop();
+
+ uv_idle_init(loop, &idler);
+
+ uv_buf_t buf = uv_buf_init(buffer, 1024);
+ uv_fs_read(loop, &stdin_watcher, 0, &buf, 1, \-1, on_type);
+ uv_idle_start(&idler, crunch_away);
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Here we initialize the idle watcher and queue it up along with the actual
+events we are interested in. \fBcrunch_away\fP will now be called repeatedly
+until the user types something and presses Return. Then it will be interrupted
+for a brief amount as the loop deals with the input data, after which it will
+keep calling the idle callback again.
+.sp
+idle\-compute/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void crunch_away(uv_idle_t* handle) {
+ // Compute extra\-terrestrial life
+ // fold proteins
+ // computer another digit of PI
+ // or similar
+ fprintf(stderr, "Computing PI...\en");
+ // just to avoid overwhelming your terminal emulator
+ uv_idle_stop(handle);
+}
+
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Passing data to worker thread
+.sp
+When using \fBuv_queue_work\fP you\(aqll usually need to pass complex data through
+to the worker thread. The solution is to use a \fBstruct\fP and set
+\fBuv_work_t.data\fP to point to it. A slight variation is to have the
+\fBuv_work_t\fP itself as the first member of this struct (called a baton [1]).
+This allows cleaning up the work request and all the data in one free call.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+struct ftp_baton {
+ uv_work_t req;
+ char *host;
+ int port;
+ char *username;
+ char *password;
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ftp_baton *baton = (ftp_baton*) malloc(sizeof(ftp_baton));
+baton\->req.data = (void*) baton;
+baton\->host = strdup("my.webhost.com");
+baton\->port = 21;
+// ...
+
+uv_queue_work(loop, &baton\->req, ftp_session, ftp_cleanup);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Here we create the baton and queue the task.
+.sp
+Now the task function can extract the data it needs:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void ftp_session(uv_work_t *req) {
+ ftp_baton *baton = (ftp_baton*) req\->data;
+
+ fprintf(stderr, "Connecting to %s\en", baton\->host);
+}
+
+void ftp_cleanup(uv_work_t *req) {
+ ftp_baton *baton = (ftp_baton*) req\->data;
+
+ free(baton\->host);
+ // ...
+ free(baton);
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+We then free the baton which also frees the watcher.
+.SS External I/O with polling
+.sp
+Usually third\-party libraries will handle their own I/O, and keep track of
+their sockets and other files internally. In this case it isn\(aqt possible to use
+the standard stream I/O operations, but the library can still be integrated
+into the libuv event loop. All that is required is that the library allow you
+to access the underlying file descriptors and provide functions that process
+tasks in small increments as decided by your application. Some libraries though
+will not allow such access, providing only a standard blocking function which
+will perform the entire I/O transaction and only then return. It is unwise to
+use these in the event loop thread, use the threadpool instead. Of
+course, this will also mean losing granular control on the library.
+.sp
+The \fBuv_poll\fP section of libuv simply watches file descriptors using the
+operating system notification mechanism. In some sense, all the I/O operations
+that libuv implements itself are also backed by \fBuv_poll\fP like code. Whenever
+the OS notices a change of state in file descriptors being polled, libuv will
+invoke the associated callback.
+.sp
+Here we will walk through a simple download manager that will use \fI\%libcurl\fP to
+download files. Rather than give all control to libcurl, we\(aqll instead be
+using the libuv event loop, and use the non\-blocking, async \fI\%multi\fP interface to
+progress with the download whenever libuv notifies of I/O readiness.
+.sp
+uvwget/main.c \- The setup
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <uv.h>
+#include <curl/curl.h>
+
+uv_loop_t *loop;
+CURLM *curl_handle;
+uv_timer_t timeout;
+}
+
+int main(int argc, char **argv) {
+ loop = uv_default_loop();
+
+ if (argc <= 1)
+ return 0;
+
+ if (curl_global_init(CURL_GLOBAL_ALL)) {
+ fprintf(stderr, "Could not init cURL\en");
+ return 1;
+ }
+
+ uv_timer_init(loop, &timeout);
+
+ curl_handle = curl_multi_init();
+ curl_multi_setopt(curl_handle, CURLMOPT_SOCKETFUNCTION, handle_socket);
+ curl_multi_setopt(curl_handle, CURLMOPT_TIMERFUNCTION, start_timeout);
+
+ while (argc\-\- > 1) {
+ add_download(argv[argc], argc);
+ }
+
+ uv_run(loop, UV_RUN_DEFAULT);
+ curl_multi_cleanup(curl_handle);
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The way each library is integrated with libuv will vary. In the case of
+libcurl, we can register two callbacks. The socket callback \fBhandle_socket\fP
+is invoked whenever the state of a socket changes and we have to start polling
+it. \fBstart_timeout\fP is called by libcurl to notify us of the next timeout
+interval, after which we should drive libcurl forward regardless of I/O status.
+This is so that libcurl can handle errors or do whatever else is required to
+get the download moving.
+.sp
+Our downloader is to be invoked as:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ ./uvwget [url1] [url2] ...
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+So we add each argument as an URL
+.sp
+uvwget/main.c \- Adding urls
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+void add_download(const char *url, int num) {
+ char filename[50];
+ sprintf(filename, "%d.download", num);
+ FILE *file;
+
+ file = fopen(filename, "w");
+ if (file == NULL) {
+ fprintf(stderr, "Error opening %s\en", filename);
+ return;
+ }
+
+ CURL *handle = curl_easy_init();
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, file);
+ curl_easy_setopt(handle, CURLOPT_URL, url);
+ curl_multi_add_handle(curl_handle, handle);
+ fprintf(stderr, "Added download %s \-> %s\en", url, filename);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+We let libcurl directly write the data to a file, but much more is possible if
+you so desire.
+.sp
+\fBstart_timeout\fP will be called immediately the first time by libcurl, so
+things are set in motion. This simply starts a libuv \fI\%timer\fP which
+drives \fBcurl_multi_socket_action\fP with \fBCURL_SOCKET_TIMEOUT\fP whenever it
+times out. \fBcurl_multi_socket_action\fP is what drives libcurl, and what we
+call whenever sockets change state. But before we go into that, we need to poll
+on sockets whenever \fBhandle_socket\fP is called.
+.sp
+uvwget/main.c \- Setting up polling
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+
+void start_timeout(CURLM *multi, long timeout_ms, void *userp) {
+ if (timeout_ms <= 0)
+ timeout_ms = 1; /* 0 means directly call socket_action, but we\(aqll do it in a bit */
+ uv_timer_start(&timeout, on_timeout, timeout_ms, 0);
+}
+
+int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp) {
+ curl_context_t *curl_context;
+ if (action == CURL_POLL_IN || action == CURL_POLL_OUT) {
+ if (socketp) {
+ curl_context = (curl_context_t*) socketp;
+ }
+ else {
+ curl_context = create_curl_context(s);
+ curl_multi_assign(curl_handle, s, (void *) curl_context);
+ }
+ }
+
+ switch (action) {
+ case CURL_POLL_IN:
+ uv_poll_start(&curl_context\->poll_handle, UV_READABLE, curl_perform);
+ break;
+ case CURL_POLL_OUT:
+ uv_poll_start(&curl_context\->poll_handle, UV_WRITABLE, curl_perform);
+ break;
+ case CURL_POLL_REMOVE:
+ if (socketp) {
+ uv_poll_stop(&((curl_context_t*)socketp)\->poll_handle);
+ destroy_curl_context((curl_context_t*) socketp);
+ curl_multi_assign(curl_handle, s, NULL);
+ }
+ break;
+ default:
+ abort();
+ }
+
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+We are interested in the socket fd \fBs\fP, and the \fBaction\fP\&. For every socket
+we create a \fBuv_poll_t\fP handle if it doesn\(aqt exist, and associate it with the
+socket using \fBcurl_multi_assign\fP\&. This way \fBsocketp\fP points to it whenever
+the callback is invoked.
+.sp
+In the case that the download is done or fails, libcurl requests removal of the
+poll. So we stop and free the poll handle.
+.sp
+Depending on what events libcurl wishes to watch for, we start polling with
+\fBUV_READABLE\fP or \fBUV_WRITABLE\fP\&. Now libuv will invoke the poll callback
+whenever the socket is ready for reading or writing. Calling \fBuv_poll_start\fP
+multiple times on the same handle is acceptable, it will just update the events
+mask with the new value. \fBcurl_perform\fP is the crux of this program.
+.sp
+uvwget/main.c \- Driving libcurl.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void curl_perform(uv_poll_t *req, int status, int events) {
+ uv_timer_stop(&timeout);
+ int running_handles;
+ int flags = 0;
+ if (status < 0) flags = CURL_CSELECT_ERR;
+ if (!status && events & UV_READABLE) flags |= CURL_CSELECT_IN;
+ if (!status && events & UV_WRITABLE) flags |= CURL_CSELECT_OUT;
+
+ curl_context_t *context;
+
+ context = (curl_context_t*)req;
+
+ curl_multi_socket_action(curl_handle, context\->sockfd, flags, &running_handles);
+ check_multi_info();
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The first thing we do is to stop the timer, since there has been some progress
+in the interval. Then depending on what event triggered the callback, we set
+the correct flags. Then we call \fBcurl_multi_socket_action\fP with the socket
+that progressed and the flags informing about what events happened. At this
+point libcurl does all of its internal tasks in small increments, and will
+attempt to return as fast as possible, which is exactly what an evented program
+wants in its main thread. libcurl keeps queueing messages into its own queue
+about transfer progress. In our case we are only interested in transfers that
+are completed. So we extract these messages, and clean up handles whose
+transfers are done.
+.sp
+uvwget/main.c \- Reading transfer status.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void check_multi_info(void) {
+ char *done_url;
+ CURLMsg *message;
+ int pending;
+
+ while ((message = curl_multi_info_read(curl_handle, &pending))) {
+ switch (message\->msg) {
+ case CURLMSG_DONE:
+ curl_easy_getinfo(message\->easy_handle, CURLINFO_EFFECTIVE_URL,
+ &done_url);
+ printf("%s DONE\en", done_url);
+
+ curl_multi_remove_handle(curl_handle, message\->easy_handle);
+ curl_easy_cleanup(message\->easy_handle);
+ break;
+
+ default:
+ fprintf(stderr, "CURLMSG default\en");
+ abort();
+ }
+ }
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Check & Prepare watchers
+.sp
+TODO
+.SS Loading libraries
+.sp
+libuv provides a cross platform API to dynamically load \fI\%shared libraries\fP\&.
+This can be used to implement your own plugin/extension/module system and is
+used by node.js to implement \fBrequire()\fP support for bindings. The usage is
+quite simple as long as your library exports the right symbols. Be careful with
+sanity and security checks when loading third party code, otherwise your
+program will behave unpredictably. This example implements a very simple
+plugin system which does nothing except print the name of the plugin.
+.sp
+Let us first look at the interface provided to plugin authors.
+.sp
+plugin/plugin.h
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#ifndef UVBOOK_PLUGIN_SYSTEM
+#define UVBOOK_PLUGIN_SYSTEM
+
+// Plugin authors should use this to register their plugins with mfp.
+void mfp_register(const char *name);
+
+#endif
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+You can similarly add more functions that plugin authors can use to do useful
+things in your application [2]\&. A sample plugin using this API is:
+.sp
+plugin/hello.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include "plugin.h"
+
+void initialize() {
+ mfp_register("Hello World!");
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Our interface defines that all plugins should have an \fBinitialize\fP function
+which will be called by the application. This plugin is compiled as a shared
+library and can be loaded by running our application:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ ./plugin libhello.dylib
+Loading libhello.dylib
+Registered plugin "Hello World!"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The shared library filename will be different depending on platforms. On
+Linux it is \fBlibhello.so\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+This is done by using \fBuv_dlopen\fP to first load the shared library
+\fBlibhello.dylib\fP\&. Then we get access to the \fBinitialize\fP function using
+\fBuv_dlsym\fP and invoke it.
+.sp
+plugin/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include "plugin.h"
+
+typedef void (*init_plugin_function)();
+
+void mfp_register(const char *name) {
+ fprintf(stderr, "Registered plugin \e"%s\e"\en", name);
+}
+
+int main(int argc, char **argv) {
+ if (argc == 1) {
+ fprintf(stderr, "Usage: %s [plugin1] [plugin2] ...\en", argv[0]);
+ return 0;
+ }
+
+ uv_lib_t *lib = (uv_lib_t*) malloc(sizeof(uv_lib_t));
+ while (\-\-argc) {
+ fprintf(stderr, "Loading %s\en", argv[argc]);
+ if (uv_dlopen(argv[argc], lib)) {
+ fprintf(stderr, "Error: %s\en", uv_dlerror(lib));
+ continue;
+ }
+
+ init_plugin_function init_plugin;
+ if (uv_dlsym(lib, "initialize", (void **) &init_plugin)) {
+ fprintf(stderr, "dlsym error: %s\en", uv_dlerror(lib));
+ continue;
+ }
+
+ init_plugin();
+ }
+
+ return 0;
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBuv_dlopen\fP expects a path to the shared library and sets the opaque
+\fBuv_lib_t\fP pointer. It returns 0 on success, \-1 on error. Use \fBuv_dlerror\fP
+to get the error message.
+.sp
+\fBuv_dlsym\fP stores a pointer to the symbol in the second argument in the third
+argument. \fBinit_plugin_function\fP is a function pointer to the sort of
+function we are looking for in the application\(aqs plugins.
+.SS TTY
+.sp
+Text terminals have supported basic formatting for a long time, with a \fI\%pretty
+standardised\fP command set. This formatting is often used by programs to
+improve the readability of terminal output. For example \fBgrep \-\-colour\fP\&.
+libuv provides the \fBuv_tty_t\fP abstraction (a stream) and related functions to
+implement the ANSI escape codes across all platforms. By this I mean that libuv
+converts ANSI codes to the Windows equivalent, and provides functions to get
+terminal information.
+.sp
+The first thing to do is to initialize a \fBuv_tty_t\fP with the file descriptor
+it reads/writes from. This is achieved with:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int unused)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The \fBunused\fP parameter is now auto\-detected and ignored. It previously needed
+to be set to use \fBuv_read_start()\fP on the stream.
+.sp
+It is then best to use \fBuv_tty_set_mode\fP to set the mode to \fInormal\fP
+which enables most TTY formatting, flow\-control and other settings. \fI\%Other\fP modes
+are also available.
+.sp
+Remember to call \fBuv_tty_reset_mode\fP when your program exits to restore the
+state of the terminal. Just good manners. Another set of good manners is to be
+aware of redirection. If the user redirects the output of your command to
+a file, control sequences should not be written as they impede readability and
+\fBgrep\fP\&. To check if the file descriptor is indeed a TTY, call
+\fBuv_guess_handle\fP with the file descriptor and compare the return value with
+\fBUV_TTY\fP\&.
+.sp
+Here is a simple example which prints white text on a red background:
+.sp
+tty/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <uv.h>
+
+uv_loop_t *loop;
+uv_tty_t tty;
+int main() {
+ loop = uv_default_loop();
+
+ uv_tty_init(loop, &tty, STDOUT_FILENO, 0);
+ uv_tty_set_mode(&tty, UV_TTY_MODE_NORMAL);
+
+ if (uv_guess_handle(1) == UV_TTY) {
+ uv_write_t req;
+ uv_buf_t buf;
+ buf.base = "\e033[41;37m";
+ buf.len = strlen(buf.base);
+ uv_write(&req, (uv_stream_t*) &tty, &buf, 1, NULL);
+ }
+
+ uv_write_t req;
+ uv_buf_t buf;
+ buf.base = "Hello TTY\en";
+ buf.len = strlen(buf.base);
+ uv_write(&req, (uv_stream_t*) &tty, &buf, 1, NULL);
+ uv_tty_reset_mode();
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The final TTY helper is \fBuv_tty_get_winsize()\fP which is used to get the
+width and height of the terminal and returns \fB0\fP on success. Here is a small
+program which does some animation using the function and character position
+escape codes.
+.sp
+tty\-gravity/main.c
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <uv.h>
+
+uv_loop_t *loop;
+uv_tty_t tty;
+uv_timer_t tick;
+uv_write_t write_req;
+int width, height;
+int pos = 0;
+char *message = " Hello TTY ";
+
+void update(uv_timer_t *req) {
+ char data[500];
+
+ uv_buf_t buf;
+ buf.base = data;
+ buf.len = sprintf(data, "\e033[2J\e033[H\e033[%dB\e033[%luC\e033[42;37m%s",
+ pos,
+ (unsigned long) (width\-strlen(message))/2,
+ message);
+ uv_write(&write_req, (uv_stream_t*) &tty, &buf, 1, NULL);
+
+ pos++;
+ if (pos > height) {
+ uv_tty_reset_mode();
+ uv_timer_stop(&tick);
+ }
+}
+
+int main() {
+ loop = uv_default_loop();
+
+ uv_tty_init(loop, &tty, STDOUT_FILENO, 0);
+ uv_tty_set_mode(&tty, 0);
+
+ if (uv_tty_get_winsize(&tty, &width, &height)) {
+ fprintf(stderr, "Could not get TTY information\en");
+ uv_tty_reset_mode();
+ return 1;
+ }
+
+ fprintf(stderr, "Width %d, height %d\en", width, height);
+ uv_timer_init(loop, &tick);
+ uv_timer_start(&tick, update, 200, 200);
+ return uv_run(loop, UV_RUN_DEFAULT);
+}
+
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The escape codes are:
+.TS
+center;
+|l|l|.
+_
+T{
+Code
+T} T{
+Meaning
+T}
+_
+T{
+\fI2\fP J
+T} T{
+Clear part of the screen, 2 is entire screen
+T}
+_
+T{
+H
+T} T{
+Moves cursor to certain position, default top\-left
+T}
+_
+T{
+\fIn\fP B
+T} T{
+Moves cursor down by n lines
+T}
+_
+T{
+\fIn\fP C
+T} T{
+Moves cursor right by n columns
+T}
+_
+T{
+m
+T} T{
+Obeys string of display settings, in this case green background (40+2), white text (30+7)
+T}
+_
+.TE
+.sp
+As you can see this is very useful to produce nicely formatted output, or even
+console based arcade games if that tickles your fancy. For fancier control you
+can try \fI\%ncurses\fP\&.
+.sp
+Changed in version 1.23.1:: the \fIreadable\fP parameter is now unused and ignored.
+The appropriate value will now be auto\-detected from the kernel.
+
+
+.sp
+.ce
+----
+
+.ce 0
+.sp
+.IP [1] 5
+I was first introduced to the term baton in this context, in Konstantin
+Käfer\(aqs excellent slides on writing node.js bindings \-\-
+\fI\%https://kkaefer.com/node\-cpp\-modules/#baton\fP
+.IP [2] 5
+mfp is My Fancy Plugin
+.SS About
+.sp
+\fI\%Nikhil Marathe\fP started writing this book one
+afternoon (June 16, 2012) when he didn\(aqt feel like programming. He had recently
+been stung by the lack of good documentation on libuv while working on
+\fI\%node\-taglib\fP\&. Although reference
+documentation was present, there were no comprehensive tutorials. This book is
+the output of that need and tries to be accurate. That said, the book may have
+mistakes. Pull requests are encouraged.
+.sp
+Nikhil is indebted to Marc Lehmann\(aqs comprehensive \fI\%man page\fP about libev which
+describes much of the semantics of the two libraries.
+.sp
+This book was made using \fI\%Sphinx\fP and \fI\%vim\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+In 2017 the libuv project incorporated the Nikhil\(aqs work into the official
+documentation and it\(aqs maintained there henceforth.
+.UNINDENT
+.UNINDENT
+.SS Upgrading
+.sp
+Migration guides for different libuv versions, starting with 1.0.
+.SS libuv 0.10 \-> 1.0.0 migration guide
+.sp
+Some APIs changed quite a bit throughout the 1.0.0 development process. Here
+is a migration guide for the most significant changes that happened after 0.10
+was released.
+.SS Loop initialization and closing
+.sp
+In libuv 0.10 (and previous versions), loops were created with \fIuv_loop_new\fP, which
+allocated memory for a new loop and initialized it; and destroyed with \fIuv_loop_delete\fP,
+which destroyed the loop and freed the memory. Starting with 1.0, those are deprecated
+and the user is responsible for allocating the memory and then initializing the loop.
+.sp
+libuv 0.10
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_loop_t* loop = uv_loop_new();
+\&...
+uv_loop_delete(loop);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+libuv 1.0
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_loop_t* loop = malloc(sizeof *loop);
+uv_loop_init(loop);
+\&...
+uv_loop_close(loop);
+free(loop);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Error handling was omitted for brevity. Check the documentation for \fBuv_loop_init()\fP
+and \fBuv_loop_close()\fP\&.
+.UNINDENT
+.UNINDENT
+.SS Error handling
+.sp
+Error handling had a major overhaul in libuv 1.0. In general, functions and status parameters
+would get 0 for success and \-1 for failure on libuv 0.10, and the user had to use \fIuv_last_error\fP
+to fetch the error code, which was a positive number.
+.sp
+In 1.0, functions and status parameters contain the actual error code, which is 0 for success, or
+a negative number in case of error.
+.sp
+libuv 0.10
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+\&... assume \(aqserver\(aq is a TCP server which is already listening
+r = uv_listen((uv_stream_t*) server, 511, NULL);
+if (r == \-1) {
+ uv_err_t err = uv_last_error(uv_default_loop());
+ /* err.code contains UV_EADDRINUSE */
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+libuv 1.0
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+\&... assume \(aqserver\(aq is a TCP server which is already listening
+r = uv_listen((uv_stream_t*) server, 511, NULL);
+if (r < 0) {
+ /* r contains UV_EADDRINUSE */
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Threadpool changes
+.sp
+In libuv 0.10 Unix used a threadpool which defaulted to 4 threads, while Windows used the
+\fIQueueUserWorkItem\fP API, which uses a Windows internal threadpool, which defaults to 512
+threads per process.
+.sp
+In 1.0, we unified both implementations, so Windows now uses the same implementation Unix
+does. The threadpool size can be set by exporting the \fBUV_THREADPOOL_SIZE\fP environment
+variable. See threadpool\&.
+.SS Allocation callback API change
+.sp
+In libuv 0.10 the callback had to return a filled \fBuv_buf_t\fP by value:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
+ return uv_buf_init(malloc(size), size);
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+In libuv 1.0 a pointer to a buffer is passed to the callback, which the user
+needs to fill:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
+ buf\->base = malloc(size);
+ buf\->len = size;
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Unification of IPv4 / IPv6 APIs
+.sp
+libuv 1.0 unified the IPv4 and IPv6 APIS. There is no longer a \fIuv_tcp_bind\fP and \fIuv_tcp_bind6\fP
+duality, there is only \fBuv_tcp_bind()\fP now.
+.sp
+IPv4 functions took \fBstruct sockaddr_in\fP structures by value, and IPv6 functions took
+\fBstruct sockaddr_in6\fP\&. Now functions take a \fBstruct sockaddr*\fP (note it\(aqs a pointer).
+It can be stack allocated.
+.sp
+libuv 0.10
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", 1234);
+\&...
+uv_tcp_bind(&server, addr)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+libuv 1.0
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+struct sockaddr_in addr;
+uv_ip4_addr("0.0.0.0", 1234, &addr)
+\&...
+uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The IPv4 and IPv6 struct creating functions (\fBuv_ip4_addr()\fP and \fBuv_ip6_addr()\fP)
+have also changed, make sure you check the documentation.
+.INDENT 0.0
+.TP
+.B \&..note::
+This change applies to all functions that made a distinction between IPv4 and IPv6
+addresses.
+.UNINDENT
+.SS Streams / UDP data receive callback API change
+.sp
+The streams and UDP data receive callbacks now get a pointer to a \fBuv_buf_t\fP buffer,
+not a structure by value.
+.sp
+libuv 0.10
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void on_read(uv_stream_t* handle,
+ ssize_t nread,
+ uv_buf_t buf) {
+ ...
+}
+
+void recv_cb(uv_udp_t* handle,
+ ssize_t nread,
+ uv_buf_t buf,
+ struct sockaddr* addr,
+ unsigned flags) {
+ ...
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+libuv 1.0
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void on_read(uv_stream_t* handle,
+ ssize_t nread,
+ const uv_buf_t* buf) {
+ ...
+}
+
+void recv_cb(uv_udp_t* handle,
+ ssize_t nread,
+ const uv_buf_t* buf,
+ const struct sockaddr* addr,
+ unsigned flags) {
+ ...
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Receiving handles over pipes API change
+.sp
+In libuv 0.10 (and earlier versions) the \fIuv_read2_start\fP function was used to start reading
+data on a pipe, which could also result in the reception of handles over it. The callback
+for such function looked like this:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void on_read(uv_pipe_t* pipe,
+ ssize_t nread,
+ uv_buf_t buf,
+ uv_handle_type pending) {
+ ...
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+In libuv 1.0, \fIuv_read2_start\fP was removed, and the user needs to check if there are pending
+handles using \fBuv_pipe_pending_count()\fP and \fBuv_pipe_pending_type()\fP while in
+the read callback:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+void on_read(uv_stream_t* handle,
+ ssize_t nread,
+ const uv_buf_t* buf) {
+ ...
+ while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) {
+ pending = uv_pipe_pending_type((uv_pipe_t*) handle);
+ ...
+ }
+ ...
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Extracting the file descriptor out of a handle
+.sp
+While it wasn\(aqt supported by the API, users often accessed the libuv internals in
+order to get access to the file descriptor of a TCP handle, for example.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+fd = handle\->io_watcher.fd;
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+This is now properly exposed through the \fBuv_fileno()\fP function.
+.SS uv_fs_readdir rename and API change
+.sp
+\fIuv_fs_readdir\fP returned a list of strings in the \fIreq\->ptr\fP field upon completion in
+libuv 0.10. In 1.0, this function got renamed to \fBuv_fs_scandir()\fP, since it\(aqs
+actually implemented using \fBscandir(3)\fP\&.
+.sp
+In addition, instead of allocating a full list strings, the user is able to get one
+result at a time by using the \fBuv_fs_scandir_next()\fP function. This function
+does not need to make a roundtrip to the threadpool, because libuv will keep the
+list of \fIdents\fP returned by \fBscandir(3)\fP around.
+.SH DOWNLOADS
+.sp
+libuv can be downloaded from \fI\%here\fP\&.
+.SH INSTALLATION
+.sp
+Installation instructions can be found in \fI\%the README\fP\&.
+.SH AUTHOR
+libuv contributors
+.SH COPYRIGHT
+2014-present, libuv contributors
+.\" Generated by docutils manpage writer.
+.