From: Matthias Urlichs (urlichs@smurf.sub.org)
Date: 02/12/93


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)/