Mercurial > hg > octave-kai > gnulib-hg
annotate lib/sigprocmask.c @ 9084:2932e92d6e31
* lib/version-etc.c (version_etc_va): Default to GPLv3+.
* NEWS: Document this change.
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Tue, 10 Jul 2007 12:22:36 +0000 |
parents | bb4e89fdfa87 |
children | bbbbbf4cd1c5 |
rev | line source |
---|---|
7503 | 1 /* POSIX compatible signal blocking. |
8783
bb4e89fdfa87
sigprocmask.h is replaced with <signal.h>.
Bruno Haible <bruno@clisp.org>
parents:
7517
diff
changeset
|
2 Copyright (C) 2006-2007 Free Software Foundation, Inc. |
7503 | 3 Written by Bruno Haible <bruno@clisp.org>, 2006. |
4 | |
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 2, or (at your option) | |
8 any later version. | |
9 | |
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. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program; if not, write to the Free Software Foundation, | |
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | |
18 | |
19 #include <config.h> | |
20 | |
21 /* Specification. */ | |
8783
bb4e89fdfa87
sigprocmask.h is replaced with <signal.h>.
Bruno Haible <bruno@clisp.org>
parents:
7517
diff
changeset
|
22 #include <signal.h> |
7503 | 23 |
24 #include <errno.h> | |
25 #include <stdint.h> | |
26 #include <stdlib.h> | |
27 | |
28 /* We assume that a platform without POSIX signal blocking functions also | |
29 does not have the POSIX sigaction() function, only the signal() function. | |
30 This is true for Woe32 platforms. */ | |
31 | |
32 /* A signal handler. */ | |
33 typedef void (*handler_t) (int signal); | |
34 | |
35 int | |
36 sigismember (const sigset_t *set, int sig) | |
37 { | |
38 if (sig >= 0 && sig < NSIG) | |
39 return (*set >> sig) & 1; | |
40 else | |
41 return 0; | |
42 } | |
43 | |
44 int | |
45 sigemptyset (sigset_t *set) | |
46 { | |
47 *set = 0; | |
48 return 0; | |
49 } | |
50 | |
51 int | |
52 sigaddset (sigset_t *set, int sig) | |
53 { | |
54 if (sig >= 0 && sig < NSIG) | |
55 { | |
56 *set |= 1U << sig; | |
57 return 0; | |
58 } | |
59 else | |
60 { | |
61 errno = EINVAL; | |
62 return -1; | |
63 } | |
64 } | |
65 | |
66 int | |
67 sigdelset (sigset_t *set, int sig) | |
68 { | |
69 if (sig >= 0 && sig < NSIG) | |
70 { | |
71 *set &= ~(1U << sig); | |
72 return 0; | |
73 } | |
74 else | |
75 { | |
76 errno = EINVAL; | |
77 return -1; | |
78 } | |
79 } | |
80 | |
81 int | |
82 sigfillset (sigset_t *set) | |
83 { | |
84 *set = (2U << (NSIG - 1)) - 1; | |
85 return 0; | |
86 } | |
87 | |
88 /* Set of currently blocked signals. */ | |
89 static sigset_t blocked_set /* = 0 */; | |
90 | |
91 /* Set of currently blocked and pending signals. */ | |
92 static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */; | |
93 | |
94 /* Signal handler that is installed for blocked signals. */ | |
95 static void | |
96 blocked_handler (int sig) | |
97 { | |
98 if (sig >= 0 && sig < NSIG) | |
99 pending_array[sig] = 1; | |
100 } | |
101 | |
102 int | |
103 sigpending (sigset_t *set) | |
104 { | |
105 sigset_t pending = 0; | |
106 int sig; | |
107 | |
108 for (sig = 0; sig < NSIG; sig++) | |
109 if (pending_array[sig]) | |
110 pending |= 1U << sig; | |
111 return pending; | |
112 } | |
113 | |
114 /* The previous signal handlers. | |
115 Only the array elements corresponding to blocked signals are relevant. */ | |
116 static handler_t old_handlers[NSIG]; | |
117 | |
118 int | |
119 sigprocmask (int operation, const sigset_t *set, sigset_t *old_set) | |
120 { | |
121 if (old_set != NULL) | |
122 *old_set = blocked_set; | |
123 | |
124 if (set != NULL) | |
125 { | |
126 sigset_t new_blocked_set; | |
127 sigset_t to_unblock; | |
128 sigset_t to_block; | |
129 | |
130 switch (operation) | |
131 { | |
132 case SIG_BLOCK: | |
133 new_blocked_set = blocked_set | *set; | |
134 break; | |
135 case SIG_SETMASK: | |
136 new_blocked_set = *set; | |
137 break; | |
138 case SIG_UNBLOCK: | |
139 new_blocked_set = blocked_set & ~*set; | |
140 break; | |
141 default: | |
142 errno = EINVAL; | |
143 return -1; | |
144 } | |
145 to_unblock = blocked_set & ~new_blocked_set; | |
146 to_block = new_blocked_set & ~blocked_set; | |
147 | |
148 if (to_block != 0) | |
149 { | |
150 int sig; | |
151 | |
152 for (sig = 0; sig < NSIG; sig++) | |
153 if ((to_block >> sig) & 1) | |
154 { | |
155 pending_array[sig] = 0; | |
156 if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR) | |
157 blocked_set |= 1U << sig; | |
158 } | |
159 } | |
160 | |
161 if (to_unblock != 0) | |
162 { | |
163 sig_atomic_t received[NSIG]; | |
164 int sig; | |
165 | |
166 for (sig = 0; sig < NSIG; sig++) | |
167 if ((to_unblock >> sig) & 1) | |
168 { | |
169 if (signal (sig, old_handlers[sig]) != blocked_handler) | |
170 /* The application changed a signal handler while the signal | |
171 was blocked. We don't support this. */ | |
172 abort (); | |
173 received[sig] = pending_array[sig]; | |
174 blocked_set &= ~(1U << sig); | |
175 pending_array[sig] = 0; | |
176 } | |
177 else | |
178 received[sig] = 0; | |
179 | |
180 for (sig = 0; sig < NSIG; sig++) | |
7517
55b0b8000058
* lib/sigprocmask.c (sigprocmask): Fix typo.
Eric Blake <ebb9@byu.net>
parents:
7503
diff
changeset
|
181 if (received[sig]) |
7503 | 182 { |
183 #if HAVE_RAISE | |
184 raise (sig); | |
185 #else | |
186 kill (getpid (), sig); | |
187 #endif | |
188 } | |
189 } | |
190 } | |
191 return 0; | |
192 } |