Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 738
Zdenal Avatar asked Nov 24 '11 11:11

Zdenal


2 Answers

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.

like image 50
wildplasser Avatar answered Sep 20 '22 12:09

wildplasser


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.

like image 40
Vladvic Avatar answered Sep 20 '22 12:09

Vladvic