We just upgraded to BusyBox v1.14.4 (w/ built-in ash shell), and we
have noticed what seems to be a bug.

When we exit from one of our user apps that sets stdin to O_NONBLOCK,
O_NONBLOCK remains set on stdin in the shell. So, any subsequent app
not expecting O_NONBLOCK on stdin gets an unexpected EAGAIN. For
example,

       # cat > textfile.txt
       cat: read error: Resource temporarily unavailable

We can think of two fixes in ash.c:

1.) In dowait(), if the exiting child left O_NONBLOCK set, we clear it.

===================================================================
--- busybox/shell/ash.c (revision 13258)
+++ busybox/shell/ash.c (working copy)
@@ -3830,6 +3830,20 @@
        if (pid <= 0)
                return pid;

+#ifdef FIX_FOR_BLOCKED_STDIN
+       /* Clear O_NONBLOCK flag on stdin, if it was left on by the
+        * previous child. */
+       {
+               int flags = fcntl(0, F_GETFL, 0);
+               if (flags >= 0 && flags & O_NONBLOCK) {
+                       flags &=~ O_NONBLOCK;
+                       if (fcntl(0, F_SETFL, flags) >= 0) {
+                               out2str("sh: turning off NDELAY mode\n");
+                       }
+               }
+       }
+#endif
+
        INT_OFF;
        thisjob = NULL;
        for (jp = curjob; jp; jp = jp->prev_job) {


2.) In forkchild(), if O_NONBLOCK was left set from a previous
command, we clear the flag.

Index: busybox/shell/ash.c
===================================================================
--- busybox/shell/ash.c (revision 13258)
+++ busybox/shell/ash.c (working copy)
@@ -4544,6 +4544,21 @@

        closescript();
        clear_traps();
+
+#ifdef FIX_FOR_BLOCKED_STDIN
+       /* Clear O_NONBLOCK flag on stdin, if it was left on by the
+        * previous child. */
+       {
+               int flags = fcntl(0, F_GETFL, 0);
+               if (flags >= 0 && flags & O_NONBLOCK) {
+                       flags &=~ O_NONBLOCK;
+                       if (fcntl(0, F_SETFL, flags) >= 0) {
+                               out2str("sh: turning off NDELAY mode\n");
+                       }
+               }
+       }
+#endif
+
 #if JOBS
        /* do job control only in root shell */
        doing_jobctl = 0;


Are either of these good fixes for the problem, or is there a better fix?

TIA!

-- Johns
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to