00001 /* 00002 Minimal defensive signal handling using sigwait (bad example) 00003 AUP2, Sec. 9.02.2 00004 00005 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00006 May be copied only for purposes and under conditions described 00007 on the Web page www.basepath.com/aup/copyright.htm. 00008 00009 The Example Files are provided "as is," without any warranty; 00010 without even the implied warranty of merchantability or fitness 00011 for a particular purpose. The author and his publisher are not 00012 responsible for any damages, direct or incidental, resulting 00013 from the use or non-use of these Example Files. 00014 00015 The Example Files may contain defects, and some contain deliberate 00016 coding mistakes that were included for educational reasons. 00017 You are responsible for determining if and how the Example Files 00018 are to be used. 00019 00020 */ 00021 #include "defs.h" 00022 #include <pthread.h> 00023 00024 /*[clean_up]*/ 00025 static void clean_up(void) 00026 { 00027 /* 00028 Clean-up code goes here -- 00029 need not be async-signal-safe. 00030 */ 00031 } 00032 /*[]*/ 00033 // redition of earlier example, but not necessarily what you want in a 00034 // multithreaded program 00035 /*[sig_thread]*/ 00036 static void *sig_thread(void *arg) 00037 { 00038 int signum; 00039 int i; 00040 struct { 00041 int signum; 00042 char *msg; 00043 } sigmsg[] = { 00044 { SIGTERM, "Termination signal" }, 00045 { SIGBUS, "Access to undefined portion of a memory object" }, 00046 { SIGFPE, "Erroneous arithmetic operation" }, 00047 { SIGILL, "Illegal instruction" }, 00048 { SIGSEGV, "Invalid memory reference" }, 00049 { SIGSYS, "Bad system call" }, 00050 { SIGXCPU, "CPU-time limit exceeded" }, 00051 { SIGXFSZ, "File-size limit exceeded" }, 00052 { 0, NULL} 00053 }; 00054 00055 { 00056 int x = 1, y; 00057 00058 printf("about to divide by zero\n"); 00059 y = x / 0; 00060 } 00061 printf("still alive\n"); 00062 while (true) { 00063 ec_rv( sigwait((sigset_t *)arg, &signum) ) 00064 clean_up(); 00065 for (i = 0; sigmsg[i].signum > 0; i++) 00066 if (sigmsg[i].signum == signum) { 00067 fprintf(stderr, "%s\n", sigmsg[i].msg); 00068 break; 00069 } 00070 _exit(EXIT_FAILURE); 00071 } 00072 return (void *)true; /* never get here */ 00073 00074 EC_CLEANUP_BGN 00075 EC_FLUSH("sig_thread") 00076 return (void *)false; 00077 EC_CLEANUP_END 00078 } 00079 /*[handler]*/ 00080 static void handler(int signum) 00081 { 00082 printf("got %d in handler\n", signum); 00083 } 00084 /*[handle_signals]*/ 00085 static bool handle_signals(void) 00086 { 00087 sigset_t *set; 00088 struct sigaction act; 00089 pthread_t tid; 00090 00091 ec_null( set = malloc(sizeof(*set)) ) 00092 ec_neg1( sigfillset(set) ) 00093 ec_rv( pthread_sigmask(SIG_SETMASK, set, NULL) ) 00094 memset(&act, 0, sizeof(act)); 00095 act.sa_handler = SIG_IGN; 00096 ec_neg1( sigaction(SIGHUP, &act, NULL) ) 00097 ec_neg1( sigaction(SIGINT, &act, NULL) ) 00098 ec_neg1( sigaction(SIGQUIT, &act, NULL) ) 00099 ec_neg1( sigaction(SIGPIPE, &act, NULL) ) 00100 ec_neg1( sigemptyset(set) ) 00101 ec_neg1( sigaddset(set, SIGTERM) ) 00102 ec_neg1( sigaddset(set, SIGBUS) ) 00103 ec_neg1( sigaddset(set, SIGFPE) ) 00104 ec_neg1( sigaddset(set, SIGILL) ) 00105 ec_neg1( sigaddset(set, SIGSEGV) ) 00106 ec_neg1( sigaddset(set, SIGSYS) ) 00107 ec_neg1( sigaddset(set, SIGXCPU) ) 00108 ec_neg1( sigaddset(set, SIGXFSZ) ) 00109 ec_rv( pthread_sigmask(SIG_SETMASK, set, NULL) ) 00110 ec_rv( pthread_create(&tid, NULL, sig_thread, set) ) 00111 return true; 00112 00113 EC_CLEANUP_BGN 00114 return false; 00115 EC_CLEANUP_END 00116 } 00117 /*[]*/ 00118 void process(void) 00119 { 00120 ec_false (handle_signals() ) 00121 sleep(2); 00122 { 00123 int x = 1, y; 00124 00125 //y = x / 0; 00126 } 00127 exit(EXIT_SUCCESS); 00128 00129 EC_CLEANUP_BGN 00130 exit(EXIT_FAILURE); 00131 EC_CLEANUP_END 00132 } 00133 00134 #define MAX_SIG 50 00135 00136 int main(void) 00137 { 00138 int signum; 00139 pid_t pid[MAX_SIG + 1]; 00140 int status; 00141 00142 for (signum = 1; signum <= MAX_SIG; signum++) { 00143 ec_neg1( pid[signum] = fork() ) 00144 if (pid[signum] == 0) 00145 process(); 00146 sleep(1); 00147 printf("\nSending signal %d...\n", signum); 00148 //if (kill(pid[signum], signum) == -1) 00149 // printf("\tkill failed\n"); 00150 ec_neg1( waitpid(-1, &status, WUNTRACED) ) 00151 if (WIFEXITED(status)) 00152 printf("%ld exited normally\n", (long)pid[signum]); 00153 else if (WIFSIGNALED(status)) 00154 printf("%ld exited with signal %d\n", (long)pid[signum], 00155 WTERMSIG(status)); 00156 else 00157 printf("wait returned with other status\n"); 00158 } 00159 for (signum = 1; signum <= MAX_SIG; signum++) 00160 (void)kill(pid[signum], SIGKILL); 00161 exit(EXIT_SUCCESS); 00162 00163 EC_CLEANUP_BGN 00164 exit(EXIT_FAILURE); 00165 EC_CLEANUP_END 00166 } 00167 /*[]*/