Re: Linux-2.1.54..

Darryl Miles (dlm@g7led.demon.co.uk)
Sat, 13 Sep 1997 01:32:15 +0100 (BST)


Hi,

If I've heard the Unix specification correctly applications are also broken
if they presume that the select timeout isn't modified and also if they
presume on how it has been modified. It's true to say "Applications should
consider the contents of the timeout to be undefined, after calling select(2)
use.".

This statement is obviously not true if you know extra information
on how it has been modified, in which case as no standard has defined how
to obtain this information then it's a platform specific issue, a Linux'ism
:-) and not what you're trying to address which is general software
portability.

How many broken commercial and non-commercial applications fall into
the area of presuming the timeout if not modified, even though the UNIX
specs now say that it maybe. If they are broken to start with then why are
we changing Linux policy, since these application will eventually be fixed
to confirm to the UNIX specification. AFAIK this fix (of reloading the
timeout every time, just before calling select(2)), then presuming nothing
about if after the syscall will make that application work with both Linux
(SLIPPY_TIMEOUTS) and DEC Unix (STICKY_TIMEOUTS).

You are advocating that it's broken applications which make use of
SLIPPY_TIMEOUTS, this is not true, yes it's a Linux'ism, but the application
using it is a Linux application, it has no interest or need to consider
other platforms. What you are really doing is bowing down to broken
application from other platforms, which presume the timeout is not modified.

Could I offer this (elegant, cough, cough) function as the basis for anyone
wanting to keep the old behavior.

It's arithmetic has had very little optimizational thought put on it.

I think if you rename the function to 'select' and rename the system calls
from 'select' to '__select' you may wrap your libc's select incarnation by
placing the resultant object code on the linker command line.

----------------------------------------------------------------------------
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

/* Number of usecs in one second */
#define TIMER_USEC_VAL 1000000

/* If you system doesn't support gettimeofday(), hah hah ha! */

int
linux_select(int maxfd, fd_set *readfd, fd_set *writefd, fd_set *exceptfd, struct timeval *timeout)
{
int retval;

if(timeout != NULL) {
struct timeval otv;
struct timeval ntv;

gettimeofday(&otv, NULL);

retval = select(maxfd, readfd, writefd, exceptfd, timeout);

gettimeofday(&ntv, NULL);

if(retval != 0) {
long sec, usec;
long nsec, nusec;

sec = ntv.tv_sec - otv.tv_sec;
usec = ntv.tv_usec - otv.tv_usec;

/* If usec is negative then drop the second */
if(usec < 0) {
/* usec is negative and (1000000 + (-500000)) = 500000 :-) */
usec = TIMER_USEC_VAL + usec;
sec--;
}

/* We now have the select sleep duration in 'sec' and 'usec' */

nsec = timeout->tv_sec - sec;
nusec = timeout->tv_usec - usec;

if(nusec < 0) {
/* nusec is negative and (1000000 + (-500000)) = 500000 :-) */
nusec = TIMER_USEC_VAL + nusec;
nsec--;
}

if(nsec < 0) {
nsec = 0;
nusec = 0;
}

timeout->tv_sec = nsec;
timeout->tv_usec = nusec;
} else {
timeout->tv_sec = 0;
timeout->tv_usec = 0;
}
} else {
retval = select(maxfd, readfd, writefd, exceptfd, timeout);
}

return retval;
}
----------------------------------------------------------------------------

-- 
Darryl Miles