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>
44 char *calloc(unsigned nelem
, unsigned size
);
45 char *malloc(unsigned size
);
50 #endif /* STDC_HEADERS */
52 /* Define the highest signal number (usually) */
57 /* Define linked list of signal handlers structure */
59 RETSIGTYPE (*handler
)();
60 struct SIG_hlist
*next
;
64 * Define array of lists of signal handlers. Note that this depends on
65 * the implementation to initialize each element to a null pointer.
68 static struct SIG_hlist
**SIG_handlers
;
70 /* Define array of default signal vectors */
73 static struct sigaction
*SIG_defaults
;
76 static struct sigvec
*SIG_defaults
;
78 static RETSIGTYPE (**SIG_defaults
) (int);
82 /* Critical section housekeeping */
83 static int SIG_crSectNest
= 0; /* Nesting level */
85 static sigset_t SIG_crSectMask
; /* Signal mask */
87 static int SIG_crSectMask
; /* Signal mask */
91 * Initialize the signal handler arrays
101 if (SIG_defaults
&& SIG_handlers
) /* already allocated */
105 (void) sigfillset(&sigset_test
);
106 for (i
= 1; i
< SIGMAX
&& sigismember(&sigset_test
, i
) == 1; i
++)
112 SIG_defaults
= (struct sigaction
*)
113 calloc(i
, sizeof(struct sigaction
));
114 (void) sigemptyset(&SIG_crSectMask
);
119 SIG_defaults
= (struct sigvec
*)
120 calloc(i
, sizeof(struct sigvec
));
123 SIG_defaults
= ( RETSIGTYPE (**) (int) )
124 calloc( i
, sizeof( RETSIGTYPE (**) (int) ) );
129 SIG_handlers
= (struct SIG_hlist
**)
130 calloc(i
, sizeof(struct SIG_hlist
*));
131 return (!SIG_defaults
|| !SIG_handlers
);
137 * The following begins a critical section.
139 void SIG_beginCrSect (void)
143 if (SIG_crSectNest
== 0)
146 sigset_t sigset_mask
;
148 (void) sigfillset(&sigset_mask
);
149 (void) sigprocmask(SIG_SETMASK
,
150 &sigset_mask
, &SIG_crSectMask
);
153 SIG_crSectMask
= sigblock(~0);
166 * The following ends a critical section.
168 void SIG_endCrSect (void)
173 if (SIG_crSectNest
== 0)
176 (void) sigprocmask(SIG_SETMASK
, &SIG_crSectMask
, NULL
);
179 (void) sigsetmask(SIG_crSectMask
);
191 * The following invokes each signal handler in the reverse order in which
192 * they were registered.
194 static RETSIGTYPE
SIG_handle (int sig
)
196 struct SIG_hlist
*this;
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.
204 this = SIG_handlers
[sig
];
205 while (this != (struct SIG_hlist
*) NULL
)
207 (*this->handler
)(sig
);
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
223 int SIG_register(int sig
, RETSIGTYPE (*fn
)())
226 struct SIG_hlist
*this;
228 struct sigaction act
;
229 sigset_t sigset_mask
, sigset_omask
;
242 /* Block this signal while we look at handler chain */
244 (void) sigemptyset(&sigset_mask
);
245 (void) sigaddset(&sigset_mask
, sig
);
246 (void) sigprocmask(SIG_BLOCK
, &sigset_mask
, &sigset_omask
);
249 mask
= sigblock(sigmask(sig
));
253 /* See if this handler was already registered */
254 this = SIG_handlers
[sig
];
255 while (this != (struct SIG_hlist
*) NULL
)
257 if (this->handler
== fn
) break;
261 /* Register the new handler only if it is not already registered. */
262 if (this == (struct SIG_hlist
*) NULL
)
266 * If this is the first handler registered for this signal,
267 * set up the signal handler dispatcher
270 if (SIG_handlers
[sig
] == (struct SIG_hlist
*) NULL
)
273 act
.sa_handler
= SIG_handle
;
274 (void) sigemptyset(&act
.sa_mask
);
276 val
= sigaction(sig
, &act
, &SIG_defaults
[sig
]);
279 memset (&vec
, 0, sizeof (vec
));
280 vec
.sv_handler
= SIG_handle
;
281 val
= sigvec(sig
, &vec
, &SIG_defaults
[sig
]);
283 if ((SIG_defaults
[sig
] = signal(sig
, SIG_handle
)) == SIG_ERR
)
289 /* If not, register it */
290 if ((val
== 0) && (this == (struct SIG_hlist
*) NULL
))
292 this = (struct SIG_hlist
*)
293 malloc(sizeof(struct SIG_hlist
));
301 this->next
= SIG_handlers
[sig
];
302 SIG_handlers
[sig
] = this;
307 /* Unblock the signal */
309 (void) sigprocmask(SIG_SETMASK
, &sigset_omask
, NULL
);
312 (void) sigsetmask(mask
);
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.
326 int SIG_deregister(int sig
, RETSIGTYPE (*fn
)())
329 struct SIG_hlist
*this;
330 struct SIG_hlist
*last
;
332 sigset_t sigset_mask
, sigset_omask
;
343 last
= (struct SIG_hlist
*) NULL
;
345 /* Block this signal while we look at handler chain */
347 (void) sigemptyset(&sigset_mask
);
348 (void) sigaddset(&sigset_mask
, sig
);
349 (void) sigprocmask(SIG_BLOCK
, &sigset_mask
, &sigset_omask
);
352 mask
= sigblock(sigmask(sig
));
356 /* Search for the signal handler */
357 this = SIG_handlers
[sig
];
358 while ((this != (struct SIG_hlist
*) NULL
) && (this->handler
!= fn
))
364 /* If it was registered, remove it */
365 if (this != (struct SIG_hlist
*) NULL
)
367 if (last
== (struct SIG_hlist
*) NULL
)
369 SIG_handlers
[sig
] = this->next
;
373 last
->next
= this->next
;
378 /* Restore default behavior if there are no registered handlers */
379 if (SIG_handlers
[sig
] == (struct SIG_hlist
*) NULL
)
382 val
= sigaction(sig
, &SIG_defaults
[sig
],
383 (struct sigaction
*) NULL
);
386 val
= sigvec(sig
, &SIG_defaults
[sig
], (struct sigvec
*) NULL
);
388 if (signal(sig
, SIG_defaults
[sig
]) == SIG_ERR
)
394 /* Unblock the signal */
396 (void) sigprocmask(SIG_SETMASK
, &sigset_omask
, NULL
);
399 (void) sigsetmask(mask
);
409 * Return nonzero if currently in a critical section.
410 * Otherwise return zero.
413 int SIG_inCrSect (void)
415 return SIG_crSectNest
> 0;