recv.2: With pending 0-length datagram read() and recv() with flags == 0 differ

Quoting Tom:

The statement "With a zero flags argument, recv() is equivalent to
read(2)." is not correct. In the case of passing a UDP socket an
empty buffer the two calls differ. read(2) will be a noop (as it
rightly says in its manpage), but recv(2) will discard the
packet.

We ran into this in networkd, as we use FIONREAD to determine the
buffer size (and allocate the right buffer), so in case someone
passed us an empty packet we would end up in a busy loop when we
were using read(2).  Changing to recv(2) fixed the issue
[https://github.com/systemd/systemd/pull/3299].

Reported-by: Tom Gundersen <teg@jklm.no>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
Michael Kerrisk 2016-05-26 17:32:59 -05:00
parent c3cfbeb992
commit 36c8e72131
1 changed files with 16 additions and 2 deletions

View File

@ -78,8 +78,9 @@ With a zero
.I flags
argument,
.BR recv ()
is equivalent to
.BR read (2).
is generally equivalent to
.BR read (2)
(but see NOTES).
Also, the following call
recv(sockfd, buf, len, flags);
@ -515,6 +516,19 @@ and
.B MSG_WAITALL
flags.
.SH NOTES
If a zero-length datagram is pending,
.BR read (2)
and
.BR recv ()
with a
.I flags
argument of zero provide different behavior.
In this circumstance,
.BR read (2)
has no effect (the datagram remains pending), while
.BR recv ()
consumes the pending datagram.
The
.I socklen_t
type was invented by POSIX.