I am having trouble understanding what it means to add a descriptor to writefds set for select() in linux. I wrote some simple code that adds the descriptor for stdout to the writefds set and uses a timeout of NULL. Now, my code just infinite loops checking if this descriptor is set, and if it does, it prints "WRITING". When I run my code it just keeps printing "WRITING" to infinity. The same thing happens when I do this for stdin. Again, there is no other code in the loop. Are stdin/stdout always just ready for writing?
Yes, FD_ISSET(fd, &writefds) == true
means fd
is writeable. If you call select()
with that FD set in the writefds after you get EWOULDBLOCK
or EAGAIN
(equivalent on Linux, at least) it blocks until the FD is again writeable.
There's more to it than that. For instance, an FD is also considered writeable if you've done a non-blocking connect()
on it, you got EAGAIN
, and call select()
to wait for the connection to be established. That establishment is signalled in the writefds.
It means you can call write on that fd and the kernel promises to not-block and consume at least 1 byte.
More details. If your socket is not in non-blocking mode and the kernel buffers associated with the socket are full, the kernel will put your thread to sleep until it can empty some of the buffer and be able to consume part of your write.
If your socket is in non-blocking mode and the kernel buffers are full, the write will return immediately without consuming any bytes.
The answer to the question "Is stdout always ready for writing" is "It depends."
stdout can be connected to anything that can be opened as a file descriptor - like a disk file, a network socket, or a pipe. The usual case is that it's connected to a terminal device.
Any of these types of file descriptors can block on writing (which means they might not be marked writeable after select()
returns), but usually only if you're just written a very large amount of data to them (and so filled some kind of buffer). "Large amount" varies between the device types - if your stdout terminal is a 9600 baud serial device, then you could fill the write buffer pretty easily; an xterm, not so much.
Some device will never block - like /dev/null
, for example.