[PATCH] tty non-blocking read bug

Tobias =?ISO-8859-1?Q?Ringstr=F6m (tobias.ringstrom@frt.frontec.se)
Sun, 28 Mar 1999 01:10:05 +0100


There is a problem with 2.2.x that makes non-blocking tty reads block.
This happens when you have multiple readers and there is already a
blocking read in progress. The "non-blocking" read blocks until the
blocking read is finished, which is illustrated by the attached C
program. Also attached is a patch that solves the problem. The patch
is against 2.2.4. The bug was introduced in 2.2.0-pre6.

Before applying the patch, the output is
Blocking read...
Non-blocking read...
and nothing more. After applying the patch, the output is
Blocking read...
Non-blocking read...
Non-blocking read: Resource temporarily unavailable
Non-blocking read done.
as it should be.

/ Tobias Ringstrom

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
char buf[100];
if (fork() == 0) {
puts("Blocking read...");
if (read(0, buf, sizeof(buf)) == -1)
perror("Blocking read");
puts("Blocking read done.");
}
else {
sleep(1);
fcntl(0, F_SETFL, O_NONBLOCK);
puts("Non-blocking read...");
if (read(0, buf, sizeof(buf)) == -1)
perror("Non-blocking read");
puts("Non-blocking read done.");
wait(NULL);
}

return 0;
}

--- n_tty.c.orig Sat Mar 27 10:29:43 1999
+++ n_tty.c Sat Mar 27 09:05:40 1999
@@ -922,8 +922,14 @@
}
}

- if (down_interruptible(&tty->atomic_read))
- return -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (down_trylock(&tty->atomic_read))
+ return -EAGAIN;
+ }
+ else {
+ if (down_interruptible(&tty->atomic_read))
+ return -ERESTARTSYS;
+ }

add_wait_queue(&tty->read_wait, &wait);
set_bit(TTY_DONT_FLIP, &tty->flags);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/