1 /* sighandle.c -- Library routines for manipulating chains of signal handlers 2 Copyright (C) 1992 Free Software Foundation, Inc. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. */ 13 14 /* Written by Paul Sander, HaL Computer Systems, Inc. <paul@hal.com> 15 Brian Berliner <berliner@Sun.COM> added POSIX support */ 16 17 /************************************************************************* 18 * 19 * signal.c -- This file contains code that manipulates chains of signal 20 * handlers. 21 * 22 * Facilities are provided to register a signal handler for 23 * any specific signal. When a signal is received, all of the 24 * registered signal handlers are invoked in the reverse order 25 * in which they are registered. Note that the signal handlers 26 * must not themselves make calls to the signal handling 27 * facilities. 28 * 29 *************************************************************************/ 30 31 #ifdef HAVE_CONFIG_H 32 #include "config.h" 33 #endif 34 #include "system.h" 35 36 #include <sys/types.h> 37 #include <stdio.h> 38 #include <signal.h> 39 40 #ifdef STDC_HEADERS 41 #include <stdlib.h> 42 #else 43 #if __STDC__ 44 char *calloc(unsigned nelem, unsigned size); 45 char *malloc(unsigned size); 46 #else 47 char *calloc(); 48 char *malloc(); 49 #endif /* __STDC__ */ 50 #endif /* STDC_HEADERS */ 51 52 /* Define the highest signal number (usually) */ 53 #ifndef SIGMAX 54 #define SIGMAX 64 55 #endif 56 57 /* Define linked list of signal handlers structure */ 58 struct SIG_hlist { 59 RETSIGTYPE (*handler)(); 60 struct SIG_hlist *next; 61 }; 62 63 /* 64 * Define array of lists of signal handlers. Note that this depends on 65 * the implementation to initialize each element to a null pointer. 66 */ 67 68 static struct SIG_hlist **SIG_handlers; 69 70 /* Define array of default signal vectors */ 71 72 #ifdef POSIX_SIGNALS 73 static struct sigaction *SIG_defaults; 74 #else 75 #ifdef BSD_SIGNALS 76 static struct sigvec *SIG_defaults; 77 #else 78 static RETSIGTYPE (**SIG_defaults) (int); 79 #endif 80 #endif 81 82 /* Critical section housekeeping */ 83 static int SIG_crSectNest = 0; /* Nesting level */ 84 #ifdef POSIX_SIGNALS 85 static sigset_t SIG_crSectMask; /* Signal mask */ 86 #else 87 static int SIG_crSectMask; /* Signal mask */ 88 #endif 89 90 /* 91 * Initialize the signal handler arrays 92 */ 93 94 static int SIG_init() 95 { 96 int i; 97 #ifdef POSIX_SIGNALS 98 sigset_t sigset_test; 99 #endif 100 101 if (SIG_defaults && SIG_handlers) /* already allocated */ 102 return (0); 103 104 #ifdef POSIX_SIGNALS 105 (void) sigfillset(&sigset_test); 106 for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++) 107 ; 108 if (i < SIGMAX) 109 i = SIGMAX; 110 i++; 111 if (!SIG_defaults) 112 SIG_defaults = (struct sigaction *) 113 calloc(i, sizeof(struct sigaction)); 114 (void) sigemptyset(&SIG_crSectMask); 115 #else 116 i = SIGMAX+1; 117 #ifdef BSD_SIGNALS 118 if (!SIG_defaults) 119 SIG_defaults = (struct sigvec *) 120 calloc(i, sizeof(struct sigvec)); 121 #else 122 if (!SIG_defaults) 123 SIG_defaults = ( RETSIGTYPE (**) (int) ) 124 calloc( i, sizeof( RETSIGTYPE (**) (int) ) ); 125 #endif 126 SIG_crSectMask = 0; 127 #endif 128 if (!SIG_handlers) 129 SIG_handlers = (struct SIG_hlist **) 130 calloc(i, sizeof(struct SIG_hlist *)); 131 return (!SIG_defaults || !SIG_handlers); 132 } 133 134 135 136 /* 137 * The following begins a critical section. 138 */ 139 void SIG_beginCrSect (void) 140 { 141 if (SIG_init() == 0) 142 { 143 if (SIG_crSectNest == 0) 144 { 145 #ifdef POSIX_SIGNALS 146 sigset_t sigset_mask; 147 148 (void) sigfillset(&sigset_mask); 149 (void) sigprocmask(SIG_SETMASK, 150 &sigset_mask, &SIG_crSectMask); 151 #else 152 #ifdef BSD_SIGNALS 153 SIG_crSectMask = sigblock(~0); 154 #else 155 /* TBD */ 156 #endif 157 #endif 158 } 159 SIG_crSectNest++; 160 } 161 } 162 163 164 165 /* 166 * The following ends a critical section. 167 */ 168 void SIG_endCrSect (void) 169 { 170 if (SIG_init() == 0) 171 { 172 SIG_crSectNest--; 173 if (SIG_crSectNest == 0) 174 { 175 #ifdef POSIX_SIGNALS 176 (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL); 177 #else 178 #ifdef BSD_SIGNALS 179 (void) sigsetmask(SIG_crSectMask); 180 #else 181 /* TBD */ 182 #endif 183 #endif 184 } 185 } 186 } 187 188 189 190 /* 191 * The following invokes each signal handler in the reverse order in which 192 * they were registered. 193 */ 194 static RETSIGTYPE SIG_handle (int sig) 195 { 196 struct SIG_hlist *this; 197 198 /* Dispatch signal handlers */ 199 /* This crit section stuff is a CVSism - we know that our interrupt 200 * handlers will always end up exiting and we don't want them to be 201 * interrupted themselves. 202 */ 203 SIG_beginCrSect(); 204 this = SIG_handlers[sig]; 205 while (this != (struct SIG_hlist *) NULL) 206 { 207 (*this->handler)(sig); 208 this = this->next; 209 } 210 SIG_endCrSect(); 211 212 return; 213 } 214 215 /* 216 * The following registers a signal handler. If the handler is already 217 * registered, it is not registered twice, nor is the order in which signal 218 * handlers are invoked changed. If this is the first signal handler 219 * registered for a given signal, the old sigvec structure is saved for 220 * restoration later. 221 */ 222 223 int SIG_register(int sig, RETSIGTYPE (*fn)()) 224 { 225 int val; 226 struct SIG_hlist *this; 227 #ifdef POSIX_SIGNALS 228 struct sigaction act; 229 sigset_t sigset_mask, sigset_omask; 230 #else 231 #ifdef BSD_SIGNALS 232 struct sigvec vec; 233 int mask; 234 #endif 235 #endif 236 237 /* Initialize */ 238 if (SIG_init() != 0) 239 return (-1); 240 val = 0; 241 242 /* Block this signal while we look at handler chain */ 243 #ifdef POSIX_SIGNALS 244 (void) sigemptyset(&sigset_mask); 245 (void) sigaddset(&sigset_mask, sig); 246 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask); 247 #else 248 #ifdef BSD_SIGNALS 249 mask = sigblock(sigmask(sig)); 250 #endif 251 #endif 252 253 /* See if this handler was already registered */ 254 this = SIG_handlers[sig]; 255 while (this != (struct SIG_hlist *) NULL) 256 { 257 if (this->handler == fn) break; 258 this = this->next; 259 } 260 261 /* Register the new handler only if it is not already registered. */ 262 if (this == (struct SIG_hlist *) NULL) 263 { 264 265 /* 266 * If this is the first handler registered for this signal, 267 * set up the signal handler dispatcher 268 */ 269 270 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL) 271 { 272 #ifdef POSIX_SIGNALS 273 act.sa_handler = SIG_handle; 274 (void) sigemptyset(&act.sa_mask); 275 act.sa_flags = 0; 276 val = sigaction(sig, &act, &SIG_defaults[sig]); 277 #else 278 #ifdef BSD_SIGNALS 279 memset (&vec, 0, sizeof (vec)); 280 vec.sv_handler = SIG_handle; 281 val = sigvec(sig, &vec, &SIG_defaults[sig]); 282 #else 283 if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR) 284 val = -1; 285 #endif 286 #endif 287 } 288 289 /* If not, register it */ 290 if ((val == 0) && (this == (struct SIG_hlist *) NULL)) 291 { 292 this = (struct SIG_hlist *) 293 malloc(sizeof(struct SIG_hlist)); 294 if (this == NULL) 295 { 296 val = -1; 297 } 298 else 299 { 300 this->handler = fn; 301 this->next = SIG_handlers[sig]; 302 SIG_handlers[sig] = this; 303 } 304 } 305 } 306 307 /* Unblock the signal */ 308 #ifdef POSIX_SIGNALS 309 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL); 310 #else 311 #ifdef BSD_SIGNALS 312 (void) sigsetmask(mask); 313 #endif 314 #endif 315 316 return val; 317 } 318 319 320 321 /* 322 * The following deregisters a signal handler. If the last signal handler for 323 * a given signal is deregistered, the default sigvec information is restored. 324 */ 325 326 int SIG_deregister(int sig, RETSIGTYPE (*fn)()) 327 { 328 int val; 329 struct SIG_hlist *this; 330 struct SIG_hlist *last; 331 #ifdef POSIX_SIGNALS 332 sigset_t sigset_mask, sigset_omask; 333 #else 334 #ifdef BSD_SIGNALS 335 int mask; 336 #endif 337 #endif 338 339 /* Initialize */ 340 if (SIG_init() != 0) 341 return (-1); 342 val = 0; 343 last = (struct SIG_hlist *) NULL; 344 345 /* Block this signal while we look at handler chain */ 346 #ifdef POSIX_SIGNALS 347 (void) sigemptyset(&sigset_mask); 348 (void) sigaddset(&sigset_mask, sig); 349 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask); 350 #else 351 #ifdef BSD_SIGNALS 352 mask = sigblock(sigmask(sig)); 353 #endif 354 #endif 355 356 /* Search for the signal handler */ 357 this = SIG_handlers[sig]; 358 while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn)) 359 { 360 last = this; 361 this = this->next; 362 } 363 364 /* If it was registered, remove it */ 365 if (this != (struct SIG_hlist *) NULL) 366 { 367 if (last == (struct SIG_hlist *) NULL) 368 { 369 SIG_handlers[sig] = this->next; 370 } 371 else 372 { 373 last->next = this->next; 374 } 375 free((char *) this); 376 } 377 378 /* Restore default behavior if there are no registered handlers */ 379 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL) 380 { 381 #ifdef POSIX_SIGNALS 382 val = sigaction(sig, &SIG_defaults[sig], 383 (struct sigaction *) NULL); 384 #else 385 #ifdef BSD_SIGNALS 386 val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL); 387 #else 388 if (signal(sig, SIG_defaults[sig]) == SIG_ERR) 389 val = -1; 390 #endif 391 #endif 392 } 393 394 /* Unblock the signal */ 395 #ifdef POSIX_SIGNALS 396 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL); 397 #else 398 #ifdef BSD_SIGNALS 399 (void) sigsetmask(mask); 400 #endif 401 #endif 402 403 return val; 404 } 405 406 407 408 /* 409 * Return nonzero if currently in a critical section. 410 * Otherwise return zero. 411 */ 412 413 int SIG_inCrSect (void) 414 { 415 return SIG_crSectNest > 0; 416 } 417