diff options
author | Matthew Dillon <dillon@FreeBSD.org> | 2000-03-24 00:47:37 +0000 |
---|---|---|
committer | Matthew Dillon <dillon@FreeBSD.org> | 2000-03-24 00:47:37 +0000 |
commit | f1924a54f82340bd3ffe1da32e523a76ed1b3fec (patch) | |
tree | 64c8bb6e3d391367d9e1dac950dc50bab8fa150a /sys/kern/sys_pipe.c | |
parent | b541ae06bd1047ad98f175e552cf9e365e4da070 (diff) | |
download | src-f1924a54f82340bd3ffe1da32e523a76ed1b3fec.tar.gz src-f1924a54f82340bd3ffe1da32e523a76ed1b3fec.zip |
Fix in-kernel infinite loop in pipe_write() when the reader goes away
at just the wrong time.
Notes
Notes:
svn path=/head/; revision=58505
Diffstat (limited to 'sys/kern/sys_pipe.c')
-rw-r--r-- | sys/kern/sys_pipe.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index b82f91d5e6dd..a181b5a70e49 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -766,6 +766,9 @@ pipe_write(fp, uio, cred, flags, p) * we do process-to-process copies directly. * If the write is non-blocking, we don't use the * direct write mechanism. + * + * The direct write mechanism will detect the reader going + * away on us. */ if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) && (fp->f_flag & FNONBLOCK) == 0 && @@ -783,7 +786,8 @@ pipe_write(fp, uio, cred, flags, p) * Pipe buffered writes cannot be coincidental with * direct writes. We wait until the currently executing * direct write is completed before we start filling the - * pipe buffer. + * pipe buffer. We break out if a signal occurs or the + * reader goes away. */ retrywrite: while (wpipe->pipe_state & PIPE_DIRECTW) { @@ -791,11 +795,16 @@ pipe_write(fp, uio, cred, flags, p) wpipe->pipe_state &= ~PIPE_WANTR; wakeup(wpipe); } - error = tsleep(wpipe, - PRIBIO|PCATCH, "pipbww", 0); + error = tsleep(wpipe, PRIBIO|PCATCH, "pipbww", 0); + if (wpipe->pipe_state & PIPE_EOF) + break; if (error) break; } + if (wpipe->pipe_state & PIPE_EOF) { + error = EPIPE; + break; + } space = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt; @@ -818,6 +827,9 @@ pipe_write(fp, uio, cred, flags, p) /* * If a process blocked in uiomove, our * value for space might be bad. + * + * XXX will we be ok if the reader has gone + * away here? */ if (space > wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) { |