Read signaled by select(), but recv() returns no data and signal EAGAIN on non-blocking sockets
Asked Answered
P

2

8

I have got signaled socket for read from select(), but then no data arrived by recv call(), instead it returns -1 with errno==EAGAIN.

I can grant that no other thread touch the socket.

I think that this behavior is not correct. If an subsequent close from other side occurs, I can expect return value 0 (graceful close) or other error code from recv, but not EAGAIN, because it means by my opinion that an data will arrive in the future.

I have found some previous thread about the problem here but without solution.

This behavior happens to me on Ubuntu Linux Oneric, or other last Linux distros, then info from link posted here

That it will be fixed in kernel is not true for 3.0.0 kernel or latest 2.6.x

Does anybody have an idea why it happens and how to avoid this unwanted behavior?

Parenthood answered 24/11, 2011 at 11:55 Comment(1)
Sample code would help perfect this question.Cot
F
6

Select() reporting a socket as readable does not mean that there is something to read; it implies that a read will not block. The read could return -1 or 0, but it would not block.

UPDATE:

After select returns readable: if read() returns -1, check errno. EAGAIN/EWOULDBLOCK and EINTR are the values to be treated specially: mostly by reissuing the read(), but you might trust on the select loop returning readable the next time around.

If there are multiple threads involved, things may get more difficult.

Ferrick answered 24/11, 2011 at 11:58 Comment(6)
EAGAIN is what you get when the read would block but you have set O_NONBLOCK.Opportuna
But that is more or less orthogonal to what select() reports. Select guarantees that a subsequent read will not block. (there are special cases eg. involving UDP requiring O_NONBLOCK, but that is not important here)Ferrick
The question here is, what read signaled by select() means. Because after this read->EAGAIN, I call the select() again, and then this call never returns (here select has infinite timeout).Parenthood
@Zdendal in that case it is a bug in your code somewhere (assuming there actually are events happening, and data or shutdown information is not lost in the network)Inna
Hmm, this problem occurs only under heavy load of the application (server). Then can occurs that connection is lost, closed by other side etc. But I have to handle those cases correctly, and expect that OS will give to me correct error code, but it doesn't happen :(Parenthood
If the EAGAIN result only happens occasionally, and the subsequent call to select() blocks, then I wouldn't worry about it too much, you can just ignore it. It's only a real problem if select() always returns immediately, and then recv() always returns -1/EAGAIN, causing your event loop to spin the CPU.Primo
S
1

I'm getting the same problem but with epoll. I noticed, that it happens whenever the system is reusing the FD numbers of the sockets that are already closed. After some research, I've noticed that this behavior is caused by closing the sockets while epolling on them. Try to avoid running select on a socket while closing it - that may help.

Shalondashalt answered 1/9, 2013 at 16:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.