New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve documentation of Unix.{in,out}_channel_of_descr #10181
Conversation
otherlibs/unix/unix.mli
Outdated
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sentence is confusing: "and of" and "several" are not so clear to me. Maybe it would be clearer to be more redundant:
If several channels are created on the same descriptor, you should either close one of the channels (but not the others nor the descriptor) or close the descriptor (but none of the channels).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's wrong with "channels ⋃ {descriptor}" ? :-)
I simplified the explanation by omitting to mention that the descriptor can be closed. It's not the best solution anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The text looks good and is a very helpful clarification; I agree with your analysis of the situation. I would add a couple of words to clarify that open_connection
and establish_server
give a pair of channels on the same descriptor (no other functions seem unclear in this way).
But I disagree that "you can close the file descriptor, just do not use the channel afterwards" is a fair advice to give to programmers. When one does so, the value is placed in an invalid state where further operation (a bug) can fail properly with an exception on good days, but it can also fail silently with an unpredictable outcome. Even assuming that users will follow simple patterns to avoid use-after-free, simple code evolves and becomes more complicated over time, use-after-free can be introduced at a distance, the escaping of borrowed resources gets more tricky to prevent with some monadic styles, etc. It gives bugs that are hard to notice and debug. Instead, we need an operation that properly closes the channel without closing the descriptor, as described at #9786 (comment) (which cannot currently be written).
Further points, if I am not mistaken:
|
Explain more precisely what to do and what not to do to close channels and their underlying descriptor. Fixes: ocaml#9786
3c1b5eb
to
4e4b8ca
Compare
Thanks @gadmm and @gasche for the feedback.
Good point. Done!
Agreed. Especially for output channels, where it can lead to data loss if the channel wasn't flushed properly. I simplified the explanations to just say "close the output channel, don't close the underlying file descriptor, and if there is also an input channel opened on this descriptor, leave the input channel alone". This should be pretty error-prone. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the new text is better, but I still have a few remarks.
otherlibs/unix/unix.mli
Outdated
Closing the channel [ic] returned by [in_channel_of_descr fd] | ||
using [close_in ic] also closes the underlying descriptor [fd]. | ||
Closing both the channel [ic] and the descriptor [fd] is | ||
incorrect and will result in a {!Stdlib.Sys_error} or {!Unix.error} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this is an undefined behavior, since the file descriptor may be reused in between. We cannot guarantee thet there is an exception raised here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All right, I just put "It is incorrect to close both the channel [ic] and the descriptor [fd].". Sometimes the less you write the better.
The time we can collectively spend on this tiny issue has reached zero, so I'll merge now. Thanks for all the discussions. |
Explain more precisely what to do and what not to do to close channels and their underlying descriptor. Fixes: ocaml#9786
As discussed in #9786: this PR documents more precisely what to do and what not to do in order to close the channels created with
Unix.{in,out}_channel_of_descr fd
and the underlying descriptorfd
.