clinuxsocketsfreebsdposix-select

select and poll syscalls. many write events problem


I have a setup with a server/client having many connections to each other. The data being sent in large volumes. The select or poll system calls return many file descriptors as being ready for write. But, as I proceed to write data, eventually, with Nth file descriptor I get EAGAIN, with zero bytes written. And that continues for the most part.

As I understand for now, it is internal kernel buffer, that gets filled up. So the rest of file descriptors get no data sent at the syscall wake up.

My question is, do all file descriptors get signalled in fair fashion? What I mean is, from total of number of file descriptors, first group get signaled and are moved to the tail of avaible for write queue. If not, then how to overcome the above, how to make so, that all sockets that need a data transfer will receive a fair amount of attention?

And as a result of a question, can I skip event loop, if the EAGAIN start to come up?

I do program in C, code references and explanations are welcome.

Update

Review my post on Linux. I have this in manual,-

"On some other UNIX systems, select() can fail with the error EAGAIN if the system fails to allocate kernel-internal resources, rather than ENOMEM as Linux does. POSIX specifies this error for poll(2), but not for select(). Portable programs may wish to check for EAGAIN and loop, just as with EINTR."

At least my intention to skip queue iterating is gone. See "portable programs part".


Solution

  • My question is, do all file descriptors get signalled in fair fashion?

    Both poll and select will return information on which file descriptors are currently readable/writable as of the instant the call returns. This is "fair" in that they are all indicated simultansously. You will need to loop over all the descriptors and write to each one that is writable. You can decide to prefer some over others if you wish, or arrange for your loop to be more fair.

    When you write to a descriptor, it will return EAGAIN or EWOULDBLOCK for any one that is non-blocking and has no buffer space. Each fd has its own buffer, so this happening on one fd has nor bearing on any other fds and they may still be writable.