1 /* POSIX compatible signal blocking.
2 Copyright (C) 2006-2007 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
27 /* We assume that a platform without POSIX signal blocking functions also
28 does not have the POSIX sigaction() function, only the signal() function.
29 This is true for Woe32 platforms. */
31 /* A signal handler. */
32 typedef void (*handler_t) (int signal);
35 sigismember (const sigset_t *set, int sig)
37 if (sig >= 0 && sig < NSIG)
38 return (*set >> sig) & 1;
44 sigemptyset (sigset_t *set)
51 sigaddset (sigset_t *set, int sig)
53 if (sig >= 0 && sig < NSIG)
66 sigdelset (sigset_t *set, int sig)
68 if (sig >= 0 && sig < NSIG)
81 sigfillset (sigset_t *set)
83 *set = (2U << (NSIG - 1)) - 1;
87 /* Set of currently blocked signals. */
88 static sigset_t blocked_set /* = 0 */;
90 /* Set of currently blocked and pending signals. */
91 static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */;
93 /* Signal handler that is installed for blocked signals. */
95 blocked_handler (int sig)
97 if (sig >= 0 && sig < NSIG)
98 pending_array[sig] = 1;
102 sigpending (sigset_t *set)
104 sigset_t pending = 0;
107 for (sig = 0; sig < NSIG; sig++)
108 if (pending_array[sig])
109 pending |= 1U << sig;
113 /* The previous signal handlers.
114 Only the array elements corresponding to blocked signals are relevant. */
115 static handler_t old_handlers[NSIG];
118 sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
121 *old_set = blocked_set;
125 sigset_t new_blocked_set;
132 new_blocked_set = blocked_set | *set;
135 new_blocked_set = *set;
138 new_blocked_set = blocked_set & ~*set;
144 to_unblock = blocked_set & ~new_blocked_set;
145 to_block = new_blocked_set & ~blocked_set;
151 for (sig = 0; sig < NSIG; sig++)
152 if ((to_block >> sig) & 1)
154 pending_array[sig] = 0;
155 if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR)
156 blocked_set |= 1U << sig;
162 sig_atomic_t received[NSIG];
165 for (sig = 0; sig < NSIG; sig++)
166 if ((to_unblock >> sig) & 1)
168 if (signal (sig, old_handlers[sig]) != blocked_handler)
169 /* The application changed a signal handler while the signal
170 was blocked. We don't support this. */
172 received[sig] = pending_array[sig];
173 blocked_set &= ~(1U << sig);
174 pending_array[sig] = 0;
179 for (sig = 0; sig < NSIG; sig++)
185 kill (getpid (), sig);