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);
}
/*