1

i was reading about the use of pselect system call when i came across this code and comments...

static void handler(int sig) { /* do nothing */  }

int main(int argc, char *argv[])
{
    fd_set readfds;
    struct sigaction sa;
    int nfds, ready;

    sa.sa_handler = handler;     /* Establish signal handler */
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, NULL);
/* ... */    
    ready = select(nfds, &readfds, NULL, NULL, NULL);
/* ... */
}

this solution suffers from a race condition: if the SIGINT signal is delivered after
the call to sigaction(), but before the call to select(), it will fail to interrupt 
that select() call and will thus be lost.

now i am not sure about sigaction system call...initially i thought that it sort of saves a handler corresponding to a signal and that's it...when signal arrives it looks for its handler and handler is executed...but if that is correct then the handler corresponding to the signal would be saved for the entire program and it would be executed whenever the signal arrives...so however small the duration between sigaction and select, the signal would be handled...

but this code makes it seem like the signal is handled only when it coincides with the call/execution of sigaction...after the call is completed signal will not be handled by handler set by sigaction for the rest of the program(which i know, sounds absurd)

please explain!!

AvinashK
  • 3,309
  • 8
  • 43
  • 94
  • Does the code fork any processes or set up pipes? Is there any relevant code missing in this snippet? That is the only condition I could see creating a race condition. – squiguy Jun 21 '12 at 15:26
  • @squiguy...i don't think that's relevant...i took this from [here](http://lwn.net/Articles/176911/) – AvinashK Jun 21 '12 at 18:16

1 Answers1

2

You need to look at that code in the context of the article - the code is attempting to arrange for a signal to interrupt select(). The race condition mentioned does not cause sigaction() or the signal handler to fail in any way - it was just noting that there's a possibility that the signal could be delivered between the sigaction() call and the select() call, which makes that pattern unacceptable for achieving the desired outcome. You are right that a signal arriving any time after sigaction() will be handled, whether it's before, during, or after signal(). However, that can't be used to reliably provide an early interruption path for select(), which is what the context of the article is about.

twalberg
  • 59,951
  • 11
  • 89
  • 84
  • @twalberg...i get it now...just one question...if signal occurs while select() is blocking, it is known that select() returns...but after it returns is the signal automatically handled by the handler that we set or we have to call the handler explicitly... – AvinashK Jun 22 '12 at 05:48
  • My understanding is that, if the signal occurs while `select()` is sleeping, the handler gets called, then as the handler is returning, the system determines that we were in `select()` before the signal, and arranges for `select()` to return with an indication that it was interrupted. So `select()` doesn't return until after the signal's already been handled. – twalberg Jun 22 '12 at 13:11