diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2008-05-10 11:35:32 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2008-05-10 11:35:32 +0000 |
commit | 2e711e4d0da6b15bfcf2b1dc83234b560ae1102f (patch) | |
tree | e1cd90cc89e1032d8bf29d5615c8c11c090fce42 /sys/kern/kern_event.c | |
parent | 5d699a2889a0b7ab7c915614780471fe546c9075 (diff) | |
download | src-2e711e4d0da6b15bfcf2b1dc83234b560ae1102f.tar.gz src-2e711e4d0da6b15bfcf2b1dc83234b560ae1102f.zip |
The kqueue_close() encountering the KN_INFLUX knotes on the kq being
closed is the legitimate situation. For instance, filedescriptor with
registered events may be closed in parallel with closing the kqueue.
Properly handle the case instead of asserting that this cannot happen.
Reported and tested by: pho
Reviewed by: jmg
MFC after: 2 weeks
Notes
Notes:
svn path=/head/; revision=178913
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r-- | sys/kern/kern_event.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index d17a20d0ed29..ffd18d416120 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1455,8 +1455,11 @@ kqueue_close(struct file *fp, struct thread *td) for (i = 0; i < kq->kq_knlistsize; i++) { while ((kn = SLIST_FIRST(&kq->kq_knlist[i])) != NULL) { - KASSERT((kn->kn_status & KN_INFLUX) == 0, - ("KN_INFLUX set when not suppose to be")); + if ((kn->kn_status & KN_INFLUX) == KN_INFLUX) { + kq->kq_state |= KQ_FLUXWAIT; + msleep(kq, &kq->kq_lock, PSOCK, "kqclo1", 0); + continue; + } kn->kn_status |= KN_INFLUX; KQ_UNLOCK(kq); if (!(kn->kn_status & KN_DETACHED)) @@ -1468,8 +1471,12 @@ kqueue_close(struct file *fp, struct thread *td) if (kq->kq_knhashmask != 0) { for (i = 0; i <= kq->kq_knhashmask; i++) { while ((kn = SLIST_FIRST(&kq->kq_knhash[i])) != NULL) { - KASSERT((kn->kn_status & KN_INFLUX) == 0, - ("KN_INFLUX set when not suppose to be")); + if ((kn->kn_status & KN_INFLUX) == KN_INFLUX) { + kq->kq_state |= KQ_FLUXWAIT; + msleep(kq, &kq->kq_lock, PSOCK, + "kqclo2", 0); + continue; + } kn->kn_status |= KN_INFLUX; KQ_UNLOCK(kq); if (!(kn->kn_status & KN_DETACHED)) |