knote_processexit() uses knote_remove() to clear any remaining knotes
from &pr->ps_klist when process `pr' exits. All EVFILT_PROC knotes are
removed by the KNOTE(&pr->ps_klist, NOTE_EXIT) call. However, ps_klist
can contain EVFILT_SIGNAL knotes after the KNOTE().
To reserve knote_remove() for the kqueue subsystem's internal use, the
diff below makes knote_processexit() use klist_invalidate() instead.
For now, knote_remove() and klist_invalidate() are quite similar.
However, more differences will arise with fine-grained locking, and
knote_remove() will no longer be appropriate for knote_processexit().
To keep the existing behaviour with EVFILT_SIGNAL knotes, the diff
adjusts klist_invalidate() to drop non-fd-based knotes instead of
activating them with an EOF condition. This overloading of FILTEROP_ISFD
should be fine because EVFILT_PROC, EVFILT_SIGNAL and EVFILT_TIMER
are the only filter types that are not fd-based; EVFILT_PROC and
EVFILT_SIGNAL use the same knote list, whereas EVFILT_TIMER does not
use a knote list. The existing uses of klist_invalidate() should not
be affected.
OK?
Index: kern/kern_event.c
===================================================================
RCS file: src/sys/kern/kern_event.c,v
retrieving revision 1.140
diff -u -p -r1.140 kern_event.c
--- kern/kern_event.c 22 Jun 2020 13:14:32 -0000 1.140
+++ kern/kern_event.c 29 Jun 2020 16:10:14 -0000
@@ -1336,10 +1336,12 @@ knote_processexit(struct proc *p)
{
struct process *pr = p->p_p;
+ KASSERT(p == curproc);
+
KNOTE(&pr->ps_klist, NOTE_EXIT);
/* remove other knotes hanging off the process */
- knote_remove(p, &pr->ps_klist.kl_list);
+ klist_invalidate(&pr->ps_klist);
}
void
@@ -1446,6 +1448,7 @@ void
klist_invalidate(struct klist *list)
{
struct knote *kn;
+ struct proc *p = curproc;
int s;
/*
@@ -1460,10 +1463,15 @@ klist_invalidate(struct klist *list)
continue;
splx(s);
kn->kn_fop->f_detach(kn);
- kn->kn_fop = &dead_filtops;
- knote_activate(kn);
- s = splhigh();
- knote_release(kn);
+ if (kn->kn_fop->f_flags & FILTEROP_ISFD) {
+ kn->kn_fop = &dead_filtops;
+ knote_activate(kn);
+ s = splhigh();
+ knote_release(kn);
+ } else {
+ knote_drop(kn, p);
+ s = splhigh();
+ }
}
splx(s);
}