From: urlichs@smurf.sub.org (Matthias Urlichs) Subject: Re: select() ? Date: 12 Feb 1993 07:12:57 +0100
In comp.os.linux, article <1lc37jINNdn@senator-bedfellow.MIT.EDU>,
jfc@athena.mit.edu (John F Carr) writes:
> In article <1lbpfv$b6g@smurf.sub.org>
> urlichs@smurf.sub.org (Matthias Urlichs) writes:
>
> >Why does select() change the timeout (last argument)?
>
> From the BSD 4.3 manual:
>
> Select should probably return the time remaining from the
> original timeout, if any, by modifying the time value in
> place. This may be implemented in future versions of the
> system. Thus, it is unwise to assume that the timeout value
> will be unmodified by the select call.
>
> I've had to code around this restriction, and am glad to see a system
> do select right. I don't like the gettimeofday solution; I want to
> minimize the number of system calls.
>
OKOK, but then why isn't the library code right? ;-)
Besides, it could be argued that when select times out it should leave the
timeout value alone, since a timeout is already signalled by returning zero
and the timeout value is likely to be used again.
Anyway, here's a patch to the RPC stuff -- I didn't look for select() calls
elsewhere in the library yet, somebody else can do that. And in case you're
wondering, no I didn't even compile this, much less test. ;-)
--- clnt_udp.c Thu Feb 11 23:35:07 1993
+++ clnt_udp.c+ Fri Feb 12 07:58:48 1993
@@ -233,7 +233,7 @@
struct sockaddr_in from;
struct rpc_msg reply_msg;
XDR reply_xdrs;
- struct timeval time_waited;
+ struct timeval time_waited, t_interval;
bool_t ok;
int nrefreshes = 2; /* number of times to refresh cred */
struct timeval timeout;
@@ -289,9 +289,10 @@
mask = 1 << cu->cu_sock;
#endif /* def FD_SETSIZE */
for (;;) {
+ t_interval = cu->cu_wait;
readfds = mask;
switch (select(_rpc_dtablesize(), &readfds, (void *)NULL,
- (void *)NULL, &(cu->cu_wait))) {
+ (void *)NULL, &t_interval)) {
case 0:
time_waited.tv_sec += cu->cu_wait.tv_sec;
--- pmap_rmt.c Thu Feb 11 23:35:06 1993
+++ pmap_rmt.c+ Fri Feb 12 07:55:38 1993
@@ -250,7 +250,7 @@
struct rmtcallargs a;
struct rmtcallres r;
struct rpc_msg msg;
- struct timeval t;
+ struct timeval t, t_interval;
char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
/*
@@ -330,8 +330,9 @@
msg.acpted_rply.ar_results.where = (caddr_t)&r;
msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
readfds = mask;
+ t_interval = t;
switch (select(_rpc_dtablesize(), &readfds, (void *)NULL,
- (void *)NULL, &t)) {
+ (void *)NULL, &t_interval)) {
case 0: /* timed out */
stat = RPC_TIMEDOUT;
--- svc_tcp.c Thu Feb 11 23:35:06 1993
+++ svc_tcp.c+ Fri Feb 12 07:57:03 1993
@@ -299,6 +299,7 @@
caddr_t buf;
register int len;
{
+ struct timeval t_interval;
register int sock = xprt->xp_sock;
#ifdef FD_SETSIZE
fd_set mask;
@@ -312,8 +313,9 @@
#endif /* def FD_SETSIZE */
do {
readfds = mask;
+ t_interval = wait_per_try;
if (select(_rpc_dtablesize(), &readfds, (void*)NULL, (void*)NULL,
- &wait_per_try) <= 0) {
+ &t_interval) <= 0) {
if (errno == EINTR) {
continue;
}
And for differently-minded people, there's a kernel patch which leaves the
timer value alone if select timed out:
--- fs/select.c Wed Feb 10 22:22:32 1993
+++ fs/select.c+ Fri Feb 12 08:06:56 1993
@@ -212,7 +212,7 @@
else
timeout = 0;
current->timeout = 0;
- if (tvp) {
+ if (tvp && i != 0) {
verify_area(tvp, sizeof(*tvp));
put_fs_long(timeout/HZ, (unsigned long *) &tvp->tv_sec);
timeout %= HZ;
-- Bring out your dead. -- Ian, DALEK INVASION OF EARTH -- Matthias Urlichs -- urlichs@smurf.sub.org -- urlichs@smurf.ira.uka.de /(o\ Humboldtstrasse 7 -- 7500 Karlsruhe 1 -- Germany -- +49-721-9612521 \o)/