0

Here I have some code sample:

/* some headers */
…
/****************/

void handler( int signum ){
    printf("Signal number: %d received\n", signum);
    signal(signum, SIG_DFL);
}

int main( int argc, char* argv[] ){
    signal(SIGINT, handler);

    while( "no signal was received" ){
        printf("another loop round\n");
        sleep(3);
    }

    return EXIT_SUCCESS;
}

and i was expecting my program to quit, with the message defined in my handler function, after CTRL + C keyboard combination, just like it normally happens, but i have to type the command twice and only after my second try it stops. And I would also like to ask another question regarding signal function. I've found a lot of references, where people would suggest using sigaction function instead of signal, but some of them are saying it'd be better for compatibility reasons to use signal. Could you give me some hints on which should I use? Thanks in advance

orustammanapov
  • 1,792
  • 5
  • 25
  • 44
  • 1
    Regarding `sigaction` vs `signal`, see http://stackoverflow.com/questions/231912/what-is-the-difference-between-sigaction-and-signal . – pilcrow Sep 21 '14 at 13:26

3 Answers3

5

With this line

signal(SIGINT, handler);

you replaced the default behaviour, which is to quit the program, by calling the handler(). That's why the program does not quit on recepetion of the signal.

The handler() then calls

signal(signum, SIG_DFL);

re-setting the default behaviour for SIGINT, which is to quit the program on (the next) reception of the signal.


OT: One shall not call printf() (among others) from signal handlers, at it (and the others) are not guranteed to be async-signal safe. See man 7 signal for a list of those functions.

alk
  • 69,737
  • 10
  • 105
  • 255
3
  • First Ctrl-C sends SIGINT to process, your program has a callback 'handler' for SIGINT processing, so your program won't quit.
  • Since handler reset SIGINT to default action (SIG_DFL), any next SIGINT received will trigger default action (Quit).
  • Second Ctrl-C triggers default action, your program quits.

Hope it's clear.

superjedi
  • 524
  • 3
  • 7
2

By default your program has a handler for SIGINT that exits. You have replaced it with signal(SIGINT, handler); If you want your program to exit when your handler is run you will need to call exit yourself. You could modify your handler to look like:

void handler( int signum ){
    printf("Signal number: %d received\n", signum);
    exit(1);
}

To avoid problems you shouldn't call printf from a signal handler because printf isn't re-entrant. The glibc documentation give this description of the problem:

If a function uses and modifies an object that you supply, then it is potentially non-reentrant; two calls can interfere if they use the same object. This case arises when you do I/O using streams. Suppose that the signal handler prints a message with fprintf. Suppose that the program was in the middle of an fprintf call using the same stream when the signal was delivered. Both the signal handler's message and the program's data could be corrupted, because both calls operate on the same data structure--the stream itself.

If you don't exit your program in the handler then your program will continue where it left off. The other option you have is to detect the SIGINT by the return value from sleep. If sleep exits early because of a signal like SIGINT being raised you can check it with the return value. The man page for sleep says

RETURN VALUE top

  Zero if the requested time has elapsed, or the number of seconds left
  to sleep, if the call was interrupted by a signal handler.

You could modify your loop to exit when sleep returns a value higher than 0 which means that it was interrupted early by a signal. Something like this would work:

signal(SIGINT, handler);

while( sleep(3) == 0 ){
    printf("another loop round\n");
}

As for your question about signal and sigaction - sigaction is the preferred way. A lot more about the reasons why can be found in this StackOverflow question and accepted answer

Community
  • 1
  • 1
Michael Petch
  • 46,082
  • 8
  • 107
  • 198