From: Kirk McKusick Date: Thu, 11 Aug 1994 13:19:13 +0000 (-0800) Subject: a zero-valued timeout (which should poll and return) gets turned into X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/630c291e5b4070bf7e5a7894b82e9699961b61d1 a zero-valued timeout (which should poll and return) gets turned into a one-tick timeout, and (worse) the amount of time to sleep is not recomputed after each sleep. I.e., if the timeout is 10 sec, and select is incorrectly after 9 sec, it will go back to sleep for up to 10 sec. In fact, in the worst case it will never return. (from karels) SCCS-vsn: sys/kern/sys_generic.c 8.7 --- diff --git a/usr/src/sys/kern/sys_generic.c b/usr/src/sys/kern/sys_generic.c index fc852d5b15..be609f20f7 100644 --- a/usr/src/sys/kern/sys_generic.c +++ b/usr/src/sys/kern/sys_generic.c @@ -9,7 +9,7 @@ * * %sccs.include.redist.c% * - * @(#)sys_generic.c 8.6 (Berkeley) %G% + * @(#)sys_generic.c 8.7 (Berkeley) %G% */ #include @@ -470,7 +470,7 @@ select(p, uap, retval) { fd_set ibits[3], obits[3]; struct timeval atv; - int s, ncoll, error = 0, timo; + int s, ncoll, error = 0, timo, doblock; u_int ni; bzero((caddr_t)ibits, sizeof(ibits)); @@ -499,14 +499,14 @@ select(p, uap, retval) error = EINVAL; goto done; } - s = splclock(); - timevaladd(&atv, (struct timeval *)&time); - timo = hzto(&atv); /* - * Avoid inadvertently sleeping forever. + * Don't let a short time get rounded down to zero + * and cause us to sleep forever, but exactly zero + * means "do not block". */ - if (timo == 0) - timo = 1; + doblock = (atv.tv_usec || atv.tv_sec); + s = splclock(); + timevaladd(&atv, (struct timeval *)&time); splx(s); } else timo = 0; @@ -517,17 +517,24 @@ retry: if (error || *retval) goto done; s = splhigh(); - /* this should be timercmp(&time, &atv, >=) */ - if (uap->tv && (time.tv_sec > atv.tv_sec || - time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { - splx(s); - goto done; + if (uap->tv) { + if (timercmp(&time, &atv, >=)) { + splx(s); + goto done; + } + timo = hzto(&atv); + /* + * Avoid inadvertently sleeping forever. + */ + if (doblock && timo == 0) + timo = 1; } if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { splx(s); goto retry; } p->p_flag &= ~P_SELECT; + doblock = 0; error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); splx(s); if (error == 0)