From 8713fbd9e3d63370b8594130e7ee8ea2213d142d Mon Sep 17 00:00:00 2001 From: jlemon Date: Mon, 7 Aug 2000 16:45:42 +0000 Subject: Fix bug with timeout; previously, when attempting to poll the kqueue by passing a zero-valued timeout, the code would always sleep for one tick. Change code to avoid calling tsleep if we have no intention of sleeping. Bring in bugfix from sys_select.c, r1.60 which also applies here. Modify error handling slightly; passing in an invalid fd will now result in EBADF returned in the eventlist, while an attempt to change a knote which does not exist will result in ENOENT being returned. Previously such attempts would fail silently without notification. Pointed out by: nicolas.leonard@animaths.com Rick Reed (rr@yahoo-inc.com) --- sys/kern/kern_event.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 2db8524..74d5fa7 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -413,10 +413,10 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p) } if (fops->f_isfd) { - /* validate descriptor; ignore invalid descriptors */ + /* validate descriptor */ if ((u_int)kev->ident >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[kev->ident]) == NULL) - return (0); + return (EBADF); if (kev->ident < fdp->fd_knlistsize) { SLIST_FOREACH(kn, &fdp->fd_knlist[kev->ident], kn_link) @@ -439,7 +439,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p) } if (kn == NULL && ((kev->flags & EV_ADD) == 0)) - goto done; + return (ENOENT); /* * kn now contains the matching knote, or NULL if no match @@ -523,24 +523,28 @@ kqueue_scan(struct file *fp, int maxevents, struct kevent *ulistp, if (count == 0) goto done; - if (tsp != NULL) { + if (tsp != NULL) { TIMESPEC_TO_TIMEVAL(&atv, tsp); - if (itimerfix(&atv)) { + if (itimerfix(&atv)) { error = EINVAL; goto done; } - timeout = atv.tv_sec > 24 * 60 * 60 ? - 24 * 60 * 60 * hz : tvtohz(&atv); - getmicrouptime(&rtv); - timevaladd(&atv, &rtv); - } else { - atv.tv_sec = 0; + if (tsp->tv_sec == 0 && tsp->tv_nsec == 0) + timeout = -1; + else + timeout = atv.tv_sec > 24 * 60 * 60 ? + 24 * 60 * 60 * hz : tvtohz(&atv); + getmicrouptime(&rtv); + timevaladd(&atv, &rtv); + } else { + atv.tv_sec = 0; + atv.tv_usec = 0; timeout = 0; } goto start; retry: - if (atv.tv_sec) { + if (atv.tv_sec || atv.tv_usec) { getmicrouptime(&rtv); if (timevalcmp(&rtv, &atv, >=)) goto done; @@ -554,8 +558,12 @@ start: kevp = kq->kq_kev; s = splhigh(); if (kq->kq_count == 0) { - kq->kq_state |= KQ_SLEEP; - error = tsleep(kq, PSOCK | PCATCH, "kqread", timeout); + if (timeout < 0) { + error = EWOULDBLOCK; + } else { + kq->kq_state |= KQ_SLEEP; + error = tsleep(kq, PSOCK | PCATCH, "kqread", timeout); + } splx(s); if (error == 0) goto retry; -- cgit v1.1