This is similar to the socket & kqueue diff I just sent.
Check for NOTE_SUBMIT hint in order to protect `so_state', `so_snd'
and `so_rcv'.
ok?
Index: miscfs//fifofs/fifo_vnops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/fifofs/fifo_vnops.c,v
retrieving revision 1.54
diff -u -p -r1.54 fifo_vnops.c
--- miscfs//fifofs/fifo_vnops.c 26 Jun 2017 09:32:31 -0000 1.54
+++ miscfs//fifofs/fifo_vnops.c 26 Jun 2017 14:07:29 -0000
@@ -527,14 +527,22 @@ int
filt_fiforead(struct knote *kn, long hint)
{
struct socket *so = (struct socket *)kn->kn_hook;
+ int s, rv;
+ if (!(hint & NOTE_SUBMIT))
+ s = solock(so);
kn->kn_data = so->so_rcv.sb_cc;
if (so->so_state & SS_CANTRCVMORE) {
kn->kn_flags |= EV_EOF;
- return (1);
+ rv = 1;
+ } else {
+ kn->kn_flags &= ~EV_EOF;
+ rv = (kn->kn_data > 0);
}
- kn->kn_flags &= ~EV_EOF;
- return (kn->kn_data > 0);
+ if (!(hint & NOTE_SUBMIT))
+ sounlock(s);
+
+ return (rv);
}
void
@@ -551,12 +559,20 @@ int
filt_fifowrite(struct knote *kn, long hint)
{
struct socket *so = (struct socket *)kn->kn_hook;
+ int s, rv;
+ if (!(hint & NOTE_SUBMIT))
+ s = solock(so);
kn->kn_data = sbspace(so, &so->so_snd);
if (so->so_state & SS_CANTSENDMORE) {
kn->kn_flags |= EV_EOF;
- return (1);
+ rv = 1;
+ } else {
+ kn->kn_flags &= ~EV_EOF;
+ rv = (kn->kn_data >= so->so_snd.sb_lowat);
}
- kn->kn_flags &= ~EV_EOF;
- return (kn->kn_data >= so->so_snd.sb_lowat);
+ if (!(hint & NOTE_SUBMIT))
+ sounlock(s);
+
+ return (rv);
}