raise_default_signal.c revision 1.1 1 /* $NetBSD: raise_default_signal.c,v 1.1 2007/09/25 01:13:56 lukem Exp $ */
2
3 /*-
4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Luke Mewburn.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #if defined(LIBC_SCCS) && !defined(lint)
41 __RCSID("$NetBSD: raise_default_signal.c,v 1.1 2007/09/25 01:13:56 lukem Exp $");
42 #endif
43
44 #include <errno.h>
45 #include <signal.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <util.h>
49
50 /*
51 * raise_default_signal sig
52 * Raise the default signal handler for sig, by
53 * - block all signals
54 * - set the signal handler to SIG_DFL
55 * - raise the signal
56 * - unblock the signal to deliver it
57 *
58 * The original signal mask and signal handler is restored on exit
59 * (whether successful or not).
60 *
61 * Returns 0 on success, or -1 on failure with errno set to
62 * on of the values for sigemptyset(), sigaddset(), sigprocmask(),
63 * sigaction(), or raise().
64 */
65 int
66 raise_default_signal(int sig)
67 {
68 struct sigaction origact, act;
69 sigset_t origmask, fullmask, mask;
70 int retval, oerrno;
71
72 retval = -1;
73
74 /* Setup data structures */
75 /* XXX memset(3) isn't async-safe according to signal(7) */
76 (void)memset(&act, 0, sizeof(act));
77 act.sa_handler = SIG_DFL;
78 act.sa_flags = 0;
79 if ((sigemptyset(&act.sa_mask) == -1) ||
80 (sigfillset(&fullmask) == -1) ||
81 (sigemptyset(&mask) == -1) ||
82 (sigaddset(&mask, sig) == -1))
83 goto restore_none;
84
85 /* Block all signals */
86 if (sigprocmask(SIG_BLOCK, &fullmask, &origmask) == -1)
87 goto restore_none;
88 /* (use 'goto restore_mask' to restore state) */
89
90 /* Enable the SIG_DFL handler */
91 if (sigaction(sig, &act, &origact) == -1)
92 goto restore_mask;
93 /* (use 'goto restore_act' to restore state) */
94
95 /* Raise the signal, and unblock the signal to deliver it */
96 if ((raise(sig) == -1) ||
97 (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1))
98 goto restore_act;
99
100 /* Flag successful raise() */
101 retval = 0;
102
103 /* Restore the original handler */
104 restore_act:
105 oerrno = errno;
106 (void)sigaction(sig, &origact, NULL);
107 errno = oerrno;
108
109 /* Restore the original mask */
110 restore_mask:
111 oerrno = errno;
112 (void)sigprocmask(SIG_SETMASK, &origmask, NULL);
113 errno = oerrno;
114
115 restore_none:
116 return retval;
117 }
118