Diff below extends the existing kqfilter handlers to be able to set
POLLHUP in the new poll(2) implementation.  

__EV_HUP is introduced and now set for this purpose.  A new kqfilter
for deadfs is introduced to match the existing poll handler.

__EV_HUP is not exactly like EV_EOF.  Very few handlers set POLLHUP so
this approach is conservative.

__EV_HUP reuses the EV_FLAG1 flag which isn't used for `file_filtops'.
We could decided to set it only if __EV_POLL is set which should ensure
it is not exported to userland.  Is it desirable?

Comments?  Oks?

Index: kern/sys_pipe.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_pipe.c,v
retrieving revision 1.119
diff -u -p -r1.119 sys_pipe.c
--- kern/sys_pipe.c     7 Apr 2020 13:27:51 -0000       1.119
+++ kern/sys_pipe.c     12 Jun 2020 17:35:55 -0000
@@ -966,7 +966,7 @@ filt_piperead(struct knote *kn, long hin
        if ((rpipe->pipe_state & PIPE_EOF) || wpipe == NULL) {
                if ((hint & NOTE_SUBMIT) == 0)
                        rw_exit_read(lock);
-               kn->kn_flags |= EV_EOF; 
+               kn->kn_flags |= (EV_EOF | __EV_HUP);
                return (1);
        }
 
@@ -990,7 +990,7 @@ filt_pipewrite(struct knote *kn, long hi
                if ((hint & NOTE_SUBMIT) == 0)
                        rw_exit_read(lock);
                kn->kn_data = 0;
-               kn->kn_flags |= EV_EOF; 
+               kn->kn_flags |= (EV_EOF | __EV_HUP);
                return (1);
        }
        kn->kn_data = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
Index: kern/tty.c
===================================================================
RCS file: /cvs/src/sys/kern/tty.c,v
retrieving revision 1.156
diff -u -p -r1.156 tty.c
--- kern/tty.c  29 May 2020 04:42:25 -0000      1.156
+++ kern/tty.c  12 Jun 2020 17:35:55 -0000
@@ -1154,7 +1154,7 @@ filt_ttyread(struct knote *kn, long hint
        kn->kn_data = ttnread(tp);
        splx(s);
        if (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) {
-               kn->kn_flags |= EV_EOF;
+               kn->kn_flags |= (EV_EOF | __EV_HUP);
                return (1);
        }
        return (kn->kn_data > 0);
Index: kern/tty_pty.c
===================================================================
RCS file: /cvs/src/sys/kern/tty_pty.c,v
retrieving revision 1.99
diff -u -p -r1.99 tty_pty.c
--- kern/tty_pty.c      21 May 2020 09:34:06 -0000      1.99
+++ kern/tty_pty.c      12 Jun 2020 17:35:55 -0000
@@ -677,7 +677,7 @@ filt_ptcread(struct knote *kn, long hint
        }
 
        if (!ISSET(tp->t_state, TS_CARR_ON)) {
-               kn->kn_flags |= EV_EOF;
+               kn->kn_flags |= (EV_EOF | __EV_HUP);
                return (1);
        }
 
Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.244
diff -u -p -r1.244 uipc_socket.c
--- kern/uipc_socket.c  12 Apr 2020 16:15:18 -0000      1.244
+++ kern/uipc_socket.c  12 Jun 2020 17:35:55 -0000
@@ -2064,6 +2064,8 @@ filt_soread(struct knote *kn, long hint)
 #endif /* SOCKET_SPLICE */
        if (so->so_state & SS_CANTRCVMORE) {
                kn->kn_flags |= EV_EOF;
+               if (so->so_state & SS_ISDISCONNECTED)
+                       kn->kn_flags |= __EV_HUP;
                kn->kn_fflags = so->so_error;
                rv = 1;
        } else if (so->so_error) {      /* temporary udp error */
@@ -2102,6 +2104,8 @@ filt_sowrite(struct knote *kn, long hint
        kn->kn_data = sbspace(so, &so->so_snd);
        if (so->so_state & SS_CANTSENDMORE) {
                kn->kn_flags |= EV_EOF;
+               if (so->so_state & SS_ISDISCONNECTED)
+                       kn->kn_flags |= __EV_HUP;
                kn->kn_fflags = so->so_error;
                rv = 1;
        } else if (so->so_error) {      /* temporary udp error */
Index: miscfs/fifofs/fifo_vnops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/fifofs/fifo_vnops.c,v
retrieving revision 1.76
diff -u -p -r1.76 fifo_vnops.c
--- miscfs/fifofs/fifo_vnops.c  8 Apr 2020 08:07:52 -0000       1.76
+++ miscfs/fifofs/fifo_vnops.c  12 Jun 2020 17:35:55 -0000
@@ -559,6 +559,8 @@ filt_fiforead(struct knote *kn, long hin
        kn->kn_data = so->so_rcv.sb_cc;
        if (so->so_state & SS_CANTRCVMORE) {
                kn->kn_flags |= EV_EOF;
+               if (so->so_state & SS_ISDISCONNECTED)
+                       kn->kn_flags |= __EV_HUP;
                rv = 1;
        } else {
                kn->kn_flags &= ~EV_EOF;
Index: sys/event.h
===================================================================
RCS file: /cvs/src/sys/sys/event.h,v
retrieving revision 1.41
diff -u -p -r1.41 event.h
--- sys/event.h 12 Jun 2020 09:34:17 -0000      1.41
+++ sys/event.h 12 Jun 2020 17:35:55 -0000
@@ -75,6 +75,7 @@ struct kevent {
 
 #define EV_SYSFLAGS    0xF000          /* reserved by system */
 #define __EV_POLL      0x1000          /* match behavior of poll & select */
+#define __EV_HUP       EV_FLAG1        /* device or socket disconnected */
 #define EV_FLAG1       0x2000          /* filter-specific flag */
 
 /* returned values */
Index: miscfs/deadfs/dead_vnops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/deadfs/dead_vnops.c,v
retrieving revision 1.32
diff -u -p -r1.32 dead_vnops.c
--- miscfs/deadfs/dead_vnops.c  20 Jan 2020 23:21:56 -0000      1.32
+++ miscfs/deadfs/dead_vnops.c  12 Jun 2020 17:35:55 -0000
@@ -34,6 +34,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/event.h>
 #include <sys/time.h>
 #include <sys/vnode.h>
 #include <sys/lock.h>
@@ -52,6 +53,7 @@ int   dead_read(void *);
 int    dead_write(void *);
 int    dead_ioctl(void *);
 int    dead_poll(void *);
+int    dead_kqfilter(void *v);
 int    dead_inactive(void *);
 int    dead_lock(void *);
 int    dead_bmap(void *);
@@ -73,6 +75,7 @@ const struct vops dead_vops = {
        .vop_write      = dead_write,
        .vop_ioctl      = dead_ioctl,
        .vop_poll       = dead_poll,
+       .vop_kqfilter   = dead_kqfilter,
        .vop_fsync      = nullop,
        .vop_remove     = dead_badop,
        .vop_link       = dead_badop,
@@ -165,6 +168,45 @@ dead_poll(void *v)
         * Let the user find out that the descriptor is gone.
         */
        return (POLLHUP);
+}
+
+void
+filt_deaddetach(struct knote *kn)
+{
+}
+
+int
+filt_deadrw(struct knote *kn, long hint)
+{
+       /*
+        * Let the user find out that the descriptor is gone.
+        */
+       kn->kn_flags |= __EV_HUP;
+       return (1);
+}
+
+const struct filterops deadrw_filtops = {
+       .f_flags        = FILTEROP_ISFD,
+       .f_attach       = NULL,
+       .f_detach       = filt_deaddetach,
+       .f_event        = filt_deadrw,
+};
+
+int
+dead_kqfilter(void *v)
+{
+       struct vop_kqfilter_args *ap = v;
+
+       switch (ap->a_kn->kn_filter) {
+       case EVFILT_READ:
+       case EVFILT_WRITE:
+               ap->a_kn->kn_fop = &deadrw_filtops;
+               break;
+       default:
+               return (EINVAL);
+       }
+
+       return (0);
 }
 
 /*

Reply via email to