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