4

I want to use the select() function to wait for 1 second, as my program uses signals to control stuff, so sleep() would return prematurely. The weird thing is that when using select() it also returns prematurely.

I am calling select like this

struct timeval timeout;    
timeout.tv_sec = 10;  
timeout.tv_usec = 1000000; 
select (0 ,NULL, NULL, NULL, &timeout);

but whenever a signal arrives, it returns (I am using a nano second timer for the signal)

Anyone knows why?

rtruszk
  • 3,902
  • 13
  • 36
  • 53
Sergio Campamá
  • 746
  • 1
  • 7
  • 14

2 Answers2

6

Try something like this:

struct timespec timeout;
timeout.tv_sec = 10;
timeout.tv_nsec = 0;
while (nanosleep(&timeout, &timeout) && errno == EINTR);

The "remaining time" pointer to nanosleep will take care of letting you restart the sleep with the necessary amount of remaining time if it gets interrupted.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
5

man 7 signal says:

Interruption of System Calls and Library Functions by Signal Handlers

If a signal handler is invoked while a system call or library function call is blocked, then either:

   * the call is automatically restarted after the signal handler
     returns; or

   * the call fails with the error EINTR.

Which of these two behaviors occurs depends on the interface and whether or not the signal handler was established using the SA_RESTART flag (see sigaction(2)). The details vary across UNIX sys‐ tems; below, the details for Linux.

If a blocked call to one of the following interfaces is interrupted by a signal handler, then the call will be automatically restarted after the signal handler returns if the SA_RESTART flag was used; otherwise the call will fail with the error EINTR

Generally, checking if the return value is -1 and errno == EINTR and then re-calling the function is the right way to correct for this.

Cody Schafer
  • 369
  • 1
  • 5
  • 1
    This answer is incomplete and not OP's issue. Linux has the sane BSD behavior for signals (restartable syscalls), but `select` *always* returns when interrupted by a signal, even if the signal handler is installed with `SA_RESTART`, as a *feature*. The idea is that the program may (probably does) want to act on the receipt of a signal just like it would act on file descriptors ready for IO. – R.. GitHub STOP HELPING ICE Mar 04 '11 at 21:10
  • 1
    I think this is the explanation for the second answer's implementation. What I am doing is using a signal to track time, trying to mimic a microprocessor's clock interrupt interface. So the signal actually gets called every nanosecond, incrementing a time counter. Is this a bad way of doing it? There may be 100s of processes running at the same time using the exact same signal. I am using a timer created with timer_create and CLOCK_PROCESS_CPUTIME_ID for clockid_t – Sergio Campamá Mar 06 '11 at 00:10