Index: head/sys/kern/kern_event.c =================================================================== --- head/sys/kern/kern_event.c +++ head/sys/kern/kern_event.c @@ -136,6 +136,7 @@ static int knote_attach(struct knote *kn, struct kqueue *kq); static void knote_drop(struct knote *kn, struct thread *td); +static void knote_drop_detached(struct knote *kn, struct thread *td); static void knote_enqueue(struct knote *kn); static void knote_dequeue(struct knote *kn); static void knote_init(void); @@ -1343,7 +1344,7 @@ } if ((error = kn->kn_fop->f_attach(kn)) != 0) { - knote_drop(kn, td); + knote_drop_detached(kn, td); goto done; } knl = kn_list_lock(kn); @@ -1359,8 +1360,6 @@ if (kev->flags & EV_DELETE) { kn_enter_flux(kn); KQ_UNLOCK(kq); - if (!(kn->kn_status & KN_DETACHED)) - kn->kn_fop->f_detach(kn); knote_drop(kn, td); goto done; } @@ -1684,8 +1683,6 @@ * We don't need to lock the list since we've * marked it as in flux. */ - if (!(kn->kn_status & KN_DETACHED)) - kn->kn_fop->f_detach(kn); knote_drop(kn, td); KQ_LOCK(kq); continue; @@ -1699,8 +1696,6 @@ * marked the knote as being in flux. */ *kevp = kn->kn_kevent; - if (!(kn->kn_status & KN_DETACHED)) - kn->kn_fop->f_detach(kn); knote_drop(kn, td); KQ_LOCK(kq); kn = NULL; @@ -1902,8 +1897,6 @@ } kn_enter_flux(kn); KQ_UNLOCK(kq); - if (!(kn->kn_status & KN_DETACHED)) - kn->kn_fop->f_detach(kn); knote_drop(kn, td); KQ_LOCK(kq); } @@ -1919,8 +1912,6 @@ } kn_enter_flux(kn); KQ_UNLOCK(kq); - if (!(kn->kn_status & KN_DETACHED)) - kn->kn_fop->f_detach(kn); knote_drop(kn, td); KQ_LOCK(kq); } @@ -2323,10 +2314,9 @@ } knlist_remove_kq(knl, kn, 1, 1); if (killkn) { - kn->kn_status |= KN_DETACHED; kn_enter_flux(kn); KQ_UNLOCK(kq); - knote_drop(kn, td); + knote_drop_detached(kn, td); } else { /* Make sure cleared knotes disappear soon */ kn->kn_flags |= EV_EOF | EV_ONESHOT; @@ -2392,10 +2382,8 @@ } kn_enter_flux(kn); KQ_UNLOCK(kq); - if (!(kn->kn_status & KN_DETACHED)) - kn->kn_fop->f_detach(kn); - knote_drop(kn, td); influx = 1; + knote_drop(kn, td); KQ_LOCK(kq); } KQ_UNLOCK_FLUX(kq); @@ -2423,20 +2411,27 @@ return (0); } -/* - * knote must already have been detached using the f_detach method. - * no lock need to be held, it is assumed that the influx state is set - * to prevent other removal. - */ static void knote_drop(struct knote *kn, struct thread *td) { + + if ((kn->kn_status & KN_DETACHED) == 0) + kn->kn_fop->f_detach(kn); + knote_drop_detached(kn, td); +} + +static void +knote_drop_detached(struct knote *kn, struct thread *td) +{ struct kqueue *kq; struct klist *list; kq = kn->kn_kq; + KASSERT((kn->kn_status & KN_DETACHED) != 0, + ("knote %p still attached", kn)); KQ_NOTOWNED(kq); + KQ_LOCK(kq); KASSERT(kn->kn_influx == 1, ("knote_drop called on %p with influx %d", kn, kn->kn_influx));