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