The Linux Programming Interface

(nextflipdebug5) #1
Alternative I/O Models 1333

The timeout argument


The timeout argument controls the blocking behavior of select(). It can be specified
either as NULL, in which case select() blocks indefinitely, or as a pointer to a timeval
structure:


struct timeval {
time_t tv_sec; /* Seconds */
suseconds_t tv_usec; /* Microseconds (long int) */
};

If both fields of timeout are 0, then select() doesn’t block; it simply polls the specified
file descriptors to see which ones are ready and returns immediately. Otherwise,
timeout specifies an upper limit on the time for which select() is to wait.
Although the timeval structure affords microsecond precision, the accuracy of
the call is limited by the granularity of the software clock (Section 10.6). SUSv3
specifies that the timeout is rounded upward if it is not an exact multiple of this
granularity.


SUSv3 requires that the maximum permissible timeout interval be at least 31 days.
Most UNIX implementations allow a considerably higher limit. Since Linux/
x86-32 uses a 32-bit integer for the time_t type, the upper limit is many years.

When timeout is NULL, or points to a structure containing nonzero fields, select()
blocks until one of the following occurs:


z at least one of the file descriptors specified in readfds, writefds, or exceptfds
becomes ready;


z the call is interrupted by a signal handler; or


z the amount of time specified by timeout has passed.


In older UNIX implementations that lacked a sleep call with subsecond preci-
sion (e.g., nanosleep()), select() was used to emulate this functionality by specifying
nfds as 0; readfds, writefds, and exceptfds as NULL; and the desired sleep interval
in timeout.

On Linux, if select() returns because one or more file descriptors became ready, and
if timeout was non-NULL, then select() updates the structure to which timeout points to
indicate how much time remained until the call would have timed out. However,
this behavior is implementation-specific. SUSv3 also allows the possibility that an
implementation leaves the structure pointed to by timeout unchanged, and most
other UNIX implementations don’t modify this structure. Portable applications
that employ select() within a loop should always ensure that the structure pointed to
by timeout is initialized before each select() call, and should ignore the information
returned in the structure after the call.
SUSv3 states that the structure pointed to by timeout may be modified only on a
successful return from select(). However, on Linux, if select() is interrupted by a signal
handler (so that it fails with the error EINTR), then the structure is modified to indicate
the time remaining until a timeout would have occurred (i.e., like a successful return).

Free download pdf