diff options
author | kib <kib@FreeBSD.org> | 2009-07-07 09:43:44 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2009-07-07 09:43:44 +0000 |
commit | 6c6bda868d12c26d6e0fe65000f5f3c00d0112d7 (patch) | |
tree | fa963c164b557f57ea4c0183ad1527b57d286d89 /sys/kern | |
parent | c59ed917ab6692f0644e851cf9485261d36789fa (diff) | |
download | FreeBSD-src-6c6bda868d12c26d6e0fe65000f5f3c00d0112d7.zip FreeBSD-src-6c6bda868d12c26d6e0fe65000f5f3c00d0112d7.tar.gz |
Fix poll(2) and select(2) for named pipes to return "ready for read"
when all writers, observed by reader, exited. Use writer generation
counter for fifo, and store the snapshot of the fifo generation in the
f_seqcount field of struct file, that is otherwise unused for fifos.
Set FreeBSD-undocumented POLLINIGNEOF flag only when file f_seqcount is
equal to fifo' fi_wgen, and revert r89376.
Fix POLLINIGNEOF for sockets and pipes, and return POLLHUP for them.
Note that the patch does not fix not returning POLLHUP for fifos.
PR: kern/94772
Submitted by: bde (original version)
Reviewed by: rwatson, jilles
Approved by: re (kensmith)
MFC after: 6 weeks (might be)
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/sys_pipe.c | 15 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 19 |
2 files changed, 19 insertions, 15 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 45dc0f6..ce20d28 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1353,8 +1353,7 @@ pipe_poll(fp, events, active_cred, td) #endif if (events & (POLLIN | POLLRDNORM)) if ((rpipe->pipe_state & PIPE_DIRECTW) || - (rpipe->pipe_buffer.cnt > 0) || - (rpipe->pipe_state & PIPE_EOF)) + (rpipe->pipe_buffer.cnt > 0)) revents |= events & (POLLIN | POLLRDNORM); if (events & (POLLOUT | POLLWRNORM)) @@ -1364,10 +1363,14 @@ pipe_poll(fp, events, active_cred, td) (wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF)) revents |= events & (POLLOUT | POLLWRNORM); - if ((rpipe->pipe_state & PIPE_EOF) || - wpipe->pipe_present != PIPE_ACTIVE || - (wpipe->pipe_state & PIPE_EOF)) - revents |= POLLHUP; + if ((events & POLLINIGNEOF) == 0) { + if (rpipe->pipe_state & PIPE_EOF) { + revents |= (events & (POLLIN | POLLRDNORM)); + if (wpipe->pipe_present != PIPE_ACTIVE || + (wpipe->pipe_state & PIPE_EOF)) + revents |= POLLHUP; + } + } if (revents == 0) { if (events & (POLLIN | POLLRDNORM)) { diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index ecb1b7b..62550b2 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -2885,14 +2885,9 @@ sopoll_generic(struct socket *so, int events, struct ucred *active_cred, SOCKBUF_LOCK(&so->so_snd); SOCKBUF_LOCK(&so->so_rcv); if (events & (POLLIN | POLLRDNORM)) - if (soreadable(so)) + if (soreadabledata(so)) revents |= events & (POLLIN | POLLRDNORM); - if (events & POLLINIGNEOF) - if (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat || - !TAILQ_EMPTY(&so->so_comp) || so->so_error) - revents |= POLLINIGNEOF; - if (events & (POLLOUT | POLLWRNORM)) if (sowriteable(so)) revents |= events & (POLLOUT | POLLWRNORM); @@ -2901,10 +2896,16 @@ sopoll_generic(struct socket *so, int events, struct ucred *active_cred, if (so->so_oobmark || (so->so_rcv.sb_state & SBS_RCVATMARK)) revents |= events & (POLLPRI | POLLRDBAND); + if ((events & POLLINIGNEOF) == 0) { + if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { + revents |= events & (POLLIN | POLLRDNORM); + if (so->so_snd.sb_state & SBS_CANTSENDMORE) + revents |= POLLHUP; + } + } + if (revents == 0) { - if (events & - (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | - POLLRDBAND)) { + if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) { selrecord(td, &so->so_rcv.sb_sel); so->so_rcv.sb_flags |= SB_SEL; } |