This patch adjusts the EVFILT_EXCEPT code of sockets and FIFOs so that
it would raise the HUP condition only when the channel has been closed
from both sides. This should match better with the POLLHUP case of
soo_poll() and fifo_poll().

The "poll index ... unclaimed" error seen by some was related to this.
With pfd[i].events = 0, the EVFILT_EXCEPT filter triggered prematurely
when the socket was only half-closed.

When comparing the code, note that POLL_NOHUP was set by the old
select(2) code with writefds. The kqueue-based code achieves the same
effect with FIFOs by not raising HUP in filt_fifowrite().

The resulting code is possibly overly contrived. The SS_CANTRCVMORE
condition alone is irrelevant for poll and select. It could be removed
to simplify the code, but then socket and FIFO's EVFILT_EXCEPT would
behave inconsistently relative to EV_EOF. However, only NOTE_OOB has
been documented and it skips SS_CANTRCVMORE...

OK?

Index: kern/uipc_socket.c
===================================================================
RCS file: src/sys/kern/uipc_socket.c,v
retrieving revision 1.269
diff -u -p -r1.269 uipc_socket.c
--- kern/uipc_socket.c  11 Nov 2021 16:35:09 -0000      1.269
+++ kern/uipc_socket.c  6 Dec 2021 16:04:55 -0000
@@ -2265,12 +2265,17 @@ filt_soexcept_common(struct knote *kn, s
                }
        } else if (so->so_state & SS_CANTRCVMORE) {
                kn->kn_flags |= EV_EOF;
-               if (kn->kn_flags & __EV_POLL) {
-                       if (so->so_state & SS_ISDISCONNECTED)
-                               kn->kn_flags |= __EV_HUP;
-               }
                kn->kn_fflags = so->so_error;
-               rv = 1;
+               if ((kn->kn_flags & __EV_POLL) == 0)
+                       rv = 1;
+       }
+
+       if (kn->kn_flags & __EV_POLL) {
+               /* Indicate HUP only when the socket is fully closed. */
+               if (so->so_state & SS_ISDISCONNECTED) {
+                       kn->kn_flags |= __EV_HUP;
+                       rv = 1;
+               }
        }
 
        return rv;
Index: miscfs/fifofs/fifo_vnops.c
===================================================================
RCS file: src/sys/miscfs/fifofs/fifo_vnops.c,v
retrieving revision 1.85
diff -u -p -r1.85 fifo_vnops.c
--- miscfs/fifofs/fifo_vnops.c  24 Oct 2021 11:23:22 -0000      1.85
+++ miscfs/fifofs/fifo_vnops.c  6 Dec 2021 16:04:55 -0000
@@ -702,11 +702,16 @@ filt_fifoexcept_common(struct knote *kn,
 
        if (so->so_state & SS_CANTRCVMORE) {
                kn->kn_flags |= EV_EOF;
-               if (kn->kn_flags & __EV_POLL) {
-                       if (so->so_state & SS_ISDISCONNECTED)
-                               kn->kn_flags |= __EV_HUP;
+               if ((kn->kn_flags & __EV_POLL) == 0)
+                       rv = 1;
+       }
+
+       if (kn->kn_flags & __EV_POLL) {
+               /* Indicate HUP only when the FIFO is fully closed. */
+               if (so->so_state & SS_ISDISCONNECTED) {
+                       kn->kn_flags |= __EV_HUP;
+                       rv = 1;
                }
-               rv = 1;
        }
 
        return (rv);

Reply via email to