diff options
author | brian <brian@cvs.openbsd.org> | 1997-12-28 21:54:26 +0000 |
---|---|---|
committer | brian <brian@cvs.openbsd.org> | 1997-12-28 21:54:26 +0000 |
commit | 9dfb52ea4b97ea1c25b3631a1675060f35885357 (patch) | |
tree | 0c42b5e21b8ffd090ea68437c4eb14c3392b784d /usr.sbin/ppp/timer.c | |
parent | af7574bc79365a4f767b1034e070349d543c364b (diff) |
Don't expect select() to adjust the passed time when it's
interrupted with a SIGALRM. In fact, select() sets the
passed time to zero, making the previous implementation
terminate always after 1/10th of a second !
Also, deal with someone changing the clock while we're
sleeping (and restart the whole sleep).
Dangers pointed out by: Theo de Raadt <deraadt@cvs.openbsd.org>
Diffstat (limited to 'usr.sbin/ppp/timer.c')
-rw-r--r-- | usr.sbin/ppp/timer.c | 82 |
1 files changed, 38 insertions, 44 deletions
diff --git a/usr.sbin/ppp/timer.c b/usr.sbin/ppp/timer.c index ebb4cd4453b..1a1516639b6 100644 --- a/usr.sbin/ppp/timer.c +++ b/usr.sbin/ppp/timer.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: timer.c,v 1.1 1997/11/23 20:27:36 brian Exp $ + * $Id: timer.c,v 1.2 1997/12/28 21:54:24 brian Exp $ * * TODO: */ @@ -207,66 +207,60 @@ ShowTimers() } #ifdef SIGALRM -u_int -nointr_sleep(u_int sec) + +static void +nointr_dosleep(u_int sec, u_int usec) { struct timeval to, st, et; - long sld, nwd, std; gettimeofday(&st, NULL); + et.tv_sec = st.tv_sec + sec; + et.tv_usec = st.tv_usec + usec; to.tv_sec = sec; - to.tv_usec = 0; - std = st.tv_sec * 1000000 + st.tv_usec; + to.tv_usec = usec; for (;;) { if (select(0, NULL, NULL, NULL, &to) == 0 || errno != EINTR) { break; } else { - gettimeofday(&et, NULL); - sld = to.tv_sec * 1000000 + to.tv_sec; - nwd = et.tv_sec * 1000000 + et.tv_usec - std; - if (sld > nwd) - sld -= nwd; - else - sld = 1; /* Avoid both tv_sec/usec is 0 */ - - /* Calculate timeout value for select */ - to.tv_sec = sld / 1000000; - to.tv_usec = sld % 1000000; + gettimeofday(&to, NULL); + if (to.tv_sec > et.tv_sec || + (to.tv_sec == et.tv_sec && to.tv_usec > et.tv_usec) || + to.tv_sec < st.tv_sec || + (to.tv_sec == st.tv_sec && to.tv_usec < st.tv_usec)) { + LogPrintf(LogWARN, "Clock adjusted between %d and %d seconds " + "during sleep !\n", + to.tv_sec - st.tv_sec, sec + to.tv_sec - st.tv_sec); + st.tv_sec = to.tv_sec; + st.tv_usec = to.tv_usec; + et.tv_sec = st.tv_sec + sec; + et.tv_usec = st.tv_usec + usec; + to.tv_sec = sec; + to.tv_usec = usec; + } else if (to.tv_sec == et.tv_sec && to.tv_usec == et.tv_usec) { + break; + } else { + to.tv_sec = et.tv_sec - to.tv_sec; + if (et.tv_usec < to.tv_usec) { + to.tv_sec--; + to.tv_usec = 1000000 + et.tv_usec - to.tv_usec; + } else + to.tv_usec = et.tv_usec - to.tv_usec; + } } } - return (0L); } void -nointr_usleep(u_int usec) +nointr_sleep(u_int sec) { - struct timeval to, st, et; - long sld, nwd, std; - - gettimeofday(&st, NULL); - to.tv_sec = 0; - to.tv_usec = usec; - std = st.tv_sec * 1000000 + st.tv_usec; - for (;;) { - if (select(0, NULL, NULL, NULL, &to) == 0 || - errno != EINTR) { - break; - } else { - gettimeofday(&et, NULL); - sld = to.tv_sec * 1000000 + to.tv_sec; - nwd = et.tv_sec * 1000000 + et.tv_usec - std; - if (sld > nwd) - sld -= nwd; - else - sld = 1; /* Avoid both tv_sec/usec is 0 */ - - /* Calculate timeout value for select */ - to.tv_sec = sld / 1000000; - to.tv_usec = sld % 1000000; + nointr_dosleep(sec, 0); +} - } - } +void +nointr_usleep(u_int usec) +{ + nointr_dosleep(0, usec); } static void |