Re: UDP recvmsg blocks after select(), 2.6 bug?

Jesper Juhl
2004-10-17T17:27:24Z

On Sun, 17 Oct 2004, Buddy Lucas wrote:

> On Sun, 17 Oct 2004 11:05:09 -0400, Mark Mielke <mark@mark.mielke.cc> wrote:
> > On Sun, Oct 17, 2004 at 04:17:06PM +0200, Buddy Lucas wrote:
> > > On Sun, 17 Oct 2004 15:35:37 +0200, Lars Marowsky-Bree <lmb@suse.de> wrote:
> > > > The SuV spec is actually quite detailed about the options here:
> > > > A descriptor shall be considered ready for reading when a call
> > > > to an input function with O_NONBLOCK clear would not block,
> > > > whether or not the function would transfer data successfully.
> > > > (The function might return data, an end-of-file indication, or
> > > > an error other than one indicating that it is blocked, and in
> > > > each of these cases the descriptor shall be considered ready for
> > > > reading.)
> > > But it says nowhere that the select()/recvmsg() operation is atomic, right?
> >
> > This is a distraction. If the call to select() had been substituted
> > with a call to recvmsg(), it would have blocked. Instead, select() is
> > returning 'yes, you can read', and then recvmsg() is blocking. The
> > select() lied. The information is all sitting in the kernel packet
>
> No. A million things might happen between select() and recvmsg(), both
> in kernel and application. For a consistent behaviour throughout all
> possibilities, you *have* to assume that any read on a blocking fd may
> block, and that a fd ready for reading at select() time might not be
> readable once the app gets to recvmsg() -- for whatever reason.
>
> And indeed, that implies that select() on blocking fds is generally
> not useful if you expect to bypass the blocking through select().
> Personally, I think any application that implements this expectation
> is broken. (If only because you might have to do a second read() or
> recvmsg() which will either result in a crappy select() loop or a
> broken read()/recvmsg() loop).
>
Personally I agree that if you want non blocking sockets that's what you
should use, but many people expect that if select says a socket is
readable then attempting to recieve that data will not block. Many people
refer to Stevens "UNIX Network Programming" to find out how select and
related networking functions are supposed to behave, and Stevens has this
to say on page 153 under the heading "Under What Conditions Is a
Descriptor Ready?" [1] :

[...]
1. A socket is ready for reading if any of the following four conditions
is true:

a. The number of bytes of data in the socker recieve buffer is greater
than or equal to the current size of the low-water mark for the
socket recieve buffer. A read operation on the socket will not block
and will return a value greater than 0 ...

[...]

He's not saying this is specific to either UDP or TCP sockets nor blocking
or non-blocking sockets, so I suspect that regardless of what POSIX might
say a lot of people will be reading the above and assume that if select
says a socket (any type of socket) is ready for reading, then attempting
to read will not block.
Using blocking sockets with select in this manner may be silly or
inefficient, but I think many people expect it to work without the
subsequent read blocking in any case.

[1] I'm only quoting what I think is relevant to the thread, but I can
quote the rest if wanted. My copy of the book has ISBN 0-13-490012-X in
case someone wants to check.

--
Jesper Juhl