summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2000-08-07 16:45:42 +0000
committerjlemon <jlemon@FreeBSD.org>2000-08-07 16:45:42 +0000
commit8713fbd9e3d63370b8594130e7ee8ea2213d142d (patch)
tree62e7957c86190da051ce2b26d3e886fd4deffa5f /sys
parente35ff24b97251716934363c568b0a7c1e8e064f5 (diff)
downloadFreeBSD-src-8713fbd9e3d63370b8594130e7ee8ea2213d142d.zip
FreeBSD-src-8713fbd9e3d63370b8594130e7ee8ea2213d142d.tar.gz
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)
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_event.c36
1 files 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;
OpenPOWER on IntegriCloud