Beware: take this with a BIG grain of salt.
After an hour of staring at TCP implementation in kernels 2.2.18 (~RH
6.2) and 2.4.4 (~RH7) (i.e. tcp_recvmsg() in \linux\net\ipv4\tcp.c it
looks like it's exactly how they work.
In 2.2.18 if len = 0 it will return 0/no error and there is a
enlightning comment near that code:
/*
* BUG BUG BUG
* This violates 1003.1g compliance. We must wait for
* data to exist even if we read none!
*/
In 2.4.4 it will try to read the data anyway and if there is no data and
socket is NOBLOCK (timeo==0) it'll return EAGAIN=EWOULDBLOCK.
So presumably that was a bug in 2.2.x fixed in 2.4.x.
But again, I wouldn't trust my analysis, after all I'm not really sure
if it even goes through this codepath. I would only trust stepping
through the code in the debugger but given that I won't do it,
eyeballing the code is second best alternative. You can check it out for
yourself, it's fun.
> I am experiencing a difference in behavior in nsunix between
> Red Hat 6.1 (kernel 2.2.14) and Red Hat 7.1. I don't have
> 7.1 to develop on, this is basically, a user report....
>
> In 6.1, when I call recvfrom within nsunix.c/GetDATAFromUDS,
> it returns 0, as in 0 bytes were available.
>
> The exact same call from 7.1 returns a -1, and an errno of
> EWOULDBLOCK.
>
> struct sockaddr_in sa;
> int size;
> size = sizeof(sa);
>
> . . .
>
> nbytes = recvfrom(sock,NULL,0,MSG_PEEK,&sa,&size);
>
> In both cases, the underlying socket has been tagged as
> nonblocking, and in fact, I can basically expect that there
> is nothing to read from the socket for most GETs. That's
> okay. As you can see, the call to recvfrom asks for 0 bytes,
> and is called for its side effect: to fill out the
> sockaddr_in structure which yields the IP address of the
> client browser.
>
> I can understand the 6.1 behavior of recvfrom: I was asked
> for 0 bytes, and
> 0 bytes were available, so return 0 bytes. I can rationalize the 7.1
> behavior. There are no bytes in the buffer, so I will have
> to issue a read to read any bytes that I have to return.
> Since I am nonblocking, return -1 and an errno of EWOULDBLOCK.
>
> So my question is: does anyone actually know what's going on?
> Is there a kernel bug here in either 6.1 or 7.1? Should a
> nonblocking call be able to return 0 bytes?