From owner-freebsd-current Thu Feb 4 16:32:36 1999 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id QAA21189 for freebsd-current-outgoing; Thu, 4 Feb 1999 16:32:36 -0800 (PST) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from alpo.whistle.com (alpo.whistle.com [207.76.204.38]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id QAA21180 for ; Thu, 4 Feb 1999 16:32:33 -0800 (PST) (envelope-from julian@whistle.com) Received: (from daemon@localhost) by alpo.whistle.com (8.8.5/8.8.5) id QAA11097; Thu, 4 Feb 1999 16:30:56 -0800 (PST) Received: from current1.whistle.com(207.76.205.22) via SMTP by alpo.whistle.com, id smtpdP11061; Fri Feb 5 00:30:52 1999 Message-ID: <36BA3B93.2781E494@whistle.com> Date: Thu, 04 Feb 1999 16:30:11 -0800 From: Julian Elischer Organization: Whistle Communications X-Mailer: Mozilla 3.0Gold (X11; I; FreeBSD 2.2.8-RELEASE i386) MIME-Version: 1.0 To: Matthew Dillon CC: current@FreeBSD.ORG Subject: Re: Bug in piperd References: <199902042219.OAA90785@apollo.backplane.com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG I've been seeng lockups in 3.0 where as is in piperd, but the stack trace has always looked as if the problem was in soft updates or the syncer daemon.. Matthew Dillon wrote: > > Ha. I've been slowly reducing MAXMEM on my test box to force it to > swap more heavily running buildworld and found a race in the > kern/sys_pipe.c module. > > My buildworld froze up... i.e. just stopped running. Everything else > on the box was fine. ps showed an 'as' command stuck in 'piperd'. > > The problem is simple (pseudo code fragment): > > pipe read: > ... > * check for EOF > * check for waiting writers > * lock the pipe > * check for waiting writers > * check for non-blocking I/O > * sleep in 'piperd' > > The problem, of course, is that if 'lock the pipe' blocks, it is possible > for the writer side to close the pipe. Since EOF is not checked for > after the pipe has been locked, the reader enters a 'piperd' state > and never gets woken up again. > > I am testing a fix now and will then commit it. > > If anyone sees anything obviously wrong with this patch, please email me. > > -Matt > Matthew Dillon > > > 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:14:58 > @@ -381,12 +381,32 @@ > #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); > + } > + > + /* > * 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 +414,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 To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message