The Linux Programming Interface

(nextflipdebug5) #1

486 Chapter 23


23.3 Setting Timeouts on Blocking Operations


One use of real-time timers is to place an upper limit on the time for which a block-
ing system call can remain blocked. For example, we may wish to cancel a read()
from a terminal if the user has not entered a line of input within a certain time. We
can do this as follows:


  1. Call sigaction() to establish a handler for SIGALRM, omitting the SA_RESTART flag, so
    that system calls are not restarted (refer to Section 21.5).

  2. Call alarm() or setitimer() to establish a timer specifying the upper limit of time
    for which we wish the system call to block.

  3. Make the blocking system call.

  4. After the system call returns, call alarm() or setitimer() once more to disable the
    timer (in case the system call completed before the timer expired).

  5. Check to see whether the blocking system call failed with errno set to EINTR
    (interrupted system call).


Listing 23-2 demonstrates this technique for read(), using alarm() to establish the
timer.

Listing 23-2: Performing a read() with timeout
–––––––––––––––––––––––––––––––––––––––––––––––––––––– timers/timed_read.c
#include <signal.h>
#include "tlpi_hdr.h"

#define BUF_SIZE 200

static void /* SIGALRM handler: interrupts blocked system call */
handler(int sig)
{
printf("Caught signal\n"); /* UNSAFE (see Section 21.1.2) */
}

int
main(int argc, char *argv[])
{
struct sigaction sa;
char buf[BUF_SIZE];
ssize_t numRead;
int savedErrno;

if (argc > 1 && strcmp(argv[1], "--help") == 0)
usageErr("%s [num-secs [restart-flag]]\n", argv[0]);

/* Set up handler for SIGALRM. Allow system calls to be interrupted,
unless second command-line argument was supplied. */

sa.sa_flags = (argc > 2)? SA_RESTART : 0;
sigemptyset(&sa.sa_mask);
Free download pdf