Another, better, fix for PR/26567.

Only sleep once within each pipe_read/pipe_write call.
If there is no data/space available after we wakeup return ERESTART so
then the 'fd' number is validated again.
A simple broadcast of the cvs is then enough to evict the correct threads
when close() is called from an active thread.
This commit is contained in:
dsl 2009-12-13 20:02:23 +00:00
parent 0a60906620
commit 723a159171
1 changed files with 18 additions and 2 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_pipe.c,v 1.124 2009/12/13 18:27:02 dsl Exp $ */
/* $NetBSD: sys_pipe.c,v 1.125 2009/12/13 20:02:23 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.124 2009/12/13 18:27:02 dsl Exp $");
__KERNEL_RCSID(0, "$NetBSD: sys_pipe.c,v 1.125 2009/12/13 20:02:23 dsl Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -449,6 +449,7 @@ pipe_read(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
size_t nread = 0;
size_t size;
size_t ocnt;
int slept = 0;
mutex_enter(lock);
++rpipe->pipe_busy;
@ -566,6 +567,7 @@ again:
if ((rpipe->pipe_state & PIPE_DIRECTR) != 0)
goto again;
#if 1 /* XXX (dsl) I'm sure these aren't needed here ... */
/*
* We want to read more, wake up select/poll.
*/
@ -575,11 +577,18 @@ again:
* If the "write-side" is blocked, wake it up now.
*/
cv_broadcast(&rpipe->pipe_wcv);
#endif
if (slept) {
error = ERESTART;
goto unlocked_error;
}
/* Now wait until the pipe is filled */
error = cv_wait_sig(&rpipe->pipe_rcv, lock);
if (error != 0)
goto unlocked_error;
slept = 1;
goto again;
}
@ -814,6 +823,7 @@ pipe_write(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
struct pipebuf *bp;
kmutex_t *lock;
int error;
int slept = 0;
/* We want to write to our peer */
rpipe = (struct pipe *) fp->f_data;
@ -987,6 +997,11 @@ pipe_write(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
if (bp->cnt)
pipeselwakeup(wpipe, wpipe, POLL_IN);
if (slept) {
error = ERESTART;
break;
}
pipeunlock(wpipe);
error = cv_wait_sig(&wpipe->pipe_wcv, lock);
(void)pipelock(wpipe, 0);
@ -1000,6 +1015,7 @@ pipe_write(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
error = EPIPE;
break;
}
slept = 1;
}
}