Skip to content

Commit

Permalink
Improve documentation of Unix.{in,out}_channel_of_descr
Browse files Browse the repository at this point in the history
Explain more precisely what to do and what not to do to close channels
and their underlying descriptor.

Fixes: ocaml#9786
  • Loading branch information
xavierleroy committed Jan 29, 2021
1 parent d14b3ec commit 3c1b5eb
Showing 1 changed file with 47 additions and 17 deletions.
64 changes: 47 additions & 17 deletions otherlibs/unix/unix.mli
Expand Up @@ -394,16 +394,37 @@ val in_channel_of_descr : file_descr -> in_channel
Text mode is supported only if the descriptor refers to a file
or pipe, but is not supported if it refers to a socket.
On Windows: [set_binary_mode_in] always fails on channels created
with this function.
Beware that channels are buffered so more characters may have been
read from the file descriptor than those accessed using channel functions.
Channels also keep a copy of the current position in the file.
On Windows: {!Stdlib.set_binary_mode_in} always fails on channels
created with this function.
Beware that input channels are buffered, so more characters may
have been read from the descriptor than those accessed using
channel functions. Channels also keep a copy of the current
position in the file.
Closing the channel [ic] returned by [in_channel_of_descr fd]
using [close_in ic] also closes the descriptor [fd].
Alternatively, it is correct to close the descriptor with
[Unix.close fd], then stop using the [ic] channel and let the GC
collect it.
Closing both the channel [ic] and the underlying descriptor [fd] is
incorrect and will result in a {!Stdlib.Sys_error} or {!Unix.error}
exception.
You need to explicitly close all channels created with this function.
Closing the channel also closes the underlying file descriptor (unless
it was already closed). *)
If several channels are created on the same descriptor, exactly one
of the channels and of the descriptor must be closed, but not
several.
Consider for example a descriptor [s] connected to a socket and two
channels [ic = in_channel_of_descr s] and [oc = out_channel_of_descr s].
The recommended closing protocol is to perform [close_out oc],
which flushes buffered output to the socket then closes the socket.
The [ic] channel must not be closed and will be collected by the GC
eventually.
Alternatively, if [oc] was flushed before, you can close the socket
using [Unix.close s] and stop using the two channels [ic] and [oc],
letting the GC collect them.
*)

val out_channel_of_descr : file_descr -> out_channel
(** Create an output channel writing on the given descriptor.
Expand All @@ -412,17 +433,26 @@ val out_channel_of_descr : file_descr -> out_channel
Text mode is supported only if the descriptor refers to a file
or pipe, but is not supported if it refers to a socket.
On Windows: [set_binary_mode_out] always fails on channels created
On Windows: {!Stdlib.set_binary_mode_out} always fails on channels created
with this function.
Beware that channels are buffered so you may have to [flush] them
to ensure that all data has been sent to the file descriptor.
Channels also keep a copy of the current position in the file.
Beware that output channels are buffered, so you may have to call
{!Stdlib.flush} to ensure that all data has been sent to the
descriptor. Channels also keep a copy of the current position in
the file.
Closing the channel [oc] returned by [out_channel_of_descr fd]
using [close_out oc] also closes the descriptor [fd].
Alternatively, it is correct to flush the channel [oc], then close
the descriptor with [Unix.close fd], then stop using the [oc]
channel and let the GC collect it.
Closing both the channel [oc] and the underlying descriptor [fd] is
not correct and will result in a {!Stdlib.Sys_error} or {!Unix.error}
exception.
You need to explicitly close all channels created with this function.
Closing the channel flushes the data and closes the underlying file
descriptor (unless it has already been closed, in which case the
buffered data is lost).*)
See {!Unix.in_channel_of_descr} for a discussion of the closing
protocol when several channels are created on the same descriptor.
*)

val descr_of_in_channel : in_channel -> file_descr
(** Return the descriptor corresponding to an input channel. *)
Expand Down

0 comments on commit 3c1b5eb

Please sign in to comment.