summaryrefslogtreecommitdiff
path: root/sys/kern/uipc_socket.c
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 /sys/kern/uipc_socket.c
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@
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r--sys/kern/uipc_socket.c91
1 files changed, 80 insertions, 11 deletions
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);