Search code examples
c++select-syscall

How to correctly use in sys/select.h


When using the timer in the following code, either the "Error calling select" error appears, otherwise new data is expected:

    timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    if( select(s + 1, &readmask, NULL, NULL, &tv ) <= 0 )
    {
         perror("Error calling select");
         return 0;
    }

What can be done on the client without breaking the session in order to avoid this error when you re-access this code?


Solution

  • You should not be using <= 0 as the condition since 0 means timeout and < 0 means error.

    Alternative:

    if(int rv = select(s + 1, &readmask, NULL, NULL, &tv ); rv > 0) {
        // success
    } else if(rv == 0) {
        // timeout
    } else {
        // error
    }
    

    What can be done on the client without breaking the session in order to avoid this error when you re-access this code?

    If you get timeouts too quickly after you've changed the code to the above you should take a closer look at the timeout parameter. You should reinitialize it before each call to select:

    "On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this. (POSIX.1 permits either behavior.) 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 select()s in a loop without reinitializing it. Consider timeout to be undefined after select() returns."

    ...

    "On Linux, select() also modifies timeout if the call is interrupted by a signal handler (i.e., the EINTR error return). This is not permitted by POSIX.1."