Messages in this thread | | | Date | Wed, 28 Apr 1999 07:17:47 +0300 | From | Ville Herva <> | Subject | Re: 2.0.3x: select returns dubious tv.tv_sec? |
| |
Yesterday I wrote: > 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. > > > 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.
I believe I found out what's wrong with that.
/usr/src/linux-2.0.3x/fs/select.c:sys_select():
unsigned long timeout;
/* ... */ timeout = ~0UL;
if (tvp) { error = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp)); if (error) goto out; timeout = ROUND_UP(get_user(&tvp->tv_usec),(1000000/HZ)); timeout += get_user(&tvp->tv_sec) * (unsigned long) HZ; if (timeout) timeout += jiffies + 1; } zero_fd_set(n, &res_in); zero_fd_set(n, &res_out); zero_fd_set(n, &res_ex); current->timeout = timeout; error = do_select(n, (fd_set *) &in, (fd_set *) &out, (fd_set *) &ex, (fd_set *) &res_in, (fd_set *) &res_out, (fd_set *) &res_ex, (fd_set *) &locked); timeout = current->timeout - jiffies - 1; current->timeout = 0; 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); }
Now, if the timeout is reached during do_select, current->timeout becomes zero. The line
if ((long) timeout < 0) timeout = 0;
is propably for that. However, if jiffies > 2**31, that wont work (since timeout wraps around and actually becomes positive), and select returns false values. I would suggest something like
timeout = current->timeout ? current->timeout - jiffies - 1 : 0;
instead of
timeout = current->timeout - jiffies - 1;
2.2 seems to do
if (tvp && !(current->personality & STICKY_TIMEOUTS)) { time_t sec = 0, usec = 0; if (timeout) { sec = timeout / HZ; usec = timeout % HZ; usec *= (1000000/HZ); } put_user(sec, &tvp->tv_sec); put_user(usec, &tvp->tv_usec); }
So I think it has not got this bug. I'm not sure, however.
-- 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/
| |