aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_event.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2008-05-10 11:35:32 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2008-05-10 11:35:32 +0000
commit2e711e4d0da6b15bfcf2b1dc83234b560ae1102f (patch)
treee1cd90cc89e1032d8bf29d5615c8c11c090fce42 /sys/kern/kern_event.c
parent5d699a2889a0b7ab7c915614780471fe546c9075 (diff)
downloadsrc-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.c15
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))