sighandle.c revision 1.1.1.1.2.2 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 (at) hal.com>
15 Brian Berliner <berliner (at) 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 /*
92 * Initialize the signal handler arrays
93 */
94
95 static int SIG_init()
96 {
97 int i;
98 #ifdef POSIX_SIGNALS
99 sigset_t sigset_test;
100 #endif
101
102 if (SIG_defaults && SIG_handlers) /* already allocated */
103 return (0);
104
105 #ifdef POSIX_SIGNALS
106 (void) sigfillset(&sigset_test);
107 for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++)
108 ;
109 if (i < SIGMAX)
110 i = SIGMAX;
111 i++;
112 if (!SIG_defaults)
113 SIG_defaults = (struct sigaction *)
114 calloc(i, sizeof(struct sigaction));
115 (void) sigemptyset(&SIG_crSectMask);
116 #else
117 i = SIGMAX+1;
118 #ifdef BSD_SIGNALS
119 if (!SIG_defaults)
120 SIG_defaults = (struct sigvec *)
121 calloc(i, sizeof(struct sigvec));
122 #else
123 if (!SIG_defaults)
124 SIG_defaults = ( RETSIGTYPE (**) (int) )
125 calloc( i, sizeof( RETSIGTYPE (**) (int) ) );
126 #endif
127 SIG_crSectMask = 0;
128 #endif
129 if (!SIG_handlers)
130 SIG_handlers = (struct SIG_hlist **)
131 calloc(i, sizeof(struct SIG_hlist *));
132 return (!SIG_defaults || !SIG_handlers);
133 }
134
135
136
137 /*
138 * The following begins a critical section.
139 */
140 void SIG_beginCrSect (void)
141 {
142 if (SIG_init() == 0)
143 {
144 if (SIG_crSectNest == 0)
145 {
146 #ifdef POSIX_SIGNALS
147 sigset_t sigset_mask;
148
149 (void) sigfillset(&sigset_mask);
150 (void) sigprocmask(SIG_SETMASK,
151 &sigset_mask, &SIG_crSectMask);
152 #else
153 #ifdef BSD_SIGNALS
154 SIG_crSectMask = sigblock(~0);
155 #else
156 /* TBD */
157 #endif
158 #endif
159 }
160 SIG_crSectNest++;
161 }
162 }
163
164
165
166 /*
167 * The following ends a critical section.
168 */
169 void SIG_endCrSect (void)
170 {
171 if (SIG_init() == 0)
172 {
173 SIG_crSectNest--;
174 if (SIG_crSectNest == 0)
175 {
176 #ifdef POSIX_SIGNALS
177 (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL);
178 #else
179 #ifdef BSD_SIGNALS
180 (void) sigsetmask(SIG_crSectMask);
181 #else
182 /* TBD */
183 #endif
184 #endif
185 }
186 }
187 }
188
189
190
191 /*
192 * The following invokes each signal handler in the reverse order in which
193 * they were registered.
194 */
195 static RETSIGTYPE SIG_handle (int sig)
196 {
197 struct SIG_hlist *this;
198
199 /* Dispatch signal handlers */
200 /* This crit section stuff is a CVSism - we know that our interrupt
201 * handlers will always end up exiting and we don't want them to be
202 * interrupted themselves.
203 */
204 SIG_beginCrSect();
205 this = SIG_handlers[sig];
206 while (this != (struct SIG_hlist *) NULL)
207 {
208 (*this->handler)(sig);
209 this = this->next;
210 }
211 SIG_endCrSect();
212
213 return;
214 }
215
216 /*
218 * The following registers a signal handler. If the handler is already
219 * registered, it is not registered twice, nor is the order in which signal
220 * handlers are invoked changed. If this is the first signal handler
221 * registered for a given signal, the old sigvec structure is saved for
222 * restoration later.
223 */
224
225 int SIG_register(int sig, RETSIGTYPE (*fn)())
226 {
227 int val;
228 struct SIG_hlist *this;
229 #ifdef POSIX_SIGNALS
230 struct sigaction act;
231 sigset_t sigset_mask, sigset_omask;
232 #else
233 #ifdef BSD_SIGNALS
234 struct sigvec vec;
235 int mask;
236 #endif
237 #endif
238
239 /* Initialize */
240 if (SIG_init() != 0)
241 return (-1);
242 val = 0;
243
244 /* Block this signal while we look at handler chain */
245 #ifdef POSIX_SIGNALS
246 (void) sigemptyset(&sigset_mask);
247 (void) sigaddset(&sigset_mask, sig);
248 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
249 #else
250 #ifdef BSD_SIGNALS
251 mask = sigblock(sigmask(sig));
252 #endif
253 #endif
254
255 /* See if this handler was already registered */
256 this = SIG_handlers[sig];
257 while (this != (struct SIG_hlist *) NULL)
258 {
259 if (this->handler == fn) break;
260 this = this->next;
261 }
262
263 /* Register the new handler only if it is not already registered. */
264 if (this == (struct SIG_hlist *) NULL)
265 {
266
267 /*
268 * If this is the first handler registered for this signal,
269 * set up the signal handler dispatcher
270 */
271
272 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
273 {
274 #ifdef POSIX_SIGNALS
275 act.sa_handler = SIG_handle;
276 (void) sigemptyset(&act.sa_mask);
277 act.sa_flags = 0;
278 val = sigaction(sig, &act, &SIG_defaults[sig]);
279 #else
280 #ifdef BSD_SIGNALS
281 memset (&vec, 0, sizeof (vec));
282 vec.sv_handler = SIG_handle;
283 val = sigvec(sig, &vec, &SIG_defaults[sig]);
284 #else
285 if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR)
286 val = -1;
287 #endif
288 #endif
289 }
290
291 /* If not, register it */
292 if ((val == 0) && (this == (struct SIG_hlist *) NULL))
293 {
294 this = (struct SIG_hlist *)
295 malloc(sizeof(struct SIG_hlist));
296 if (this == NULL)
297 {
298 val = -1;
299 }
300 else
301 {
302 this->handler = fn;
303 this->next = SIG_handlers[sig];
304 SIG_handlers[sig] = this;
305 }
306 }
307 }
308
309 /* Unblock the signal */
310 #ifdef POSIX_SIGNALS
311 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
312 #else
313 #ifdef BSD_SIGNALS
314 (void) sigsetmask(mask);
315 #endif
316 #endif
317
318 return val;
319 }
320
321
322
323 /*
324 * The following deregisters a signal handler. If the last signal handler for
325 * a given signal is deregistered, the default sigvec information is restored.
326 */
327
328 int SIG_deregister(int sig, RETSIGTYPE (*fn)())
329 {
330 int val;
331 struct SIG_hlist *this;
332 struct SIG_hlist *last;
333 #ifdef POSIX_SIGNALS
334 sigset_t sigset_mask, sigset_omask;
335 #else
336 #ifdef BSD_SIGNALS
337 int mask;
338 #endif
339 #endif
340
341 /* Initialize */
342 if (SIG_init() != 0)
343 return (-1);
344 val = 0;
345 last = (struct SIG_hlist *) NULL;
346
347 /* Block this signal while we look at handler chain */
348 #ifdef POSIX_SIGNALS
349 (void) sigemptyset(&sigset_mask);
350 (void) sigaddset(&sigset_mask, sig);
351 (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
352 #else
353 #ifdef BSD_SIGNALS
354 mask = sigblock(sigmask(sig));
355 #endif
356 #endif
357
358 /* Search for the signal handler */
359 this = SIG_handlers[sig];
360 while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn))
361 {
362 last = this;
363 this = this->next;
364 }
365
366 /* If it was registered, remove it */
367 if (this != (struct SIG_hlist *) NULL)
368 {
369 if (last == (struct SIG_hlist *) NULL)
370 {
371 SIG_handlers[sig] = this->next;
372 }
373 else
374 {
375 last->next = this->next;
376 }
377 free((char *) this);
378 }
379
380 /* Restore default behavior if there are no registered handlers */
381 if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
382 {
383 #ifdef POSIX_SIGNALS
384 val = sigaction(sig, &SIG_defaults[sig],
385 (struct sigaction *) NULL);
386 #else
387 #ifdef BSD_SIGNALS
388 val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
389 #else
390 if (signal(sig, SIG_defaults[sig]) == SIG_ERR)
391 val = -1;
392 #endif
393 #endif
394 }
395
396 /* Unblock the signal */
397 #ifdef POSIX_SIGNALS
398 (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
399 #else
400 #ifdef BSD_SIGNALS
401 (void) sigsetmask(mask);
402 #endif
403 #endif
404
405 return val;
406 }
407
408
409
410 /*
411 * Return nonzero if currently in a critical section.
412 * Otherwise return zero.
413 */
414
415 int SIG_inCrSect (void)
416 {
417 return SIG_crSectNest > 0;
418 }
419