[MPlayer-dev-eng] Re: kernel: to do_select(pipe) or not to do

Ivan Kalvachev ivan at cacad.com
Tue Nov 23 22:33:41 CET 2004


On Sun, 21 Nov 2004 20:21:58 -0800 (PST)
Linus Torvalds <torvalds at osdl.org> wrote:

> 
> 
> On Mon, 22 Nov 2004, Ivan Kalvachev wrote:
> > 
> > You are very wrong at this point. A full write WILL block if it writes
> > an PIPE_SIZE+1 bytes. And it have nothing to do with select()!
> 
> Don't bother arguing when you don't know what you're talking about.
> 
> As I already mentioned, "select()" usage ONLY MAKES SENSE FOR NONBLOCKING 
> FILE DESCRIPTORS.

Good. Did you send this to documentation maintainers. Because I have not
met this explanation nowhere else!

> 
> Of _course_ a write() will block if the fd is blocking. But if you have a 
> nonblocking fd it will NOT block.

I am talking only for blocking fd. Nonblocking pipes don't have problems (afaik).
 
> What "select()" returns is not whether something blocks or not. Never has 
> been. What the return value of select() means is whether you can do a 
> successful nonblocking write.

Again "nonblocking" is omitted in the documentation i had found.

Here is an small paste from `man select` 
..." those  in  writefds  will  be
watched  to  see  if  a write will not block, "...

> And yes, you _can_ do a successful nonblocking write of PIPE_BUF+1 bytes. 
> It won't do the _whole_ write (it will only do as much as it can), but the 
> point is, select _properly_ returned the fact that yes, you can write to 
> the fd.
> 
> > No need to send me samples, I have not send you the patch that I commit
> > few weeks back, and it does indeed use O_NONBLOCK.
> > 
> > But there is an fundamental problem with select() and pipes (not sure
> > for other types). We don't know how big will be the write! So in case of
> > 1 byte it does too paranoid and unnecessary blocking. In case of big
> > write it will block.
> 
> No. If the pipe is set to nonblocking IT WILL NOT BLOCK. Not for a small
> write, not for a big one. It will write "as much as it can", with the
> added benefit that POSIX guarantees that small writes (as defined by
> PIPE_BUF) are always atomic (ie they will be done fully or not done at
> all, and a reader that has a sufficiently big buffer will see the whole
> packet or none at all).
> 
> So there is no fundamental problem anywhere. Not for pipes, not for 
> sockets, not for anything. The only "fundamental" problem with select is 
> that
>  - it doesn't work for regular files (well, it "works" in the sense that 
>    regular files are never considered to block at all)
>  - if you use select, you basically have to use O_NONBLOCK, or the 
>    operation just doesn't make sense.

Yes. This was my point too. It doesn't make sense. There is no good reason
select() to forecast block after one written byte, it could do the same
even on empty or half-full buffer. All three behaviours could be explained
with same block/nonblock arguing. In all three cases an write may block.

This arguing could be used as long as pipe buffer is fixed size, as you said.


Anyway, I think that select() comes from BSD and if the original implementation
have same behaviour we can assume it is normal. Just document it.

 
> So I repeat, as I did in my example program: just do the damn write(), and 
> stop worrying about it. If you don't want to block, use O_NONBLOCK. 
> 
> And never EVER try to use "select()" _before_ the write. You use select
> after the write _fails_ with EAGAIN, not before. Select is not a "will
> this write work", it's a "ok, the write didn't work, let's not try
> immediately again, but instead wait until it might work".
> 
> I really thought my example program made that very clear. 

Here is paste from `man select_tut`

.."The way that select is
       usually used is to block while waiting for  a  "change  of
       status"  on one or more of the file descriptors. A "change
       of status" is when more characters become  available  from
       the  file  descriptor,  or  when  space  becomes available
       within the kernel's internal buffers"

You see that the explanation you give me is not written here.
I understand you. But this behaviour is not documented nor the proper
usage. Because of this it will make better coders than me to 
make stupid things like this select(blocking_pipe) and they will
have hard time tracing rare bad behaviour. 

If I am not mistaken, Arpad Gereoffy the author of mplayer, wrote
the original code and when I talk with him in irc he told me he had
used select() in many programs without running on problems. This bad
usage was the reason of years old stuck mouse button bug, and if you
have used mplayer then you may have experienced it too.

So if you don't have motivation to implement variable size pipe buffer, then
at least document the current behaviour.
As I said the documentation writer people will listen to you.

If you have done it already, say so. 
Thank you in advance.

Wish You Best
   Ivan Kalvachev
  iive




More information about the MPlayer-dev-eng mailing list