I put together a nanosleep() for systems without it. Please review/test before I commit. It sems to make UnixWare and Open Server 5 happy. My SCO Open Server 3 box broke so I can't test it there. -------------< cut here >---------------- --- openssh/configure.ac.old 2003-03-09 17:16:43.000000000 -0800 +++ openssh/configure.ac 2003-03-16 15:38:28.520560008 -0800 @@ -1483,6 +1483,8 @@ have_struct_timeval=1 fi +AC_CHECK_TYPES(struct timespec) + # If we don't have int64_t then we can't compile sftp-server. So don't # even attempt to do it. if test "x$ac_cv_have_int64_t" = "xno" -a \ --- openssh/openbsd-compat/bsd-misc.c.old 2003-01-19 19:21:01.000000000 -0800 +++ openssh/openbsd-compat/bsd-misc.c 2003-03-16 14:49:58.740480006 -0800 @@ -135,3 +135,34 @@ } #endif +#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) +int nanosleep(const struct timespec *req, struct timespec *rem) +{ + int rc; + extern int errno; + struct timeval tsave, ttmp, time2wait; + + TIMESPEC_TO_TIMEVAL(&time2wait, req) + + gettimeofday(&tsave, NULL); + rc = select(0, NULL, NULL, NULL, &time2wait); + if (rc) { + gettimeofday (&ttmp, NULL); + ttmp.tv_sec -= tsave.tv_sec; + ttmp.tv_usec -= tsave.tv_usec; + tsave.tv_sec = (time2wait.tv_sec - ttmp.tv_sec); + tsave.tv_usec = (time2wait.tv_usec - ttmp.tv_usec); + if(tsave.tv_sec < 0){ + tsave.tv_sec = 0; + tsave.tv_usec += 1000000L; + } + rc = -1; + } + + TIMEVAL_TO_TIMESPEC(&tsave, rem) + + return(rc); +} + +#endif + --- openssh/openbsd-compat/bsd-misc.h.old 2002-06-20 20:35:30.000000000 -0700 +++ openssh/openbsd-compat/bsd-misc.h 2003-03-16 15:32:29.850560003 -0800 @@ -80,5 +80,14 @@ int setgroups(size_t size, const gid_t *list); #endif +#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) +#ifndef HAVE_STRUCT_TIMESPEC +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif +int nanosleep(const struct timespec *req, struct timespec *rem); +#endif #endif /* _BSD_MISC_H */ -------------< end cut >---------------- -- Tim Rice Multitalents (707) 887-1469 tim at multitalents.net
Tim Rice wrote:> I put together a nanosleep() for systems without it. > > Please review/test before I commit.I can confirm that this works on Solaris 8 (configured without librt, which is where nanosleep is), however it doesn't seem to cope well with the lower limits. Is this an unavoidable consequence of the lesser precision of select? For comparison here's what I got from: $ scp -l [limit] -o Compression=no openssh-3.5p1.tar.gz localhost:/tmp limit nanosleep select/bsd-misc 1 1 30 8 8 48 64 64 66 128 129 130 256 255 255 (all kbits/sec, calculated from kbytes/sec reported by scp) One other thought: since lots of things (including scp) use ssh as a transport, and bandwidth limiting is more a transport layer function, shouldn't bandwidth limiting be a function of ssh not scp? -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.
Tim Rice wrote:> I put together a nanosleep() for systems without it. > > Please review/test before I commit.Before I forget, a couple of things I noticed while playing around with this: [snip]> +int nanosleep(const struct timespec *req, struct timespec *rem) > +{ > + int rc; > + extern int errno; > + struct timeval tsave, ttmp, time2wait; > + > + TIMESPEC_TO_TIMEVAL(&time2wait, req) > + > + gettimeofday(&tsave, NULL); > + rc = select(0, NULL, NULL, NULL, &time2wait); > + if (rc) {Checking for rc == -1, right? Would "if (rc < 0)" be clearer?> + gettimeofday (&ttmp, NULL);This can reset errno so (errno==EINTR) from select can be lost.> + ttmp.tv_sec -= tsave.tv_sec; > + ttmp.tv_usec -= tsave.tv_usec; > + tsave.tv_sec = (time2wait.tv_sec - ttmp.tv_sec); > + tsave.tv_usec = (time2wait.tv_usec - ttmp.tv_usec); > + if(tsave.tv_sec < 0){ > + tsave.tv_sec = 0; > + tsave.tv_usec += 1000000L; > + } > + rc = -1; > + } > + > + TIMEVAL_TO_TIMESPEC(&tsave, rem)In the case where select returns normally, the remainder is whatever gettimeofday() returned which will be *way* bigger than the requested wait time and any possible remainder.> + return(rc);[snip] -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.
After Darren noticed a couple of problems, I've made a few changes. I'd like to hear from Wendy if this works on cray. Thanks for all the input. -------------< cut >---------------- --- openssh/configure.ac.old 2003-03-09 17:16:43.000000000 -0800 +++ openssh/configure.ac 2003-03-16 15:38:28.520560008 -0800 @@ -1483,6 +1483,8 @@ have_struct_timeval=1 fi +AC_CHECK_TYPES(struct timespec) + # If we don't have int64_t then we can't compile sftp-server. So don't # even attempt to do it. if test "x$ac_cv_have_int64_t" = "xno" -a \ --- openssh/openbsd-compat/bsd-misc.c.old 2003-01-19 19:21:01.000000000 -0800 +++ openssh/openbsd-compat/bsd-misc.c 2003-03-17 14:02:20.905600005 -0800 @@ -135,3 +135,38 @@ } #endif +#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) +int nanosleep(const struct timespec *req, struct timespec *rem) +{ + int rc, saverrno; + extern int errno; + struct timeval tsave, ttmp, time2wait; + + TIMESPEC_TO_TIMEVAL(&time2wait, req) + + gettimeofday(&tsave, NULL); + rc = select(0, NULL, NULL, NULL, &time2wait); + if (rc == -1) { + saverrno = errno; + gettimeofday (&ttmp, NULL); + errno = saverrno; + ttmp.tv_sec -= tsave.tv_sec; + ttmp.tv_usec -= tsave.tv_usec; + tsave.tv_sec = (time2wait.tv_sec - ttmp.tv_sec); + tsave.tv_usec = (time2wait.tv_usec - ttmp.tv_usec); + if(tsave.tv_sec < 0){ + tsave.tv_sec = 0; + tsave.tv_usec += 1000000L; + } + } + else { + tsave.tv_sec = 0; + tsave.tv_usec = 0; + } + TIMEVAL_TO_TIMESPEC(&tsave, rem) + + return(rc); +} + +#endif + --- openssh/openbsd-compat/bsd-misc.h.old 2002-06-20 20:35:30.000000000 -0700 +++ openssh/openbsd-compat/bsd-misc.h 2003-03-16 15:32:29.850560003 -0800 @@ -80,5 +80,14 @@ int setgroups(size_t size, const gid_t *list); #endif +#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) +#ifndef HAVE_STRUCT_TIMESPEC +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif +int nanosleep(const struct timespec *req, struct timespec *rem); +#endif #endif /* _BSD_MISC_H */ -------------< end cut >---------------- -- Tim Rice Multitalents (707) 887-1469 tim at multitalents.net