msh stdin, fcntl nonblock on stdin by child of child

Denys Vlasenko vda.linux at googlemail.com
Wed Feb 20 19:48:09 UTC 2008


On Wednesday 20 February 2008 17:39, Jate Sujjavanich wrote:
> I run a script in the background which starts dropbear client. Dropbear
> sets stdin to non-blocking. This causes my msh shell in the foreground
> to print infinite prompts because lineedit is expecting a blocking read
> (in safe_read).
> 
> msh -> sh spawn_dbclient & -> dbclient args
> 
> Should dbclient's fcntl be affecting msh's stdin?

Yes. This is a design bug in UNIX API.

fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NONBLOCK);

will set nonblocking mode not only on _your_
stdin, but also on stdin of your parent, etc.

In general,

        fd2 = dup(fd1);
        fcntl(fd2, F_SETFL, fcntl(fd2, F_GETFL, 0) | O_NONBLOCK);

sets both fd1 and fd2 to O_NONBLOCK. This includes cases
where duping is done implicitly by fork() etc.

We need

        fcntl(fd2, F_SETFD, fcntl(fd2, F_GETFD, 0) | O_NONBLOCK);

(note SETFD, not SETFL!) but such thing doesn't exist.

Alternatively, we need nonblocking_read(fd, ...) which doesn't
require O_NONBLOCK dance at all. Actually, it exists:

        n = recv(fd, buf, len, MSG_DONTWAIT);

       MSG_DONTWAIT
              Enables non-blocking operation; if the operation
              would block, EAGAIN is returned.

but recv() works only for sockets!!! DAMN.
--
vda



More information about the busybox mailing list