From owner-svn-src-all@FreeBSD.ORG Tue Jul 31 02:00:38 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 07EF2106564A; Tue, 31 Jul 2012 02:00:38 +0000 (UTC) (envelope-from davidxu@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E65B08FC08; Tue, 31 Jul 2012 02:00:37 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q6V20bpt073158; Tue, 31 Jul 2012 02:00:37 GMT (envelope-from davidxu@svn.freebsd.org) Received: (from davidxu@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q6V20bJR073154; Tue, 31 Jul 2012 02:00:37 GMT (envelope-from davidxu@svn.freebsd.org) Message-Id: <201207310200.q6V20bJR073154@svn.freebsd.org> From: David Xu Date: Tue, 31 Jul 2012 02:00:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r238928 - in head/sys: fs/fifofs kern sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 31 Jul 2012 02:00:38 -0000 Author: davidxu Date: Tue Jul 31 02:00:37 2012 New Revision: 238928 URL: http://svn.freebsd.org/changeset/base/238928 Log: When a thread is blocked in direct write state, it only sets PIPE_DIRECTW flag but not PIPE_WANTW, but FIFO pipe code does not understand this internal state, when a FIFO peer reader closes the pipe, it wants to notify the writer, it checks PIPE_WANTW, if not set, it skips calling wakeup(), so blocked writer never noticed the case, but in general, the writer should return from the syscall with EPIPE error code and may get SIGPIPE signal. Setting the PIPE_WANTW fixed problem, or you can turn off direct write, it should fix the problem too. This bug is found by PR/170203. Another bug in FIFO pipe code is when peer closes the pipe, another end which is being blocked in select() or poll() is not notified, it missed to call pipeselwakeup(). Third problem is found in poll regression test, the existing code can not pass 6b,6c,6d tests, but FreeBSD-4 works. This commit does not fix the problem, I still need to study more to find the cause. PR: 170203 Tested by: Garrett Copper < yanegomi at gmail dot com > Modified: head/sys/fs/fifofs/fifo_vnops.c head/sys/kern/sys_pipe.c head/sys/sys/pipe.h Modified: head/sys/fs/fifofs/fifo_vnops.c ============================================================================== --- head/sys/fs/fifofs/fifo_vnops.c Tue Jul 31 00:46:19 2012 (r238927) +++ head/sys/fs/fifofs/fifo_vnops.c Tue Jul 31 02:00:37 2012 (r238928) @@ -283,8 +283,11 @@ fifo_close(ap) if (fip->fi_readers == 0) { PIPE_LOCK(cpipe); cpipe->pipe_state |= PIPE_EOF; - if (cpipe->pipe_state & PIPE_WANTW) + if ((cpipe->pipe_state & PIPE_WANTW)) { + cpipe->pipe_state &= ~PIPE_WANTW; wakeup(cpipe); + } + pipeselwakeup(cpipe); PIPE_UNLOCK(cpipe); } } @@ -293,10 +296,13 @@ fifo_close(ap) if (fip->fi_writers == 0) { PIPE_LOCK(cpipe); cpipe->pipe_state |= PIPE_EOF; - if (cpipe->pipe_state & PIPE_WANTR) + if ((cpipe->pipe_state & PIPE_WANTR)) { + cpipe->pipe_state &= ~PIPE_WANTR; wakeup(cpipe); + } fip->fi_wgen++; FIFO_UPDWGEN(fip, cpipe); + pipeselwakeup(cpipe); PIPE_UNLOCK(cpipe); } } Modified: head/sys/kern/sys_pipe.c ============================================================================== --- head/sys/kern/sys_pipe.c Tue Jul 31 00:46:19 2012 (r238927) +++ head/sys/kern/sys_pipe.c Tue Jul 31 02:00:37 2012 (r238928) @@ -227,7 +227,6 @@ static int pipe_create(struct pipe *pipe static int pipe_paircreate(struct thread *td, struct pipepair **p_pp); static __inline int pipelock(struct pipe *cpipe, int catch); static __inline void pipeunlock(struct pipe *cpipe); -static __inline void pipeselwakeup(struct pipe *cpipe); #ifndef PIPE_NODIRECT static int pipe_build_write_buffer(struct pipe *wpipe, struct uio *uio); static void pipe_destroy_write_buffer(struct pipe *wpipe); @@ -607,7 +606,7 @@ pipeunlock(cpipe) } } -static __inline void +void pipeselwakeup(cpipe) struct pipe *cpipe; { @@ -738,7 +737,7 @@ pipe_read(fp, uio, active_cred, flags, t rpipe->pipe_map.pos += size; rpipe->pipe_map.cnt -= size; if (rpipe->pipe_map.cnt == 0) { - rpipe->pipe_state &= ~PIPE_DIRECTW; + rpipe->pipe_state &= ~(PIPE_DIRECTW|PIPE_WANTW); wakeup(rpipe); } #endif @@ -1001,6 +1000,7 @@ retry: wakeup(wpipe); } pipeselwakeup(wpipe); + wpipe->pipe_state |= PIPE_WANTW; pipeunlock(wpipe); error = msleep(wpipe, PIPE_MTX(wpipe), PRIBIO | PCATCH, "pipdwt", 0); Modified: head/sys/sys/pipe.h ============================================================================== --- head/sys/sys/pipe.h Tue Jul 31 00:46:19 2012 (r238927) +++ head/sys/sys/pipe.h Tue Jul 31 02:00:37 2012 (r238928) @@ -143,5 +143,5 @@ struct pipepair { void pipe_dtor(struct pipe *dpipe); int pipe_named_ctor(struct pipe **ppipe, struct thread *td); - +void pipeselwakeup(struct pipe *cpipe); #endif /* !_SYS_PIPE_H_ */