Monday, June 11, 2007

Is this implementation of select() syscall in Linux correct?

Here is the code
linuxMachine:/tmp # uname -a
Linux linuxMachine 2.4.21-309.PTF.97199.1-smp #1 SMP Mon Jul 24 12:20:00 UTC 2006 i686 unknown
linuxMachine:/tmp # cat testSelectCall.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;


FD_ZERO(&rfds);
FD_SET(0, &rfds);

tv.tv_sec = 5;
tv.tv_usec = 0;

retval = select(1, &rfds, NULL, NULL, &tv);
/* Here is the tricky part! */

printf("tv.tv_sec=%i\n",tv.tv_sec);
printf("tv.tv_usec=%i\n",tv.tv_usec);
if (retval)
printf("Data is available now.\n");
else
printf("No data within five seconds.\n");

return 0;
}
linuxMachine:/tmp # !gcc
gcc testSelectCall.c
linuxMachine:/tmp # !time
time ./a.out
tv.tv_sec=0
tv.tv_usec=0

No data within five seconds.

real 0m5.000s
user 0m0.000s
sys 0m0.000s
linuxMachine:/tmp #

On a solaris box

solarisBox>uname -a
SunOS solarisBox 5.10 Generic_118835-02 sun4u sparc SUNW,Sun-Blade-100
solarisBox>gcc testSelectCall.c
solarisBox>!time
time ./a.out
tv.tv_sec=5
tv.tv_usec=0

No data within five seconds.

real 0m5.025s
user 0m0.003s
sys 0m0.010s
solarisBox>


Man Page has the following description
man 2 select

Some code calls select with all three sets empty, n zero, and a non-null
timeout as a fairly portable way to sleep with subsecond precision.

On Linux, the function select modifies timeout to reflect the amount of
time not slept; most other implementations do not do this. This causes
problems both when Linux code which reads timeout is ported to other
operating systems, and when code is ported to Linux that reuses a struct
timeval for multiple selects in a loop without reinitializing it. Con�
sider timeout to be undefined after select returns.

6 comments:

Girish said...

goood catch...

rakesh rc said...
This comment has been removed by the author.
rakesh rc said...

I was seeing open group standards page about what they say on select() call.

http://stds107.cup.hp.com/stds/cdrom/susv3/html/susv3/functions/select.html

They say this :-

"The timeout parameter controls how long the pselect() or select() function shall take before timing out. If the timeout parameter is not a null pointer, it specifies a maximum interval to wait for the selection to complete."

which means, select() behaviour on linux is not unix2003 conforming.

If linux man page even says this, then it is incorrect behaviour other wise it should not be incorrect since their behaviour would be compatible with their man page.

Can you check ?

Shantanu said...

Looks like
http://stds107.cup.hp.com/
is an internal site of HP.

rakesh rc said...

Shantanu,

I checked linux man page, it says this :-
"The select function may update the timeout parameter to indicate how much time was left."

So, this isnt a defect but it doesnot conform to open group standards.

Shantanu said...

exactly .... these cases affect porting. The whole concept of standards goes for a toss.