1 /* sighandle.c -- Library routines for manipulating chains of signal handlers
2 Copyright (C) 1992 Free Software Foundation, Inc.
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)
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. */
14 /* Written by Paul Sander, HaL Computer Systems, Inc. <paul@hal.com>
15 Brian Berliner <berliner@Sun.COM> added POSIX support */
17 /*************************************************************************
19 * signal.c -- This file contains code that manipulates chains of signal
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
29 *************************************************************************/
36 #include <sys/types.h>
40 /* Add prototype support. */
42 #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
43 #define PROTO(ARGS) ARGS
45 #define PROTO(ARGS) ()
53 char *calloc(unsigned nelem, unsigned size);
54 char *malloc(unsigned size);
59 #endif /* STDC_HEADERS */
61 /* Define the highest signal number (usually) */
66 /* Define linked list of signal handlers structure */
68 RETSIGTYPE (*handler)();
69 struct SIG_hlist *next;
73 * Define array of lists of signal handlers. Note that this depends on
74 * the implementation to initialize each element to a null pointer.
77 static struct SIG_hlist **SIG_handlers;
79 /* Define array of default signal vectors */
82 static struct sigaction *SIG_defaults;
85 static struct sigvec *SIG_defaults;
87 static RETSIGTYPE (**SIG_defaults) PROTO ((int));
91 /* Critical section housekeeping */
92 static int SIG_crSectNest = 0; /* Nesting level */
94 static sigset_t SIG_crSectMask; /* Signal mask */
96 static int SIG_crSectMask; /* Signal mask */
100 * Initialize the signal handler arrays
103 static int SIG_init()
107 sigset_t sigset_test;
110 if (SIG_defaults && SIG_handlers) /* already allocated */
114 (void) sigfillset(&sigset_test);
115 for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++)
121 SIG_defaults = (struct sigaction *)
122 calloc(i, sizeof(struct sigaction));
123 (void) sigemptyset(&SIG_crSectMask);
128 SIG_defaults = (struct sigvec *)
129 calloc(i, sizeof(struct sigvec));
132 SIG_defaults = (RETSIGTYPE (**) PROTO ((int)) )
133 calloc(i, sizeof(RETSIGTYPE (**) PROTO ((int)) ));
138 SIG_handlers = (struct SIG_hlist **)
139 calloc(i, sizeof(struct SIG_hlist *));
140 return (!SIG_defaults || !SIG_handlers);
144 * The following invokes each signal handler in the reverse order in which
145 * they were registered.
147 static RETSIGTYPE SIG_handle PROTO ((int));
149 static RETSIGTYPE SIG_handle(sig)
152 struct SIG_hlist *this;
154 /* Dispatch signal handlers */
155 this = SIG_handlers[sig];
156 while (this != (struct SIG_hlist *) NULL)
158 (*this->handler)(sig);
166 * The following registers a signal handler. If the handler is already
167 * registered, it is not registered twice, nor is the order in which signal
168 * handlers are invoked changed. If this is the first signal handler
169 * registered for a given signal, the old sigvec structure is saved for
173 int SIG_register(sig,fn)
178 struct SIG_hlist *this;
180 struct sigaction act;
181 sigset_t sigset_mask, sigset_omask;
194 /* Block this signal while we look at handler chain */
196 (void) sigemptyset(&sigset_mask);
197 (void) sigaddset(&sigset_mask, sig);
198 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
201 mask = sigblock(sigmask(sig));
205 /* See if this handler was already registered */
206 this = SIG_handlers[sig];
207 while (this != (struct SIG_hlist *) NULL)
209 if (this->handler == fn) break;
213 /* Register the new handler only if it is not already registered. */
214 if (this == (struct SIG_hlist *) NULL)
218 * If this is the first handler registered for this signal,
219 * set up the signal handler dispatcher
222 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
225 act.sa_handler = SIG_handle;
226 (void) sigemptyset(&act.sa_mask);
228 val = sigaction(sig, &act, &SIG_defaults[sig]);
231 memset (&vec, 0, sizeof (vec));
232 vec.sv_handler = SIG_handle;
233 val = sigvec(sig, &vec, &SIG_defaults[sig]);
235 if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR)
241 /* If not, register it */
242 if ((val == 0) && (this == (struct SIG_hlist *) NULL))
244 this = (struct SIG_hlist *)
245 malloc(sizeof(struct SIG_hlist));
253 this->next = SIG_handlers[sig];
254 SIG_handlers[sig] = this;
259 /* Unblock the signal */
261 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
264 (void) sigsetmask(mask);
272 * The following deregisters a signal handler. If the last signal handler for
273 * a given signal is deregistered, the default sigvec information is restored.
276 int SIG_deregister(sig,fn)
281 struct SIG_hlist *this;
282 struct SIG_hlist *last;
284 sigset_t sigset_mask, sigset_omask;
295 last = (struct SIG_hlist *) NULL;
297 /* Block this signal while we look at handler chain */
299 (void) sigemptyset(&sigset_mask);
300 (void) sigaddset(&sigset_mask, sig);
301 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
304 mask = sigblock(sigmask(sig));
308 /* Search for the signal handler */
309 this = SIG_handlers[sig];
310 while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn))
316 /* If it was registered, remove it */
317 if (this != (struct SIG_hlist *) NULL)
319 if (last == (struct SIG_hlist *) NULL)
321 SIG_handlers[sig] = this->next;
325 last->next = this->next;
330 /* Restore default behavior if there are no registered handlers */
331 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
334 val = sigaction(sig, &SIG_defaults[sig],
335 (struct sigaction *) NULL);
338 val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
340 if (signal(sig, SIG_defaults[sig]) == SIG_ERR)
346 /* Unblock the signal */
348 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
351 (void) sigsetmask(mask);
359 * The following begins a critical section.
362 void SIG_beginCrSect()
366 if (SIG_crSectNest == 0)
369 sigset_t sigset_mask;
371 (void) sigfillset(&sigset_mask);
372 (void) sigprocmask(SIG_SETMASK,
373 &sigset_mask, &SIG_crSectMask);
376 SIG_crSectMask = sigblock(~0);
387 * Return nonzero if currently in a critical section.
388 * Otherwise return zero.
393 return SIG_crSectNest > 0;
397 * The following ends a critical section.
405 if (SIG_crSectNest == 0)
408 (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL);
411 (void) sigsetmask(SIG_crSectMask);