Messages in this thread Patch in this message | ![/](/images/icornerl.gif) | | Date | Mon, 20 Dec 1999 01:33:57 +0100 (MET) | From | Markus Schoder <> | Subject | Weird behaviour of Named Pipes |
| |
There is a weirdness with FIFOs (named pipes) and Linux 2.3.33 (probably older kernels too) when doing the following
Terminal 1:
$ mkfifo /tmp/f $ cat /tmp/f
Terminal 2:
$ echo hello >/tmp/f
I would have expected that the cat does now produce `hello' instead it just sits there (most of the time). After several echo invocations the cat will output everything at once and then exit.
I don't have the POSIX specs but this behaviour looks weird.
The reason for this behaviour is a race condition in fifo_open which the following patch attempts to fix. Note that this race condition is probably much more likely to trigger on an UP system.
What happens is that between the interruptible_sleep_on call of the reader (the cat command in the example) an the down for the pipe semaphore, the writer (the echo command) does write to the pipe and close the pipe. The reader then checks the writer count, finds it to be zero and continues to sleep.
The patch changes this bevaviour so that the reader successfully completes the open even if no writer is present anymore relying on the fact that a writer must have been present for the wakeup of the reader to occur.
(Please reply by email since I currently don't have access to the mailing list).
-- Markus
--- fifo.c.old Mon Dec 20 00:36:33 1999 +++ fifo.c Mon Dec 20 00:38:39 1999 @@ -55,17 +55,13 @@ wake_up_interruptible(PIPE_WAIT(*inode)); if (!(filp->f_flags & O_NONBLOCK)) { - while (!PIPE_WRITERS(*inode)) { + if (!PIPE_WRITERS(*inode)) { if (signal_pending(current)) goto err_rd; + filp->f_op = &read_fifo_fops; up(PIPE_SEM(*inode)); interruptible_sleep_on(PIPE_WAIT(*inode)); - - /* Note that using down_interruptible here - and similar places below is pointless, - since we have to acquire the lock to clean - up properly. */ - down(PIPE_SEM(*inode)); + return 0; } } @@ -87,12 +83,12 @@ if (!PIPE_WRITERS(*inode)++) wake_up_interruptible(PIPE_WAIT(*inode)); - while (!PIPE_READERS(*inode)) { + if (!PIPE_READERS(*inode)) { if (signal_pending(current)) goto err_wr; up(PIPE_SEM(*inode)); interruptible_sleep_on(PIPE_WAIT(*inode)); - down(PIPE_SEM(*inode)); + return 0; } break;
- 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/
| ![\](/images/icornerr.gif) |