[PATCH] ash: clear NONBLOCK flag from stdin when in foreground

Rich Felker dalias at aerifal.cx
Wed Aug 17 21:20:37 UTC 2011


On Wed, Aug 17, 2011 at 10:09:52PM +0200, Laurent Bercot wrote:
> > This is by design and part of how multi-tool script programming works.
> 
>  The Unix design is that scions (via fork() and execve()) inherit stuff
> from their ancestors. If I'm running "nice shoes" and the "nice" program
> sets stdin non-blocking, then the "shoes" program, which is just execve'd
> from "nice", will have to deal with a nonblocking stdin. That's perfectly
> normal.
> 
>  However, what is *not* normal and an aberration in the Unix file handling
> specification, is that a child can change the parent's environment. That
> is what happens in a shell; that is what Denys is talking about.

If the child could not change things about the open file in a way that
would affect the parent, then shell scripts would not be possible. For
instance, after a command that reads from a seekable stdin, the parent
(shell) would still be looking at the old file position, not the new
one.

> #!/bin/sh
> ( head -n 1 ; cat ) < /nfs/file
>  
>  If "head" sets stdin nonblocking, then every process that shares it,

head has no reason to do so, and *cannot* do this. (It's not allowed to.)

> *including its parent* the shell, sees it as nonblocking. The nonblocking
> state goes *back up* the process tree. And then, the "cat" process
> inherits it, and if /nfs/file is on a slow network... you lose.

No, nonblocking mode has *no effect* on ordinary files. Even on NFS.

>  The only portable workaround to the problem at hand is patching
> every shell to sanitize all file descriptor flags before forkexecing
> every command, and it only helps shell programs. The right way to

No, the way to workaround the problem is not doing stupid things.
Hacking nonstandard, nonconformant, nonportable behavior into your
shell is not acceptable.

> fix this is to have the Unix specification changed; and since the
> Unix specification is a huge joke that only officializes existing
> behaviour as standard (if you don't believe me, check
> http://pubs.opengroup.org/onlinepubs/9699919799/functions/gets.html
> - it's still in the standard, in friggin August 2011), the best way

Irrelevant. gets is part of ISO C and POSIX/Unix defers to C. When
gets is removed from C (upcoming C1x) it will also be removed from the
standards that are based on it.

> to have it change is to push Unix implementors towards the change.
>  Denys is right, the Linux kernel is the place to start lobbying.

I hate it when fools who don't know what they're doing and don't
respect standards lobby for nonstandard behavior in Linux, thereby
making the portability landscape *worse* than it already it. Instead
try to understand why things are the way they are and just stop
insisting on doing stupid things (like setting nonblocking mode on a
fd you inherited).

Rich


More information about the busybox mailing list