select(2) returns EINVAL if the timeout is specified for longer than 100000000 seconds. Is this according to some specification? If so, nevermind, but please document this limitation in the man page. As it stands, there's nothing in the man page that indicates there is such an arbitrary limitation. Otherwise, it should support up to the maximum possible value that can be specified in a struct timeval. Fix: Either allow all valid struct timeval's, or else please document this shortcoming in the man page. How-To-Repeat: #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/time.h> #include <unistd.h> #include <string.h> #include <err.h> void main(int ac, char *av[]) { struct timeval tv; fd_set fds; int r; switch (ac) { default: errx(1, "usage: xx [secs]"); case 2: tv.tv_sec = strtol(av[1], 0, NULL); break; case 1: tv.tv_sec = 100000001; break; } tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(0, &fds); r = select(1, &fds, NULL, NULL, &tv); if (r < 0) err(1, "select"); }
Here is what "The Single UNIX Specification, Version 2" that I downloaded about a year ago says: Implementations may place limitations on the maximum timeout interval supported. On all implementations, the maximum timeout interval supported will be at least 31 days. If the timeout argument specifies a timeout interval greater than the implementation-dependent maximum value, the maximum value will be used as the actual timeout value. Implementations may also place limitations on the granularity of timeout intervals. If the requested timeout interval requires a finer granularity than the implementation supports, the actual timeout interval will be rounded up to the next supported value. So it looks the implimentation doesn't agree with this, and the man page should probably say what the max timeout is. (Excerpt is from http://www.opennc.org/onlinepubs/7908799/xsh/select.html). David.
Everything that is implemented using itimers has this limit. The limit is only documented explicitly in setitimer.2, alarm.3 and ualarm.3. The possible existence of a limit is documented in select.2: [EINVAL] The specified time limit is invalid. One of its com- ponents is negative or too large. Saying exactly which values are too large in the man page wouldn't be very useful. Programs (sic) would have to read the man page to determine the limit, since it would be machine-dependent. A limit reported by sysconf(2) would be more useful, but there is no standard for this. The limit of 10^8 seconds is imposed to reduce the chance of overflows in computations involving itimers. Note that timeouts of 10^8 seconds don't actually work, at least for select(). 10^8 seconds is 1157+ days, by the default configuration of HZ = 100, timeouts in 32-bit ticks are limited to only 248+ days. If you increase HZ to 10^5 then you may even notice this bug :-). On Tue, 30 May 2000, Kelly Yancey wrote: > On Tue, 30 May 2000, David Malone wrote: > > Here is what "The Single UNIX Specification, Version 2" that I > > downloaded about a year ago says: > > > > Implementations may place limitations on the maximum timeout > > interval supported. On all implementations, the maximum timeout > > interval supported will be at least 31 days. If the timeout Setting HZ to More than about 800 will break this. There are many possible problems like this, so nonstandard values of HZ aren't really supported. > > argument specifies a timeout interval greater than the > > implementation-dependent maximum value, the maximum value will be > > used as the actual timeout value. Implementations may also place > > limitations on the granularity of timeout intervals. If the > > requested timeout interval requires a finer granularity than the > > implementation supports, the actual timeout interval will be > > rounded up to the next supported value. > > > > So it looks the implimentation doesn't agree with this, and the > > man page should probably say what the max timeout is. > > > > (Excerpt is from http://www.opennc.org/onlinepubs/7908799/xsh/select.html). > > > > I read this to say that returning EINVAL (as reported in the submitted > PR) is the Wrong Thing and that we should be rounding the interval down > instead. The culprit is kern_time.c:itimerfix which is called by select, I read this as a bug in the SUS :-). The easiest workaround is to not have a limit. It seems to be easy to fix for select() and poll(), since there is already a loop where we check after some wakeups to see if the timeout expired (see old fixes for this problem in nanosleep()). > So someone more wise will definately need to review this (simple) patch > as it may have far-reaching affects. It affects setitimer(), etc. The SUS requires setitimer() and alarm() to handle the full interval. POSIX requires this for alarm() IIRC. Bruce
> Everything that is implemented using itimers has this limit. The limit > is only documented explicitly in setitimer.2, alarm.3 and ualarm.3. Unless I'm mistaken, select (and poll and the kevent stuff) don't actually have anything to do with itimers, as the implementation of their timeouts is with tsleep, which uses timeout, which uses callouts. They are just borrowing the itimerfix() function for a use for which it wasn't intended? Probably what is needed is a timevalisvalid() function. There is already a (static) timevalfix() function, however it doesn't do what is required here. > The limit of 10^8 seconds is imposed to reduce the chance of overflows > in computations involving itimers. Note that timeouts of 10^8 seconds > don't actually work, at least for select(). 10^8 seconds is 1157+ > days, by the default configuration of HZ = 100, timeouts in 32-bit > ticks are limited to only 248+ days. If you increase HZ to 10^5 then > you may even notice this bug :-). I guess this means that itimerfix should really say something like: - if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || + if (tv->tv_sec < 0 || tv->tv_sec/hz > 1000000 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) to avoid problems on such systems? > I read this as a bug in the SUS :-). The easiest workaround is to not > have a limit. It seems to be easy to fix for select() and poll(), since > there is already a loop where we check after some wakeups to see if the > timeout expired (see old fixes for this problem in nanosleep()). > It affects setitimer(), etc. The SUS requires setitimer() and alarm() to > handle the full interval. POSIX requires this for alarm() IIRC. I'd be interested in trying to fix this, and really just need more info on how timevals should be handeled. Is adding a timevalisvalid() function/macro reasonable? How should negative timevals be represented? Is -1.5s written as: tv_sec = -2; tv_usec = 500000; or tv_sec = -1; tv_usec = -500000; I'd presume it is the first, but you never can tell. David.
On Wed, 7 Jun 2000, David Malone wrote: > > Everything that is implemented using itimers has this limit. The limit > > is only documented explicitly in setitimer.2, alarm.3 and ualarm.3. > > Unless I'm mistaken, select (and poll and the kevent stuff) don't > actually have anything to do with itimers, as the implementation > of their timeouts is with tsleep, which uses timeout, which uses > callouts. They are just borrowing the itimerfix() function for > a use for which it wasn't intended? I think it was intended. For both itimers and select(), the value of timeout()'s `tick' arg was once calculated using hzto(). This involved a timevaladd() of the current time to a timeout. It was important that the addition doesn't overflow. This was arranged by limiting the timeout. 32-bit signed time_t's will overflow in 2038, and timeouts of 10^8 would have started overflowing things in 2035. FreeBSD now uses tvtohz() instead of hzto(), so the limit of 10^8 is no longer very appropriate for either itimers or select(). A limit of (timeval when time_t's overflow) - (current time) would be about right. It would be better to have no limit until the current time actually overflows time_t (which won't happen becauase either time_t or the code will be changed before then), but this may require more changes to avoid overflow in intermediate computations. > I'd be interested in trying to fix this, and really just need more > info on how timevals should be handeled. Is adding a timevalisvalid() > function/macro reasonable? How should negative timevals be represented? > Is -1.5s written as: > > tv_sec = -2; tv_usec = 500000; > or tv_sec = -1; tv_usec = -500000; > > I'd presume it is the first, but you never can tell. The first is enforced in various places. Bruce
Responsible Changed From-To: freebsd-bugs->dwmalone I'm interested in this one.
Responsible Changed From-To: dwmalone->freebsd-bugs over to the pool (approved by bugmeister)
FreeBSD 11.1/i386 does not have this problem anymore. That is, select(2) does not return EINVAL if a timeout is specified for longer than 100000000 seconds. Close this after 17 years.