Now that we have a mechanism to check when to lock the socket inside a
kqueue filter, let's use it.

Diff below protects `so_qlen', `so_state' and `so_snd.sb_lowat' which
are accessed in tcp_input().

ok?

Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.189
diff -u -p -r1.189 uipc_socket.c
--- kern/uipc_socket.c  26 Jun 2017 09:32:31 -0000      1.189
+++ kern/uipc_socket.c  26 Jun 2017 14:00:46 -0000
@@ -1991,35 +1991,44 @@ int
 filt_sowrite(struct knote *kn, long hint)
 {
        struct socket *so = kn->kn_fp->f_data;
-       int s;
+       int s, rv;
 
        if (!(hint & NOTE_SUBMIT))
                s = solock(so);
        kn->kn_data = sbspace(so, &so->so_snd);
-       if (!(hint & NOTE_SUBMIT))
-               sounlock(s);
        if (so->so_state & SS_CANTSENDMORE) {
                kn->kn_flags |= EV_EOF;
                kn->kn_fflags = so->so_error;
-               return (1);
+               rv = 1;
+       } else if (so->so_error) {      /* temporary udp error */
+               rv = 1;
+       } else if (((so->so_state & SS_ISCONNECTED) == 0) &&
+           (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
+               rv = 0;
+       } if (kn->kn_sfflags & NOTE_LOWAT) {
+               rv = (kn->kn_data >= kn->kn_sdata);
+       } else {
+               rv = (kn->kn_data >= so->so_snd.sb_lowat);
        }
-       if (so->so_error)       /* temporary udp error */
-               return (1);
-       if (((so->so_state & SS_ISCONNECTED) == 0) &&
-           (so->so_proto->pr_flags & PR_CONNREQUIRED))
-               return (0);
-       if (kn->kn_sfflags & NOTE_LOWAT)
-               return (kn->kn_data >= kn->kn_sdata);
-       return (kn->kn_data >= so->so_snd.sb_lowat);
+       if (!(hint & NOTE_SUBMIT))
+               sounlock(s);
+
+       return (rv);
 }
 
 int
 filt_solisten(struct knote *kn, long hint)
 {
        struct socket *so = kn->kn_fp->f_data;
+       int s;
 
+       if (!(hint & NOTE_SUBMIT))
+               s = solock(so);
        kn->kn_data = so->so_qlen;
-       return (so->so_qlen != 0);
+       if (!(hint & NOTE_SUBMIT))
+               sounlock(s);
+
+       return (kn->kn_data != 0);
 }
 
 #ifdef DDB

Reply via email to