From 0650ab1ab46675585b0d7493c0601701a8c8dd3f Mon Sep 17 00:00:00 2001 From: mpi Date: Fri, 22 Oct 2021 15:11:32 +0000 Subject: [PATCH] Make EVFILT_EXCEPT handling separate from the read filter. This is a change of behavior and events wont be generated if there is something to read on the fd. Only EV_EOF or NOTE_OOB will now be reported. While here a new filter for FIFOs supporting EV_EOF and __EV_HUP. ok visa@ --- sys/kern/tty_pty.c | 43 +++++++++++----- sys/kern/uipc_socket.c | 91 ++++++++++++++++++++++++++++++---- sys/miscfs/fifofs/fifo_vnops.c | 79 ++++++++++++++++++++++++++++- 3 files changed, 189 insertions(+), 24 deletions(-) diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index 660a2e86a9b..42eb39e2eb9 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty_pty.c,v 1.108 2021/02/08 09:18:30 claudio Exp $ */ +/* $OpenBSD: tty_pty.c,v 1.109 2021/10/22 15:11:32 mpi Exp $ */ /* $NetBSD: tty_pty.c,v 1.33.4.1 1996/06/02 09:08:11 mrg Exp $ */ /* @@ -107,6 +107,7 @@ void filt_ptcrdetach(struct knote *); int filt_ptcread(struct knote *, long); void filt_ptcwdetach(struct knote *); int filt_ptcwrite(struct knote *, long); +int filt_ptcexcept(struct knote *, long); static struct pt_softc **ptyarralloc(int); static int check_pty(int); @@ -670,16 +671,6 @@ filt_ptcread(struct knote *kn, long hint) tp = pti->pt_tty; kn->kn_data = 0; - if (kn->kn_sfflags & NOTE_OOB) { - /* If in packet or user control mode, check for data. */ - if (((pti->pt_flags & PF_PKT) && pti->pt_send) || - ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) { - kn->kn_fflags |= NOTE_OOB; - kn->kn_data = 1; - return (1); - } - return (0); - } if (ISSET(tp->t_state, TS_ISOPEN)) { if (!ISSET(tp->t_state, TS_TTSTOP)) kn->kn_data = tp->t_outq.c_cc; @@ -731,6 +722,34 @@ filt_ptcwrite(struct knote *kn, long hint) return (kn->kn_data > 0); } +int +filt_ptcexcept(struct knote *kn, long hint) +{ + struct pt_softc *pti = (struct pt_softc *)kn->kn_hook; + struct tty *tp; + + tp = pti->pt_tty; + + if (kn->kn_sfflags & NOTE_OOB) { + /* If in packet or user control mode, check for data. */ + if (((pti->pt_flags & PF_PKT) && pti->pt_send) || + ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) { + kn->kn_fflags |= NOTE_OOB; + kn->kn_data = 1; + return (1); + } + return (0); + } + if (!ISSET(tp->t_state, TS_CARR_ON)) { + kn->kn_flags |= EV_EOF; + if (kn->kn_flags & __EV_POLL) + kn->kn_flags |= __EV_HUP; + return (1); + } + + return (0); +} + const struct filterops ptcread_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, @@ -749,7 +768,7 @@ const struct filterops ptcexcept_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_ptcrdetach, - .f_event = filt_ptcread, + .f_event = filt_ptcexcept, }; int diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 7b855ad3b77..afab85de1ee 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.265 2021/10/14 23:05:10 mvs Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.266 2021/10/22 15:11:32 mpi Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -78,6 +78,10 @@ int filt_sowrite(struct knote *kn, long hint); int filt_sowritemodify(struct kevent *kev, struct knote *kn); int filt_sowriteprocess(struct knote *kn, struct kevent *kev); int filt_sowrite_common(struct knote *kn, struct socket *so); +int filt_soexcept(struct knote *kn, long hint); +int filt_soexceptmodify(struct kevent *kev, struct knote *kn); +int filt_soexceptprocess(struct knote *kn, struct kevent *kev); +int filt_soexcept_common(struct knote *kn, struct socket *so); int filt_solisten(struct knote *kn, long hint); int filt_solistenmodify(struct kevent *kev, struct knote *kn); int filt_solistenprocess(struct knote *kn, struct kevent *kev); @@ -114,9 +118,9 @@ const struct filterops soexcept_filtops = { .f_flags = FILTEROP_ISFD, .f_attach = NULL, .f_detach = filt_sordetach, - .f_event = filt_soread, - .f_modify = filt_soreadmodify, - .f_process = filt_soreadprocess, + .f_event = filt_soexcept, + .f_modify = filt_soexceptmodify, + .f_process = filt_soexceptprocess, }; #ifndef SOMINCONN @@ -2089,13 +2093,7 @@ filt_soread_common(struct knote *kn, struct socket *so) rv = 0; } else #endif /* SOCKET_SPLICE */ - if (kn->kn_sfflags & NOTE_OOB) { - if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) { - kn->kn_fflags |= NOTE_OOB; - kn->kn_data -= so->so_oobmark; - rv = 1; - } - } else if (so->so_state & SS_CANTRCVMORE) { + if (so->so_state & SS_CANTRCVMORE) { kn->kn_flags |= EV_EOF; if (kn->kn_flags & __EV_POLL) { if (so->so_state & SS_ISDISCONNECTED) @@ -2234,6 +2232,77 @@ filt_sowriteprocess(struct knote *kn, struct kevent *kev) return (rv); } +int +filt_soexcept_common(struct knote *kn, struct socket *so) +{ + int rv = 0; + + soassertlocked(so); + +#ifdef SOCKET_SPLICE + if (isspliced(so)) { + rv = 0; + } else +#endif /* SOCKET_SPLICE */ + if (kn->kn_sfflags & NOTE_OOB) { + if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) { + kn->kn_fflags |= NOTE_OOB; + kn->kn_data -= so->so_oobmark; + rv = 1; + } + } 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; + } + + return rv; +} + +int +filt_soexcept(struct knote *kn, long hint) +{ + struct socket *so = kn->kn_fp->f_data; + + return (filt_soexcept_common(kn, so)); +} + +int +filt_soexceptmodify(struct kevent *kev, struct knote *kn) +{ + struct socket *so = kn->kn_fp->f_data; + int rv, s; + + s = solock(so); + knote_modify(kev, kn); + rv = filt_soexcept_common(kn, so); + sounlock(so, s); + + return (rv); +} + +int +filt_soexceptprocess(struct knote *kn, struct kevent *kev) +{ + struct socket *so = kn->kn_fp->f_data; + int rv, s; + + s = solock(so); + if (kev != NULL && (kn->kn_flags & EV_ONESHOT)) + rv = 1; + else + rv = filt_soexcept_common(kn, so); + if (rv != 0) + knote_submit(kn, kev); + sounlock(so, s); + + return (rv); +} + int filt_solisten_common(struct knote *kn, struct socket *so) { diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c index 072187f1e80..6aa0c3284e2 100644 --- a/sys/miscfs/fifofs/fifo_vnops.c +++ b/sys/miscfs/fifofs/fifo_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fifo_vnops.c,v 1.82 2021/10/15 06:30:06 semarie Exp $ */ +/* $OpenBSD: fifo_vnops.c,v 1.83 2021/10/22 15:11:32 mpi Exp $ */ /* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */ /* @@ -112,6 +112,10 @@ int filt_fifowrite(struct knote *kn, long hint); int filt_fifowritemodify(struct kevent *kev, struct knote *kn); int filt_fifowriteprocess(struct knote *kn, struct kevent *kev); int filt_fifowrite_common(struct knote *kn, struct socket *so); +int filt_fifoexcept(struct knote *kn, long hint); +int filt_fifoexceptmodify(struct kevent *kev, struct knote *kn); +int filt_fifoexceptprocess(struct knote *kn, struct kevent *kev); +int filt_fifoexcept_common(struct knote *kn, struct socket *so); const struct filterops fiforead_filtops = { .f_flags = FILTEROP_ISFD, @@ -131,6 +135,15 @@ const struct filterops fifowrite_filtops = { .f_process = filt_fifowriteprocess, }; +const struct filterops fifoexcept_filtops = { + .f_flags = FILTEROP_ISFD, + .f_attach = NULL, + .f_detach = filt_fifordetach, + .f_event = filt_fifoexcept, + .f_modify = filt_fifoexceptmodify, + .f_process = filt_fifoexceptprocess, +}; + /* * Open called to set up a new instance of a fifo or * to find an active instance of a fifo. @@ -522,6 +535,11 @@ fifo_kqfilter(void *v) so = fip->fi_writesock; sb = &so->so_snd; break; + case EVFILT_EXCEPT: + ap->a_kn->kn_fop = &fifoexcept_filtops; + so = fip->fi_readsock; + sb = &so->so_rcv; + break; default: return (EINVAL); } @@ -670,3 +688,62 @@ filt_fifowriteprocess(struct knote *kn, struct kevent *kev) return (rv); } + +int +filt_fifoexcept_common(struct knote *kn, struct socket *so) +{ + int rv = 0; + + soassertlocked(so); + + 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; + } + rv = 1; + } + + return (rv); +} + +int +filt_fifoexcept(struct knote *kn, long hint) +{ + struct socket *so = kn->kn_hook; + + return (filt_fifoexcept_common(kn, so)); +} + +int +filt_fifoexceptmodify(struct kevent *kev, struct knote *kn) +{ + struct socket *so = kn->kn_hook; + int rv, s; + + s = solock(so); + knote_modify(kev, kn); + rv = filt_fifoexcept_common(kn, so); + sounlock(so, s); + + return (rv); +} + +int +filt_fifoexceptprocess(struct knote *kn, struct kevent *kev) +{ + struct socket *so = kn->kn_hook; + int rv, s; + + s = solock(so); + if (kev != NULL && (kn->kn_flags & EV_ONESHOT)) + rv = 1; + else + rv = filt_fifoexcept_common(kn, so); + if (rv != 0) + knote_submit(kn, kev); + sounlock(so, s); + + return (rv); +} -- 2.20.1