Module Name: src Committed By: dsl Date: Sat Dec 12 21:28:04 UTC 2009
Modified Files: src/sys/kern: sys_pipe.c src/sys/sys: pipe.h Log Message: Add support for unblocking read/write when close called. Fixes PR/26567 for pipes. (NB ad backed out the fix for sockets) To generate a diff of this commit: cvs rdiff -u -r1.122 -r1.123 src/sys/kern/sys_pipe.c cvs rdiff -u -r1.29 -r1.30 src/sys/sys/pipe.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/sys_pipe.c diff -u src/sys/kern/sys_pipe.c:1.122 src/sys/kern/sys_pipe.c:1.123 --- src/sys/kern/sys_pipe.c:1.122 Thu Dec 10 20:55:17 2009 +++ src/sys/kern/sys_pipe.c Sat Dec 12 21:28:04 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_pipe.c,v 1.122 2009/12/10 20:55:17 dsl Exp $ */ +/* $NetBSD: sys_pipe.c,v 1.123 2009/12/12 21:28:04 dsl Exp $ */ /*- * Copyright (c) 2003, 2007, 2008, 2009 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_pipe.c,v 1.122 2009/12/10 20:55:17 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_pipe.c,v 1.123 2009/12/12 21:28:04 dsl Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -109,6 +109,7 @@ static int pipe_kqfilter(file_t *, struct knote *); static int pipe_stat(file_t *, struct stat *); static int pipe_ioctl(file_t *, u_long, void *); +static void pipe_abort(file_t *); static const struct fileops pipeops = { .fo_read = pipe_read, @@ -119,7 +120,7 @@ .fo_stat = pipe_stat, .fo_close = pipe_close, .fo_kqfilter = pipe_kqfilter, - .fo_abort = fnullop_abort, + .fo_abort = pipe_abort, }; /* @@ -541,8 +542,12 @@ * Detect EOF condition. * Read returns 0 on EOF, no need to set error. */ - if (rpipe->pipe_state & PIPE_EOF) + if (rpipe->pipe_state & (PIPE_EOF | PIPE_ABORTED)) { + if (rpipe->pipe_state & PIPE_ABORTED) + /* Another thread has called close() */ + error = EBADF; break; + } /* * Don't block on non-blocking I/O. @@ -979,6 +984,13 @@ break; } + if (wpipe->pipe_state & PIPE_ABORTED) { + /* Another thread has called close() */ + if (uio->uio_resid == 0) + error = EBADF; + break; + } + /* * We have no more space and have something to offer, * wake up select/poll. @@ -1204,6 +1216,19 @@ } static void +pipe_abort(file_t *fp) +{ + struct pipe *pipe = fp->f_data; + + /* Unblock blocked reads/writes - they will return EBADF. */ + mutex_enter(pipe->pipe_lock); + pipe->pipe_state |= PIPE_ABORTED; + cv_broadcast(&pipe->pipe_rcv); + cv_broadcast(&pipe->pipe_wcv); + mutex_exit(pipe->pipe_lock); +} + +static void pipe_free_kmem(struct pipe *pipe) { Index: src/sys/sys/pipe.h diff -u src/sys/sys/pipe.h:1.29 src/sys/sys/pipe.h:1.30 --- src/sys/sys/pipe.h:1.29 Thu Nov 26 16:18:37 2009 +++ src/sys/sys/pipe.h Sat Dec 12 21:28:04 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: pipe.h,v 1.29 2009/11/26 16:18:37 pooka Exp $ */ +/* $NetBSD: pipe.h,v 1.30 2009/12/12 21:28:04 dsl Exp $ */ /* * Copyright (c) 1996 John S. Dyson @@ -96,6 +96,7 @@ pointers/data. */ #define PIPE_LWANT 0x200 /* Process wants exclusive access to pointers/data. */ +#define PIPE_ABORTED 0x400 /* fo_abort()ed, unblock read/write */ /* * Per-pipe data structure.