diff options
author | jilles <jilles@FreeBSD.org> | 2011-12-14 22:26:39 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2011-12-14 22:26:39 +0000 |
commit | 5200c1964bcd8905b74260534dc719cfa71cebde (patch) | |
tree | 52674120d1f22b4d3cf93f3c2fceb4ab1105f459 /sys/kern/sys_pipe.c | |
parent | 6d1299a388490b22f5d0619237868efafa3f3428 (diff) | |
download | FreeBSD-src-5200c1964bcd8905b74260534dc719cfa71cebde.zip FreeBSD-src-5200c1964bcd8905b74260534dc719cfa71cebde.tar.gz |
Fix select/poll/kqueue for write on reverse direction before first write.
The reverse direction of a pipe is lazily allocated on the first write in
that direction (because pipes are usually used in one direction only). A
special case is needed to ensure the pipe appears writable before the first
write because there are 0 bytes of pending data in 0 bytes of buffer space
at that point, leaving 0 bytes of data that can be written with the normal
code.
Note that the first write returns [ENOMEM] if kern.ipc.maxpipekva is
exceeded and does not block or return [EAGAIN], so selecting true for write
is correct even in that case.
PR: kern/93685
Submitted by: gianni
MFC after: 2 weeks
Diffstat (limited to 'sys/kern/sys_pipe.c')
-rw-r--r-- | sys/kern/sys_pipe.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 9a4448a..9edcb74 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1349,7 +1349,8 @@ pipe_poll(fp, events, active_cred, td) if (wpipe->pipe_present != PIPE_ACTIVE || (wpipe->pipe_state & PIPE_EOF) || (((wpipe->pipe_state & PIPE_DIRECTW) == 0) && - (wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF)) + ((wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF || + wpipe->pipe_buffer.size == 0))) revents |= events & (POLLOUT | POLLWRNORM); if ((events & POLLINIGNEOF) == 0) { @@ -1660,7 +1661,8 @@ filt_pipewrite(struct knote *kn, long hint) PIPE_UNLOCK(rpipe); return (1); } - kn->kn_data = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt; + kn->kn_data = (wpipe->pipe_buffer.size > 0) ? + (wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) : PIPE_BUF; if (wpipe->pipe_state & PIPE_DIRECTW) kn->kn_data = 0; |