LWN.net Logo

select() actually IS edge triggered

select() actually IS edge triggered

Posted Mar 16, 2003 8:12 UTC (Sun) by Ross (subscriber, #4065)
In reply to: select() actually IS edge triggered by IkeTo
Parent article: Edge-triggered interfaces are too difficult?

Yep, if you are using select() to do nonblocking operations without setting the socket to nonblocking mode, your code will break. Believe me, I've done it :) It won't happen predictably, but it can happen. Basically treat the output from select() as a hint, and then try the operation until you get EAGAIN (or EWOULDBLOCK or whatever), and be prepared to handle the case where the very first call returns that error.


(Log in to post comments)

select() actually IS edge triggered

Posted Mar 16, 2003 8:41 UTC (Sun) by IkeTo (subscriber, #2122) [Link]

> Yep, if you are using select() to do nonblocking operations
> without setting the socket to nonblocking mode, your code will
> break.

Seen it only when I've got many threads/processes waiting for the same socket/fd. Then all threads wake up but only one can get the event that occurred. This is even documented in the accept() system call (perhaps because it always bite people making a multiprocess server). Of course you must respect the guarantee of select: only the first read() or write() is guaranteed to be non-blocking, and they may not write all the data you want to write, or read the whole buffer that you give it. Then you must wait for select() to tell you that it is ready again. But if you do respect them, I have never seen it failed, despite that I use it rather regularly. Perhaps the advice is a good safe-guard, but if any type of device or file has that behaviour (without saying that it does not work with select), then it is broken and should be reported as bugs.

BTW, your problem is just the opposite to the problem that paulsheer mentioned. What he says is that select might not return even if some fd is ready---because it has been returned in previous call of select. You say just the opposite: select might return even if no fd is ready. This should never happen, unlike the problem mentioned by paulsheer, which seems to be a gray area in the man page.

select() actually IS edge triggered

Posted Mar 16, 2003 19:00 UTC (Sun) by Ross (subscriber, #4065) [Link]

Yes, I have seen this happen "in real life" on several systems including Linux. The information given by select() is just a "snapshot" in time. You seem to be claiming that this is something new with edge triggered notification. It's not.

You point out the case I'm talking about: accept(), but the problem isn't caused by reading or writing more than once. In fact, if you use blocking sockets, there is no way to avoid the problem.

Specifically, I was talking about connections which are canceled between the call to select() and the call to accept(). The problem in general is that things can change between those two system calls.

If a connection is made to a server with a blocking listen socket the server will be notified of that new connection by select(). But the client can then cancel the connection before the server calls accept(). If there are no other waiting connections, the server will block until another connection is made. This is a classic race condition like the signal right before select() race and the alarm() without sigsetjmp() race). Most systems do not prevent this from happening (though a few will keep dead sockets in the accept queue so they can be handled as errors by accept).

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds