blob: 769b71b2228c6c634c69cb8c18f5e83bcf5bf78f [file] [log] [blame]
mostang.com!davidm824d6612003-02-08 10:10:59 +00001/* libunwind - a platform-independent unwind library
2 Copyright (C) 2003 Hewlett-Packard Co
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5Permission is hereby granted, free of charge, to any person obtaining
6a copy of this software and associated documentation files (the
7"Software"), to deal in the Software without restriction, including
8without limitation the rights to use, copy, modify, merge, publish,
9distribute, sublicense, and/or sell copies of the Software, and to
10permit persons to whom the Software is furnished to do so, subject to
11the following conditions:
12
13The above copyright notice and this permission notice shall be
14included in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
24/* The setjmp()/longjmp(), sigsetjmp()/siglongjmp(). */
25
Tommi Rantala6b55e0a2012-09-19 13:50:59 +030026#include "compiler.h"
27
mostang.com!davidm824d6612003-02-08 10:10:59 +000028#include <setjmp.h>
29#include <signal.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34
35int nerrors;
36int verbose;
37
38static jmp_buf jbuf;
39static sigjmp_buf sigjbuf;
40static sigset_t sigset4;
41
42void
43raise_longjmp (jmp_buf jbuf, int i, int n)
44{
45 while (i < n)
46 raise_longjmp (jbuf, i + 1, n);
47
48 longjmp (jbuf, n);
49}
50
51void
52test_setjmp (void)
53{
54 volatile int i;
55 jmp_buf jbuf;
56 int ret;
57
58 for (i = 0; i < 10; ++i)
59 {
60 if ((ret = setjmp (jbuf)))
61 {
62 if (verbose)
63 printf ("%s: secondary setjmp () return, ret=%d\n",
64 __FUNCTION__, ret);
65 if (ret != i + 1)
66 {
67 fprintf (stderr, "%s: setjmp() returned %d, expected %d\n",
68 __FUNCTION__, ret, i + 1);
69 ++nerrors;
70 }
71 continue;
72 }
73 if (verbose)
74 printf ("%s.%d: done with setjmp(); calling children\n",
75 __FUNCTION__, i + 1);
76
77 raise_longjmp (jbuf, 0, i + 1);
78
hp.com!davidm1c5c60b2003-09-25 05:08:18 +000079 fprintf (stderr, "%s: raise_longjmp() returned unexpectedly\n",
mostang.com!davidm824d6612003-02-08 10:10:59 +000080 __FUNCTION__);
81 ++nerrors;
82 }
83}
84
85
86void
87raise_siglongjmp (sigjmp_buf jbuf, int i, int n)
88{
89 while (i < n)
90 raise_siglongjmp (jbuf, i + 1, n);
91
92 siglongjmp (jbuf, n);
93}
94
95void
96test_sigsetjmp (void)
97{
98 sigjmp_buf jbuf;
mostang.com!davidm5adfead2003-03-28 07:43:22 +000099 volatile int i;
100 int ret;
mostang.com!davidm824d6612003-02-08 10:10:59 +0000101
102 for (i = 0; i < 10; ++i)
103 {
104 if ((ret = sigsetjmp (jbuf, 1)))
105 {
106 if (verbose)
107 printf ("%s: secondary sigsetjmp () return, ret=%d\n",
108 __FUNCTION__, ret);
109 if (ret != i + 1)
110 {
111 fprintf (stderr, "%s: sigsetjmp() returned %d, expected %d\n",
112 __FUNCTION__, ret, i + 1);
113 ++nerrors;
114 }
115 continue;
116 }
117 if (verbose)
118 printf ("%s.%d: done with sigsetjmp(); calling children\n",
119 __FUNCTION__, i + 1);
120
121 raise_siglongjmp (jbuf, 0, i + 1);
122
hp.com!davidm1c5c60b2003-09-25 05:08:18 +0000123 fprintf (stderr, "%s: raise_siglongjmp() returned unexpectedly\n",
mostang.com!davidm824d6612003-02-08 10:10:59 +0000124 __FUNCTION__);
125 ++nerrors;
126 }
127}
128
129void
130sighandler (int signal)
131{
132 if (verbose)
133 printf ("%s: got signal %d\n", __FUNCTION__, signal);
134
135 sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset4);
hp.com!davidm1c5c60b2003-09-25 05:08:18 +0000136 if (verbose)
137 printf ("%s: back from sigprocmask\n", __FUNCTION__);
138
mostang.com!davidm824d6612003-02-08 10:10:59 +0000139 siglongjmp (sigjbuf, 1);
hp.com!davidm1c5c60b2003-09-25 05:08:18 +0000140 printf ("%s: siglongjmp() returned unexpectedly!\n", __FUNCTION__);
mostang.com!davidm824d6612003-02-08 10:10:59 +0000141}
142
143int
Tommi Rantala6b55e0a2012-09-19 13:50:59 +0300144main (int argc, char **argv UNUSED)
mostang.com!davidm824d6612003-02-08 10:10:59 +0000145{
146 volatile sigset_t sigset1, sigset2, sigset3;
147 volatile struct sigaction act;
148
149 if (argc > 1)
150 verbose = 1;
151
152 sigemptyset ((sigset_t *) &sigset1);
153 sigaddset ((sigset_t *) &sigset1, SIGUSR1);
154 sigemptyset ((sigset_t *) &sigset2);
155 sigaddset ((sigset_t *) &sigset2, SIGUSR2);
156
157 memset ((void *) &act, 0, sizeof (act));
158 act.sa_handler = sighandler;
159 sigaction (SIGTERM, (struct sigaction *) &act, NULL);
160
161 test_setjmp ();
162 test_sigsetjmp ();
163
164 /* _setjmp() MUST NOT change signal mask: */
165 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
166 if (_setjmp (jbuf))
167 {
168 sigemptyset ((sigset_t *) &sigset3);
169 sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
170 if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2,
171 sizeof (sigset_t)) != 0)
172 {
173 fprintf (stderr, "FAILURE: _longjmp() manipulated signal mask!\n");
174 ++nerrors;
175 }
176 else if (verbose)
177 printf ("OK: _longjmp() seems not to change signal mask\n");
178 }
179 else
180 {
181 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
182 _longjmp (jbuf, 1);
183 }
184
185 /* sigsetjmp(jbuf, 1) MUST preserve signal mask: */
186 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
187 if (sigsetjmp (sigjbuf, 1))
188 {
189 sigemptyset ((sigset_t *) &sigset3);
190 sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
191 if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1,
192 sizeof (sigset_t)) != 0)
193 {
194 fprintf (stderr,
195 "FAILURE: siglongjmp() didn't restore signal mask!\n");
196 ++nerrors;
197 }
198 else if (verbose)
199 printf ("OK: siglongjmp() restores signal mask when asked to\n");
200 }
201 else
202 {
203 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
204 siglongjmp (sigjbuf, 1);
205 }
206
207 /* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */
208 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
209 if (sigsetjmp (sigjbuf, 0))
210 {
211 sigemptyset ((sigset_t *) &sigset3);
212 sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
213 if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2,
214 sizeof (sigset_t)) != 0)
215 {
216 fprintf (stderr,
217 "FAILURE: siglongjmp() changed signal mask!\n");
218 ++nerrors;
219 }
220 else if (verbose)
hp.com!davidm1c5c60b2003-09-25 05:08:18 +0000221 printf ("OK: siglongjmp() leaves signal mask alone when asked to\n");
mostang.com!davidm824d6612003-02-08 10:10:59 +0000222 }
223 else
224 {
225 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
226 siglongjmp (sigjbuf, 1);
227 }
228
229 /* sigsetjmp(jbuf, 1) MUST preserve signal mask: */
230 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
231 if (sigsetjmp (sigjbuf, 1))
232 {
233 sigemptyset ((sigset_t *) &sigset3);
234 sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
235 if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1,
236 sizeof (sigset_t)) != 0)
237 {
238 fprintf (stderr,
239 "FAILURE: siglongjmp() didn't restore signal mask!\n");
240 ++nerrors;
241 }
242 else if (verbose)
243 printf ("OK: siglongjmp() restores signal mask when asked to\n");
244 }
245 else
246 {
247 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
248 kill (getpid (), SIGTERM);
249 fprintf (stderr, "FAILURE: unexpected return from kill()\n");
250 ++nerrors;
251 }
252
253 /* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */
254 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
255 if (sigsetjmp (sigjbuf, 0))
256 {
257 sigemptyset ((sigset_t *) &sigset3);
258 sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
259 if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset4,
260 sizeof (sigset_t)) != 0)
261 {
262 fprintf (stderr,
263 "FAILURE: siglongjmp() changed signal mask!\n");
264 ++nerrors;
265 }
266 else if (verbose)
hp.com!davidm1c5c60b2003-09-25 05:08:18 +0000267 printf ("OK: siglongjmp() leaves signal mask alone when asked to\n");
mostang.com!davidm824d6612003-02-08 10:10:59 +0000268 }
269 else
270 {
271 sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
272 kill (getpid (), SIGTERM);
273 fprintf (stderr, "FAILURE: unexpected return from kill()\n");
274 ++nerrors;
275 }
276
277 if (nerrors > 0)
278 {
279 fprintf (stderr, "FAILURE: detected %d failures\n", nerrors);
280 exit (-1);
281 }
282 if (verbose)
283 printf ("SUCCESS\n");
284 return 0;
285}