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 majord...@freebsd.org
with "unsubscribe freebsd-current" in the body of the message

Reply via email to