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 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Written by Paul Sander, HaL Computer Systems, Inc. <paul@hal.com>
19 Brian Berliner <berliner@Sun.COM> added POSIX support */
21 /*************************************************************************
23 * signal.c -- This file contains code that manipulates chains of signal
26 * Facilities are provided to register a signal handler for
27 * any specific signal. When a signal is received, all of the
28 * registered signal handlers are invoked in the reverse order
29 * in which they are registered. Note that the signal handlers
30 * must not themselves make calls to the signal handling
33 * $CVSid: @(#)sighandle.c 1.13 94/10/07 $
35 *************************************************************************/
42 #include <sys/types.h>
46 /* Add prototype support. */
48 #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
49 #define PROTO(ARGS) ARGS
51 #define PROTO(ARGS) ()
59 char *calloc(unsigned nelem, unsigned size);
60 char *malloc(unsigned size);
65 #endif /* STDC_HEADERS */
67 /* Define the highest signal number (usually) */
72 /* Define linked list of signal handlers structure */
74 RETSIGTYPE (*handler)();
75 struct SIG_hlist *next;
79 * Define array of lists of signal handlers. Note that this depends on
80 * the implementation to initialize each element to a null pointer.
83 static struct SIG_hlist **SIG_handlers;
85 /* Define array of default signal vectors */
88 static struct sigaction *SIG_defaults;
91 static struct sigvec *SIG_defaults;
93 static RETSIGTYPE (**SIG_defaults) PROTO ((int));
97 /* Critical section housekeeping */
98 static int SIG_crSectNest = 0; /* Nesting level */
100 static sigset_t SIG_crSectMask; /* Signal mask */
102 static int SIG_crSectMask; /* Signal mask */
106 * Initialize the signal handler arrays
109 static int SIG_init()
113 sigset_t sigset_test;
116 if (SIG_defaults && SIG_handlers) /* already allocated */
120 (void) sigfillset(&sigset_test);
121 for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++)
127 SIG_defaults = (struct sigaction *)
128 calloc(i, sizeof(struct sigaction));
129 (void) sigemptyset(&SIG_crSectMask);
134 SIG_defaults = (struct sigvec *)
135 calloc(i, sizeof(struct sigvec));
138 SIG_defaults = (RETSIGTYPE (**) PROTO ((int)) )
139 calloc(i, sizeof(RETSIGTYPE (**) PROTO ((int)) ));
144 SIG_handlers = (struct SIG_hlist **)
145 calloc(i, sizeof(struct SIG_hlist *));
146 return (!SIG_defaults || !SIG_handlers);
150 * The following invokes each signal handler in the reverse order in which
151 * they were registered.
153 static RETSIGTYPE SIG_handle PROTO ((int));
155 static RETSIGTYPE SIG_handle(sig)
158 struct SIG_hlist *this;
160 /* Dispatch signal handlers */
161 this = SIG_handlers[sig];
162 while (this != (struct SIG_hlist *) NULL)
164 (*this->handler)(sig);
172 * The following registers a signal handler. If the handler is already
173 * registered, it is not registered twice, nor is the order in which signal
174 * handlers are invoked changed. If this is the first signal handler
175 * registered for a given signal, the old sigvec structure is saved for
179 int SIG_register(sig,fn)
184 struct SIG_hlist *this;
186 struct sigaction act;
187 sigset_t sigset_mask, sigset_omask;
200 /* Block this signal while we look at handler chain */
202 (void) sigemptyset(&sigset_mask);
203 (void) sigaddset(&sigset_mask, sig);
204 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
207 mask = sigblock(sigmask(sig));
211 /* See if this handler was already registered */
212 this = SIG_handlers[sig];
213 while (this != (struct SIG_hlist *) NULL)
215 if (this->handler == fn) break;
219 /* Register the new handler only if it is not already registered. */
220 if (this == (struct SIG_hlist *) NULL)
224 * If this is the first handler registered for this signal,
225 * set up the signal handler dispatcher
228 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
231 act.sa_handler = SIG_handle;
232 (void) sigemptyset(&act.sa_mask);
234 val = sigaction(sig, &act, &SIG_defaults[sig]);
237 memset (&vec, 0, sizeof (vec));
238 vec.sv_handler = SIG_handle;
239 val = sigvec(sig, &vec, &SIG_defaults[sig]);
241 if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR)
247 /* If not, register it */
248 if ((val == 0) && (this == (struct SIG_hlist *) NULL))
250 this = (struct SIG_hlist *)
251 malloc(sizeof(struct SIG_hlist));
259 this->next = SIG_handlers[sig];
260 SIG_handlers[sig] = this;
265 /* Unblock the signal */
267 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
270 (void) sigsetmask(mask);
278 * The following deregisters a signal handler. If the last signal handler for
279 * a given signal is deregistered, the default sigvec information is restored.
282 int SIG_deregister(sig,fn)
287 struct SIG_hlist *this;
288 struct SIG_hlist *last;
290 sigset_t sigset_mask, sigset_omask;
301 last = (struct SIG_hlist *) NULL;
303 /* Block this signal while we look at handler chain */
305 (void) sigemptyset(&sigset_mask);
306 (void) sigaddset(&sigset_mask, sig);
307 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
310 mask = sigblock(sigmask(sig));
314 /* Search for the signal handler */
315 this = SIG_handlers[sig];
316 while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn))
322 /* If it was registered, remove it */
323 if (this != (struct SIG_hlist *) NULL)
325 if (last == (struct SIG_hlist *) NULL)
327 SIG_handlers[sig] = this->next;
331 last->next = this->next;
336 /* Restore default behavior if there are no registered handlers */
337 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
340 val = sigaction(sig, &SIG_defaults[sig],
341 (struct sigaction *) NULL);
344 val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
346 if (signal(sig, SIG_defaults[sig]) == SIG_ERR)
352 /* Unblock the signal */
354 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
357 (void) sigsetmask(mask);
365 * The following begins a critical section.
368 void SIG_beginCrSect()
372 if (SIG_crSectNest == 0)
375 sigset_t sigset_mask;
377 (void) sigfillset(&sigset_mask);
378 (void) sigprocmask(SIG_SETMASK,
379 &sigset_mask, &SIG_crSectMask);
382 SIG_crSectMask = sigblock(~0);
393 * The following ends a critical section.
401 if (SIG_crSectNest == 0)
404 (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL);
407 (void) sigsetmask(SIG_crSectMask);