Documentation
¶
Overview ¶
Package fdset asks the kernel which descriptors a read would not wait on.
Two questions, and they are the same question asked with two different amounts of patience:
- ReadableNow, of one descriptor, waiting no time at all. It is what an interpreter asks before a read it does not want to block on.
- Wait, of a set of them, waiting until something happens. It is what a line editor asks so that it can sit idle on a terminal and still notice a descriptor a shell asked it to watch.
**They are one package because they are one mechanism.** The descriptor set, how many descriptors one of its words holds, and the fact that this call's result is spelled differently on Linux than on the BSDs are the substrate underneath both, and the substrate is where the platform mistakes live. A second copy of it beside the first is the shape of bug this tree has now found four times: the copy is written from the same understanding and then the fix goes into only one of them. The callers are in packages that cannot see each other's unexported names — an interpreter and a line editor — so the shared thing has to be a package.
Neither question ever reads. That is the whole point of both: a poll that consumed the byte it reported would leave a caller eating its own input.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrUnsupported = errors.New("waiting on descriptors is not supported on this system")
ErrUnsupported is what Wait answers on a system with no descriptor set to wait on. A caller that cannot wait can still read; see Wait.
Functions ¶
func ReadableNow ¶
ReadableNow reports whether a read on fd would return at once, waiting no time at all for the answer.
The descriptor is not read from, which is the whole point: the caller wants to know whether input is waiting and a read is what would consume it.
Every answer this cannot get is "yes". A descriptor past what a set can name cannot be asked about, and neither can one the call itself failed on, and in both cases the honest fallback is the one that says "go ahead" — the caller then does the read it was going to do, and finds out.
func ReadableWithin ¶
ReadableWithin is ReadableNow with a deadline: it waits up to d for a read on fd to become one that would not block, and reports whether it became one.
The third answer this has and ReadableNow does not is *whether the question could be asked at all*. A caller that only wants to avoid blocking can treat "cannot ask" as "go ahead" and find out from the read; a caller implementing a builtin whose whole contract is a timeout cannot, because a shell that reported a timeout it never waited for, or read where it was asked to wait, is wrong in a way no later call recovers from.
A negative or zero d is the same look ReadableNow takes, which is what `-t 0` means: ask, do not wait.
func Ready ¶
Ready waits until a descriptor is ready in the way the set it was named in asks about, and answers which ones are, set by set.
The general form of the two questions above, and the reason it is here rather than beside its caller: read, write and error are one call to the kernel with three sets in it, and a caller that asked them one at a time would be waiting on the first while the second became ready.
timeout is how long to wait, and **nil means forever** — the distinction a builtin whose timeout is optional has to be able to make, since a zero duration already means "look and come back". A wait with nothing in any set and no timeout is a wait that never ends, which is what a caller asking for exactly that has asked for.
A descriptor that is not open, or is past what a set can name, is **dropped rather than complained about**, and it is dropped before the call rather than after it. The kernel's answer to a set holding one dead entry is a complaint about the *call*, so every live descriptor beside it would lose its turn — the same reasoning Wait gives, and the same bug: a caller's second watcher silently stops working because the first one's descriptor was closed. A caller that wanted to hear about a bad descriptor still does, by the descriptor never being reported ready.
func Wait ¶
Wait waits until terminal has a byte or one of fds is readable, and answers with the descriptors among fds that are.
terminal is the descriptor a key arrives on, or negative where the caller's input is not a descriptor at all. That is the difference between waiting and looking: with a terminal to wait on, this blocks until *something* happens, which is what lets a session sit at an idle prompt costing nothing while a watcher is armed. Without one there is nothing to block on that would ever wake for a keystroke, so it looks once and returns, and a caller that has to do its own read is no worse off than it was.
terminalReady is the whole of what the caller needs to know about the terminal, and answering it separately is deliberate: a key somebody pressed must be able to get through a descriptor that is *permanently* readable. The read end of a pipe whose writer has gone is exactly that, and a caller that served descriptors first would never reach the key.
Types ¶
This section is empty.