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
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)sys_generic.c 8.6 (Berkeley) %G%
+ * @(#)sys_generic.c 8.7 (Berkeley) %G%
*/
#include <sys/param.h>
*/
#include <sys/param.h>
{
fd_set ibits[3], obits[3];
struct timeval atv;
{
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));
u_int ni;
bzero((caddr_t)ibits, sizeof(ibits));
error = EINVAL;
goto done;
}
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;
splx(s);
} else
timo = 0;
if (error || *retval)
goto done;
s = splhigh();
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;
}
if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
splx(s);
goto retry;
}
p->p_flag &= ~P_SELECT;
error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
splx(s);
if (error == 0)
error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
splx(s);
if (error == 0)