2.0.3x: select returns dubious tv.tv_sec?

Ville Herva (vherva@babbage.tky.hut.fi)
Wed, 28 Apr 1999 00:55:34 +0300


I had a problem with zsh, whose command line started working strangely
after 248 days of uptime (jiffies > 2**31).

The problem turned out to be a select call that had invalid timeout value.
The tv struct in zsh was first initialized to zero. Then select was called
multiple times reinitializing the tv_usec part to zero before each call.
tv_sec should have remained zero after select() as far as I can tell (and
most like did before the 248 day barrier). From the man page:

"On Linux, timeout is modified to reflect the amount of
time not slept; most other implementations do not do this."

So tv.tv_sec only get decremented during select().

The example program from the select man page with one additional printf:

vherva@turing:/home/vherva>cat u.c
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;

/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;

retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
printf("... because if one does, he'll get suprised: %i.\n",
tv.tv_sec);

if (retval)
printf("Data is available now.\n");
/* FD_ISSET(0, &rfds) will be true. */
else
printf("No data within five seconds.\n");

exit(0);
}
vherva@turing:/home/vherva>gcc u.c -o u;./u
q
... because if one does, he'll get suprised: 4.
Data is available now.
vherva@turing:/home/vherva>cd
vherva@turing:/home/vherva>gcc u.c -o u;./u
... because if one does, he'll get suprised: 13124461.
No data within five seconds.
vherva@turing:/home/vherva>uptime
12:49am up 345 days, 4:48, 1 user, load average: 0.00, 0.00, 0.00

The problem is somewhere in the fs/select.c, I suspect.

if ((long) timeout < 0)
timeout = 0;
if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
put_user(timeout/HZ, &tvp->tv_sec);
timeout %= HZ;
timeout *= (1000000/HZ);
put_user(timeout, &tvp->tv_usec);
}

It seems clear that timeout (unsigned) is somewhere between 2**31 and 2**32
when those erranous values are returned. It is not clear to me how
timeout gets those values.

-- v --

v@iki.fi

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/