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