From e472b9091e08c00349d400ae410d4c4e14cc9cdc Mon Sep 17 00:00:00 2001 From: kardel Date: Sat, 8 Jul 2006 12:16:09 +0000 Subject: [PATCH] fix a bug reported by Steven M. Bellovin regarding oversleeping select(2) timeouts. Introduced via timecounter branch from a tvtohz() conversion. The left over timeout was not decremented when re-starting the sleep in select. --- sys/kern/sys_generic.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index eb7577c3315a..c2f55d2c9bfa 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1,4 +1,4 @@ -/* $NetBSD: sys_generic.c,v 1.86 2006/06/07 22:33:40 kardel Exp $ */ +/* $NetBSD: sys_generic.c,v 1.87 2006/07/08 12:16:09 kardel Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.86 2006/06/07 22:33:40 kardel Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.87 2006/07/08 12:16:09 kardel Exp $"); #include "opt_ktrace.h" @@ -753,6 +753,7 @@ selcommon(struct lwp *l, register_t *retval, int nd, fd_set *u_in, int s, ncoll, error, timo; size_t ni; sigset_t oldmask; + struct timeval sleepts; error = 0; if (nd < 0) @@ -780,9 +781,14 @@ selcommon(struct lwp *l, register_t *retval, int nd, fd_set *u_in, #undef getbits timo = 0; - if (tv && itimerfix(tv)) { - error = EINVAL; - goto done; + timerclear(&sleepts); + + if (tv) { + if (itimerfix(tv)) { + error = EINVAL; + goto done; + } + getmicrouptime(&sleepts); } if (mask) (void)sigprocmask1(p, SIG_SETMASK, mask, &oldmask); @@ -798,6 +804,16 @@ selcommon(struct lwp *l, register_t *retval, int nd, fd_set *u_in, /* * We have to recalculate the timeout on every retry. */ + struct timeval slepttime; + /* + * reduce tv by elapsed time + * based on monotonic time scale + */ + getmicrouptime(&slepttime); + timeradd(tv, &slepttime, tv); + timersub(tv, &sleepts, tv); + sleepts = slepttime; + timo = tvtohz(tv); if (timo <= 0) goto done;