Date: Thu, 4 Feb 1999 14:30:26 -0800 (PST) From: Matthew Dillon <dillon@apollo.backplane.com> To: current@FreeBSD.ORG Subject: Re: Bug in piperd Message-ID: <199902042230.OAA90906@apollo.backplane.com> References: <199902042219.OAA90785@apollo.backplane.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Updated patch - one must also check to see if any new data has
entered the pipe after locking it in case the lock blocked.
( this patch FYI only, the problem occurs unoften enough that
you can afford to wait until I commit it ).
-Matt
Index: sys_pipe.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sys_pipe.c,v
retrieving revision 1.49
diff -u -r1.49 sys_pipe.c
--- sys_pipe.c 1999/01/28 00:57:47 1.49
+++ sys_pipe.c 1999/02/04 22:24:42
@@ -381,12 +381,39 @@
#endif
} else {
/*
+ * If there is no more to read in the pipe, reset
+ * its pointers to the beginning. This improves
+ * cache hit stats.
+ *
+ * We get this over with now because it may block
+ * and cause the state to change out from under us,
+ * rather then have to re-test the state both before
+ * and after this fragment.
+ */
+
+ if ((error = pipelock(rpipe,1)) == 0) {
+ if (rpipe->pipe_buffer.cnt == 0) {
+ rpipe->pipe_buffer.in = 0;
+ rpipe->pipe_buffer.out = 0;
+ }
+ pipeunlock(rpipe);
+
+ /*
+ * If pipe filled up due to pipelock
+ * blocking, loop back up.
+ */
+ if (rpipe->pipe_buffer.cnt > 0)
+ continue;
+ }
+
+ /*
* detect EOF condition
*/
if (rpipe->pipe_state & PIPE_EOF) {
/* XXX error = ? */
break;
}
+
/*
* If the "write-side" has been blocked, wake it up now.
*/
@@ -394,34 +421,26 @@
rpipe->pipe_state &= ~PIPE_WANTW;
wakeup(rpipe);
}
- if (nread > 0)
+
+ /*
+ * break if error (signal via pipelock), or if some
+ * data was read
+ */
+ if (error || nread > 0)
break;
+ /*
+ * Handle non-blocking mode operation
+ */
+
if (fp->f_flag & FNONBLOCK) {
error = EAGAIN;
break;
}
/*
- * If there is no more to read in the pipe, reset
- * its pointers to the beginning. This improves
- * cache hit stats.
+ * Wait for more data
*/
-
- if ((error = pipelock(rpipe,1)) == 0) {
- if (rpipe->pipe_buffer.cnt == 0) {
- rpipe->pipe_buffer.in = 0;
- rpipe->pipe_buffer.out = 0;
- }
- pipeunlock(rpipe);
- } else {
- break;
- }
-
- if (rpipe->pipe_state & PIPE_WANTW) {
- rpipe->pipe_state &= ~PIPE_WANTW;
- wakeup(rpipe);
- }
rpipe->pipe_state |= PIPE_WANTR;
if ((error = tsleep(rpipe, PRIBIO|PCATCH, "piperd", 0)) != 0) {
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199902042230.OAA90906>
