11. <signal.h> Signals
The header <signal.h> provides facilities for handling exceptional conditions that arise during execution, such as an interrupt signal from an external source or an error in execution.
void (*signal(int sig, void (*handler)(int)))(int)
signal specifies the new signal handler handler for the signal sig and returns the previous handler, if successful; otherwise, it returns SIG_ERR.
l If handler is SIG_DFL, the implementation-defined default behavior is used for the signal.
l If handler is SIG_IGN, the signal is ignored;
l Otherwise, the function handler will be called with the value of the signal as its argument.
Valid signals include:
SIGABRT | abnormal termination | e.g.) abort |
SIGFPE | arithmetic error | e.g.) zero divide or overflow |
SIGILL | illegal function image | e.g.) illegal instruction |
SIGINT | interactive attention | e.g.) interrupt |
SIGSEGV | illegal storage access | e.g.) access outside memory limits |
SIGTERM | termination request |
When the signal sig subsequently occurs, the signal is restored to its default behavior; then the signal handler function is called, as if by (*handler)(sig). If the handler returns, execution will resume where it was when the signal occurred.
The initial state of signals is implementation-defined.
int raise(int sig)
raise sends the signal sig to the program; it returns non-zero if unsuccessful.
Example codes
l sig-1.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void sh_SIGABRT(int sig) {
printf("handling SIGABRT ...\n");
exit(0);
}
void main() {
printf("set: sh_SIGABRT\n"); signal(SIGABRT, sh_SIGABRT);
abort();
printf("end of main\n");
}
> sig-1
set: sh_SIGABRT
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
handling SIGABRT ...
> echo %ERRORLEVEL%
0
l sig-2.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
typedef void (*SH_T)(int); // signal handler type
void sh_SIGTERM_1(int sig) {
printf("sh_SIGTERM_1: handling SIGTERM ...\n");
}
void sh_SIGTERM_2(int sig) {
printf("sh_SIGTERM_2: handling SIGTERM ...\n");
}
void main() {
SH_T sh;
printf("set: sh_SIGTERM_1\n");
if (signal(SIGTERM, sh_SIGTERM_1) == SIG_ERR)
fprintf(stderr, "cannot set sh_SIGTERM_1\n"), exit(1);
printf("set: sh_SIGTERM_2\n");
if ((sh = signal(SIGTERM, sh_SIGTERM_2)) == SIG_ERR)
fprintf(stderr, "cannot set sh_SIGTERM_2\n"), exit(1);
raise(SIGTERM);
printf("reset: sh_SIGTERM_1\n");
if (signal(SIGTERM, sh) == SIG_ERR)
fprintf(stderr, "cannot set sh_SIGTERM_1\n"), exit(1);
raise(SIGTERM);
}
> sig-2
set: sh_SIGTERM_1
set: sh_SIGTERM_2
sh_SIGTERM_2: handling SIGTERM ...
reset: sh_SIGTERM_1
sh_SIGTERM_1: handling SIGTERM ...
> echo %ERRORLEVEL%
0
l sig-3.c
#include <stdio.h>
#include <signal.h>
void main() {
printf("set: SIG_IGN\n"); signal(SIGTERM, SIG_IGN);
printf("raising SIGTERM ...\n"); raise(SIGTERM);
printf("raised SIGTERM\n");
printf("raising SIGTERM ...\n"); raise(SIGTERM);
printf("raised SIGTERM\n");
printf("set: SIG_DFL\n"); signal(SIGTERM, SIG_DFL);
printf("raising SIGTERM ...\n"); raise(SIGTERM);
printf("raised SIGTERM\n"); // not executed
}
> sig-3
set: SIG_IGN
raising SIGTERM ...
raised SIGTERM
raising SIGTERM ...
raised SIGTERM
set: SIG_DFL
raising SIGTERM ...
> echo %ERRORLEVEL%
3
l sig-4.c
#include <stdio.h>
#include <signal.h>
void sh_SIGTERM(int sig) {
printf("sh_SIGTERM: handling SIGTERM ...\n");
}
void main() {
printf("set: sh_SIGTERM\n"); signal(SIGTERM, sh_SIGTERM);
printf("raising SIGTERM ...\n"); raise(SIGTERM);
printf("raised SIGTERM\n");
printf("raising SIGTERM ...\n"); raise(SIGTERM);
printf("raised SIGTERM\n"); // not executed
}
> sig-4
set: sh_SIGTERM
raising SIGTERM ...
sh_SIGTERM: handling SIGTERM ...
raised SIGTERM
raising SIGTERM ...
l sig-5.c
#include <stdio.h>
#include <signal.h>
void sh_SIGTERM(int sig) {
printf("handling SIGTERM ...\n");
printf("set: sh_SIGTERM\n"); signal(SIGTERM, sh_SIGTERM);
}
void main() {
printf("set: sh_SIGTERM\n"); signal(SIGTERM, sh_SIGTERM);
printf("raising SIGTERM ...\n"); raise(SIGTERM);
printf("raised SIGTERM\n");
printf("raising SIGTERM ...\n"); raise(SIGTERM);
printf("raised SIGTERM\n");
}
> sig-5
set: sh_SIGTERM
raising SIGTERM ...
handling SIGTERM ...
set: sh_SIGTERM
raised SIGTERM
raising SIGTERM ...
handling SIGTERM ...
set: sh_SIGTERM
raised SIGTERM
l sig-6.c
#include <stdio.h>
#include <signal.h>
void sh(int sig) {
if (sig == SIGTERM)
printf("handling SIGTERM ...\n"), signal(sig, sh);
else if (sig == SIGABRT)
printf("handling SIGABRT ...\n"), signal(sig, sh);
else
printf("no action for signal '%d' only once\n", sig);
}
void main() {
signal(SIGTERM, sh); signal(SIGABRT, sh);
signal(SIGINT, sh); signal(SIGILL, sh);
raise(SIGTERM); raise(SIGTERM);
raise(SIGABRT); raise(SIGABRT);
raise(SIGILL);
raise(SIGINT);
raise(SIGINT); // **
printf("end of main\n");
}
> sig-6
handling SIGTERM ...
handling SIGTERM ...
handling SIGABRT ...
handling SIGABRT ...
no action for signal '4' only once
no action for signal '2' only once
l sig-7.c
#include <stdio.h>
#include <signal.h>
void sh_SIGINT(int sig) {
static int count = 3;
printf("handle SIGINT ...\n");
if (--count > 0) signal(SIGINT, sh_SIGINT);
}
void main() {
signal(SIGINT, sh_SIGINT);
while (1) ;
}
> sig-7
^Chandle SIGINT ...
^Chandle SIGINT ...
^Chandle SIGINT ...
^C
No comments:
Post a Comment