1 | // RUN: %clangxx -std=c++11 -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s |
2 | |
3 | #include <assert.h> |
4 | #include <climits> |
5 | #include <errno.h> |
6 | #include <stdio.h> |
7 | #include <signal.h> |
8 | |
9 | #include <initializer_list> |
10 | |
11 | constexpr int std_signals[] = { |
12 | SIGHUP, |
13 | SIGINT, |
14 | SIGQUIT, |
15 | SIGILL, |
16 | SIGTRAP, |
17 | SIGABRT, |
18 | SIGIOT, |
19 | SIGBUS, |
20 | SIGFPE, |
21 | SIGUSR1, |
22 | SIGSEGV, |
23 | SIGUSR2, |
24 | SIGPIPE, |
25 | SIGALRM, |
26 | SIGTERM, |
27 | SIGCHLD, |
28 | SIGCONT, |
29 | SIGTSTP, |
30 | SIGTTIN, |
31 | SIGTTOU, |
32 | SIGURG, |
33 | SIGXCPU, |
34 | SIGXFSZ, |
35 | SIGVTALRM, |
36 | SIGPROF, |
37 | SIGWINCH, |
38 | SIGIO, |
39 | SIGSYS, |
40 | }; |
41 | |
42 | constexpr int no_change_act_signals[] = { |
43 | SIGKILL, |
44 | SIGSTOP, |
45 | }; |
46 | |
47 | void signal_handler(int) {} |
48 | void signal_action_handler(int, siginfo_t*, void*) {} |
49 | |
50 | void test_signal_custom() { |
51 | for (int signum : std_signals) { |
52 | auto* ret = signal(sig: signum, handler: &signal_handler); |
53 | assert(ret != SIG_ERR); |
54 | } |
55 | #ifdef SIGRTMIN |
56 | for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) { |
57 | auto* ret = signal(sig: signum, handler: &signal_handler); |
58 | assert(ret != SIG_ERR); |
59 | } |
60 | #endif |
61 | for (int signum : no_change_act_signals) { |
62 | auto* ret = signal(sig: signum, handler: &signal_handler); |
63 | int err = errno; |
64 | assert(ret == SIG_ERR); |
65 | assert(err == EINVAL); |
66 | } |
67 | for (int signum : { |
68 | 0, |
69 | #ifdef SIGRTMAX |
70 | SIGRTMAX + 1, |
71 | #endif |
72 | INT_MAX}) { |
73 | auto* ret = signal(sig: signum, handler: &signal_handler); |
74 | int err = errno; |
75 | assert(ret == SIG_ERR); |
76 | assert(err == EINVAL); |
77 | } |
78 | } |
79 | |
80 | void test_signal_ignore() { |
81 | for (int signum : std_signals) { |
82 | auto* ret = signal(sig: signum, SIG_IGN); |
83 | if (signum != SIGCHLD) { |
84 | // POSIX.1-1990 disallowed setting the action for SIGCHLD to SIG_IGN |
85 | // though POSIX.1-2001 and later allow this possibility. |
86 | assert(ret != SIG_ERR); |
87 | } |
88 | } |
89 | #ifdef SIGRTMIN |
90 | for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) { |
91 | auto* ret = signal(sig: signum, SIG_IGN); |
92 | assert(ret != SIG_ERR); |
93 | } |
94 | #endif |
95 | for (int signum : no_change_act_signals) { |
96 | auto* ret = signal(sig: signum, SIG_IGN); |
97 | int err = errno; |
98 | assert(ret == SIG_ERR); |
99 | assert(err == EINVAL); |
100 | } |
101 | for (int signum : { |
102 | 0, |
103 | #ifdef SIGRTMAX |
104 | SIGRTMAX + 1, |
105 | #endif |
106 | INT_MAX}) { |
107 | auto* ret = signal(sig: signum, SIG_IGN); |
108 | int err = errno; |
109 | assert(ret == SIG_ERR); |
110 | assert(err == EINVAL); |
111 | } |
112 | } |
113 | |
114 | void test_signal_default() { |
115 | for (int signum : std_signals) { |
116 | auto* ret = signal(sig: signum, SIG_DFL); |
117 | assert(ret != SIG_ERR); |
118 | } |
119 | #ifdef SIGRTMIN |
120 | for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) { |
121 | auto* ret = signal(sig: signum, SIG_DFL); |
122 | assert(ret != SIG_ERR); |
123 | } |
124 | #endif |
125 | for (int signum : { |
126 | 0, |
127 | #ifdef SIGRTMAX |
128 | SIGRTMAX + 1, |
129 | #endif |
130 | INT_MAX}) { |
131 | auto* ret = signal(sig: signum, SIG_DFL); |
132 | int err = errno; |
133 | assert(ret == SIG_ERR); |
134 | assert(err == EINVAL); |
135 | } |
136 | } |
137 | |
138 | void test_sigaction_custom() { |
139 | struct sigaction act = {}, oldact; |
140 | |
141 | act.sa_handler = &signal_handler; |
142 | sigemptyset(set: &act.sa_mask); |
143 | act.sa_flags = 0; |
144 | |
145 | for (int signum : std_signals) { |
146 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
147 | assert(ret == 0); |
148 | } |
149 | #ifdef SIGRTMIN |
150 | for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) { |
151 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
152 | assert(ret == 0); |
153 | } |
154 | #endif |
155 | for (int signum : no_change_act_signals) { |
156 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
157 | int err = errno; |
158 | assert(ret == -1); |
159 | assert(err == EINVAL); |
160 | } |
161 | for (int signum : { |
162 | 0, |
163 | #ifdef SIGRTMAX |
164 | SIGRTMAX + 1, |
165 | #endif |
166 | INT_MAX}) { |
167 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
168 | int err = errno; |
169 | assert(ret == -1); |
170 | assert(err == EINVAL); |
171 | } |
172 | |
173 | act.sa_handler = nullptr; |
174 | act.sa_sigaction = &signal_action_handler; |
175 | act.sa_flags = SA_SIGINFO; |
176 | |
177 | for (int signum : std_signals) { |
178 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
179 | assert(ret == 0); |
180 | } |
181 | #ifdef SIGRTMIN |
182 | for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) { |
183 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
184 | assert(ret == 0); |
185 | } |
186 | #endif |
187 | for (int signum : no_change_act_signals) { |
188 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
189 | int err = errno; |
190 | assert(ret == -1); |
191 | assert(err == EINVAL); |
192 | } |
193 | for (int signum : { |
194 | 0, |
195 | #ifdef SIGRTMAX |
196 | SIGRTMAX + 1, |
197 | #endif |
198 | INT_MAX}) { |
199 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
200 | int err = errno; |
201 | assert(ret == -1); |
202 | assert(err == EINVAL); |
203 | } |
204 | } |
205 | |
206 | void test_sigaction_ignore() { |
207 | struct sigaction act = {}, oldact; |
208 | |
209 | act.sa_handler = SIG_IGN; |
210 | sigemptyset(set: &act.sa_mask); |
211 | act.sa_flags = 0; |
212 | |
213 | for (int signum : std_signals) { |
214 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
215 | if (signum != SIGCHLD) { |
216 | // POSIX.1-1990 disallowed setting the action for SIGCHLD to SIG_IGN |
217 | // though POSIX.1-2001 and later allow this possibility. |
218 | assert(ret == 0); |
219 | } |
220 | } |
221 | #ifdef SIGRTMIN |
222 | for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) { |
223 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
224 | assert(ret == 0); |
225 | } |
226 | #endif |
227 | for (int signum : no_change_act_signals) { |
228 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
229 | int err = errno; |
230 | assert(ret == -1); |
231 | assert(err == EINVAL); |
232 | } |
233 | for (int signum : { |
234 | 0, |
235 | #ifdef SIGRTMAX |
236 | SIGRTMAX + 1, |
237 | #endif |
238 | INT_MAX}) { |
239 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
240 | int err = errno; |
241 | assert(ret == -1); |
242 | assert(err == EINVAL); |
243 | } |
244 | } |
245 | |
246 | void test_sigaction_default() { |
247 | struct sigaction act = {}, oldact; |
248 | |
249 | act.sa_handler = SIG_DFL; |
250 | sigemptyset(set: &act.sa_mask); |
251 | act.sa_flags = 0; |
252 | |
253 | for (int signum : std_signals) { |
254 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
255 | assert(ret == 0); |
256 | } |
257 | #ifdef SIGRTMIN |
258 | for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) { |
259 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
260 | assert(ret == 0); |
261 | } |
262 | #endif |
263 | for (int signum : { |
264 | 0, |
265 | #ifdef SIGRTMAX |
266 | SIGRTMAX + 1, |
267 | #endif |
268 | INT_MAX}) { |
269 | int ret = sigaction(sig: signum, act: &act, oact: &oldact); |
270 | int err = errno; |
271 | assert(ret == -1); |
272 | assert(err == EINVAL); |
273 | } |
274 | } |
275 | |
276 | int main(void) { |
277 | printf(format: "sigaction\n" ); |
278 | |
279 | test_signal_custom(); |
280 | test_signal_ignore(); |
281 | test_signal_default(); |
282 | |
283 | test_sigaction_custom(); |
284 | test_sigaction_ignore(); |
285 | test_sigaction_default(); |
286 | |
287 | // CHECK: sigaction |
288 | |
289 | return 0; |
290 | } |
291 | |