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);
 }

Reply via email to