summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2021-10-22 15:11:33 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2021-10-22 15:11:33 +0000
commitb9041dc6c1d2560ca446e447e882ecd980a476f1 (patch)
tree78bfbee15395da3d631b9b0219fc4375edd82caa
parentf453b027ab8209588b5f264d66607d1fff0defb9 (diff)
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@
-rw-r--r--sys/kern/tty_pty.c43
-rw-r--r--sys/kern/uipc_socket.c91
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c79
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)
@@ -2235,6 +2233,77 @@ filt_sowriteprocess(struct knote *kn, struct kevent *kev)
}
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)
{
soassertlocked(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);
+}