2

Recently I found some code which uses signal:

  286 static void sighandler( int signum )
  287 {   
  288     alarmed = 1;
  289     signal( signum, sighandler );
  290 }
  291 
  292 void set_alarm( int seconds )
  293 {
  294     alarmed = 0;
  295     signal( SIGALRM, sighandler );
  296     alarm( seconds );
  297 }

I have some troubles to figure out why do I need to call signal 2 times, especially, why do I need to call signal in sighandler? I know what the above code does but dont understand why do I need to call signal 2 times.

yak
  • 3,770
  • 19
  • 60
  • 111

3 Answers3

2

(1) Calling signal two or more times is not unusual. It's just setting up two handlers for 2 different signals.

(2) Older unix systems used to reset a signals disposition to default after a handler was invoked. This code is reestablishing the handler.

The GNU man (2) signal page has a couple of paragraphs devoted to this in the "portability" section. Actually one of several reasons to use sigaction.

Duck
  • 26,924
  • 5
  • 64
  • 92
2

Handling Signals

The call to signal establishes signal handling for only one occurrence of a signal. Before the signal-handling function is called, the library resets the signal so that the default action is performed if the same signal occurs again. Resetting signal handling helps to prevent an infinite loop if, for example, an action performed in the signal handler raises the same signal again. If you want your handler to be used for a signal each time it occurs, you must call signal within the handler to reinstate it. You should be cautious in reinstating signal handling. For example, if you continually reinstate SIGINT handling, you may lose the ability to interrupt and terminate your program.

The signal() function defines the handling of the next received signal only, after which the default handling is reinstated. So it is necessary for the signal handler to call signal() if the program needs to continue handling signals using a non-default handler.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • So if I would like to use `sigaction` instead, should my code I pasted above look like this: http://pastie.org/private/4bxjmwwh4tgg5wq5qcxfw? thanks :) – yak Jul 18 '13 at 16:03
  • 1
    @yak `signal()` is specified in the C standard. `sigaction()` is **not** . So, yes, `sigaction()` will avoid the need for calling `signal().` – Grijesh Chauhan Jul 18 '13 at 16:07
  • 1
    @yak additionally by set `sa_flags = SA_RESTART;` , `sigaction()` also handles situations where a second signal comes in while handling a signal. [read this answer](http://stackoverflow.com/questions/17705842/is-there-a-way-to-make-my-program-work-with-less-code/17706116#17706116) – Grijesh Chauhan Jul 18 '13 at 16:08
  • 1
    @yak you are calling printf in signal handler, and its not safe to call it inside signalhandler because signal handler can be called asynchronously read : [How to avoid using printf in a signal handler?](http://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler/16891065#16891065) – Grijesh Chauhan Jul 18 '13 at 16:12
  • thank you! I removed `printf` and added a flag but is my code I pasted here in comments, correct? I mean I would like to do the same thing but with the use of `sigaction` instead of `signal` (learning purpose:) – yak Jul 18 '13 at 16:14
  • 1
    I suggest you if you want to handle signal in serious application learn from here [GNU: Signal Handling](http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC330) – Grijesh Chauhan Jul 18 '13 at 16:15
  • 1
    @yak *`would like to do the same thing but with the use of sigaction instead of signal`* ? => **Yes**, it is considered a better approach. – Grijesh Chauhan Jul 18 '13 at 16:19
  • But is my code I pases on `pastie` equivalent to the one I gave in my first, main question? Im not 100% sure ;) – yak Jul 18 '13 at 16:34
  • @yak didn't get you :( – Grijesh Chauhan Jul 18 '13 at 16:35
  • Im just asking if my code from here (with `signal`) : http://pastie.org/private/hrlk81ifsjgesghzve3ba does the same thing like my code with `sigaction` from here: http://pastie.org/private/4bxjmwwh4tgg5wq5qcxfw? I wrote them both to understand how signals work but Im not 100% sure is they're 'equal', if they do the same thing :) – yak Jul 18 '13 at 16:40
  • 1
    @yak yes, but as I said you no need to reset signalhandler again if you are using `sigaction()`. Second in 2nd implementation you are calling printf inside signal-handler. – Grijesh Chauhan Jul 18 '13 at 16:44
  • 1
    @yak No what I means you don't need line number 11 to 18 in your signal-handler that you registered using `sigaction()` function. Additionally if they behave different let me know. Read [this page](http://cboard.cprogramming.com/linux-programming/150239-when-re-enable-signal-handlers.html) precisely! where from I given information about `sigaction()` – Grijesh Chauhan Jul 18 '13 at 17:01
  • OK, removed lines from 11 to 18: http://pastie.org/private/igkotcigut2o20lhymgzw and it works fine :) – yak Jul 18 '13 at 17:03
1

There are systems where, if signal() is called with a function, the signal handler is reset to default after the first signal is caught (I haven't found out on the fly if it's defined to be so). That's the reason why signal() is called again in the signal handler.

Ingo Leonhardt
  • 9,435
  • 2
  • 24
  • 33