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 
signal_handler(int)47 void signal_handler(int) {}
signal_action_handler(int,siginfo_t *,void *)48 void signal_action_handler(int, siginfo_t*, void*) {}
49 
test_signal_custom()50 void test_signal_custom() {
51   for (int signum : std_signals) {
52     auto* ret = signal(signum, &signal_handler);
53     assert(ret != SIG_ERR);
54   }
55 #ifdef SIGRTMIN
56   for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) {
57     auto* ret = signal(signum, &signal_handler);
58     assert(ret != SIG_ERR);
59   }
60 #endif
61   for (int signum : no_change_act_signals) {
62     auto* ret = signal(signum, &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(signum, &signal_handler);
74     int err = errno;
75     assert(ret == SIG_ERR);
76     assert(err == EINVAL);
77   }
78 }
79 
test_signal_ignore()80 void test_signal_ignore() {
81   for (int signum : std_signals) {
82     auto* ret = signal(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(signum, SIG_IGN);
92     assert(ret != SIG_ERR);
93   }
94 #endif
95   for (int signum : no_change_act_signals) {
96     auto* ret = signal(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(signum, SIG_IGN);
108     int err = errno;
109     assert(ret == SIG_ERR);
110     assert(err == EINVAL);
111   }
112 }
113 
test_signal_default()114 void test_signal_default() {
115   for (int signum : std_signals) {
116     auto* ret = signal(signum, SIG_DFL);
117     assert(ret != SIG_ERR);
118   }
119 #ifdef SIGRTMIN
120   for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) {
121     auto* ret = signal(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(signum, SIG_DFL);
132     int err = errno;
133     assert(ret == SIG_ERR);
134     assert(err == EINVAL);
135   }
136 }
137 
test_sigaction_custom()138 void test_sigaction_custom() {
139   struct sigaction act = {}, oldact;
140 
141   act.sa_handler = &signal_handler;
142   sigemptyset(&act.sa_mask);
143   act.sa_flags = 0;
144 
145   for (int signum : std_signals) {
146     int ret = sigaction(signum, &act, &oldact);
147     assert(ret == 0);
148   }
149 #ifdef SIGRTMIN
150   for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) {
151     int ret = sigaction(signum, &act, &oldact);
152     assert(ret == 0);
153   }
154 #endif
155   for (int signum : no_change_act_signals) {
156     int ret = sigaction(signum, &act, &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(signum, &act, &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(signum, &act, &oldact);
179     assert(ret == 0);
180   }
181 #ifdef SIGRTMIN
182   for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) {
183     int ret = sigaction(signum, &act, &oldact);
184     assert(ret == 0);
185   }
186 #endif
187   for (int signum : no_change_act_signals) {
188     int ret = sigaction(signum, &act, &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(signum, &act, &oldact);
200     int err = errno;
201     assert(ret == -1);
202     assert(err == EINVAL);
203   }
204 }
205 
test_sigaction_ignore()206 void test_sigaction_ignore() {
207   struct sigaction act = {}, oldact;
208 
209   act.sa_handler = SIG_IGN;
210   sigemptyset(&act.sa_mask);
211   act.sa_flags = 0;
212 
213   for (int signum : std_signals) {
214     int ret = sigaction(signum, &act, &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(signum, &act, &oldact);
224     assert(ret == 0);
225   }
226 #endif
227   for (int signum : no_change_act_signals) {
228     int ret = sigaction(signum, &act, &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(signum, &act, &oldact);
240     int err = errno;
241     assert(ret == -1);
242     assert(err == EINVAL);
243   }
244 }
245 
test_sigaction_default()246 void test_sigaction_default() {
247   struct sigaction act = {}, oldact;
248 
249   act.sa_handler = SIG_DFL;
250   sigemptyset(&act.sa_mask);
251   act.sa_flags = 0;
252 
253   for (int signum : std_signals) {
254     int ret = sigaction(signum, &act, &oldact);
255     assert(ret == 0);
256   }
257 #ifdef SIGRTMIN
258   for (int signum = SIGRTMIN; signum <= SIGRTMAX; ++signum) {
259     int ret = sigaction(signum, &act, &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(signum, &act, &oldact);
270     int err = errno;
271     assert(ret == -1);
272     assert(err == EINVAL);
273   }
274 }
275 
main(void)276 int main(void) {
277   printf("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