Home | History | Annotate | Line # | Download | only in lib
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