*nix select and exceptfds/errorfds semantics
It is sometimes thought that exceptfds is needed to detect errors, but that is a misconception. Errors will be flagged in readfds. Although POSIX requires it (and even calls the parameter errorfds), it depends on the OS whether errors are also flagged in exceptfds. Really, this parameter is only needed if you care about exceptional conditions, but only rarely is there any need to detect those.
What qualifies as an exceptional condition depends on the kind of file descriptor, but by far the most common use is on a TCP socket where it indicates that out-of-band data is available to be read using recv()
with the MSG_OOB
flag. However, TCP out-of-band data has a number of quirks (e.g. only 1 byte can be outstanding) and as a result is rarely used.
In recent Linux kernels exceptfds can be used to detect when certain sysfs attributes change. The current value of the attribute can be read by reading the appropriate file under /sys
, and a select()
on the file descriptor will flag exceptfds when the attribute changes. However this currently only works for some of the attributes, and for mount changes (/proc/mounts
).
Also some device drivers will flag certain device-specific conditions using exceptfds.
You're right, it depends on the type of device you're referencing with the file descriptors. So, it's different for sockets, FIFOs, serial ports, etc...
Look at the man page for read(). At the bottom (at least in OS X) it lists the different errors you can get for different devices. Same goes for write().
For sockets, FIFOs and other IPC mechanisms, I would check out Unix Network Programming, Volumes 1 and 2. IIRC it describes what kind of errnos to expect for different error conditions.
I walked this path once with FIFOs. I ended up brainstorming all the ways the producer and consumer could interact with each end of the FIFO and then wrote test cases for each of those situations. It was a good (although tedious) way to discover all the different error conditions. I learned a lot though and ultimately the code just works now.