Skip site navigation (1)Skip section navigation (2)
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>