• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libunwind - a platform-independent unwind library
2    Copyright (C) 2003 Hewlett-Packard Co
3 	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4 
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
12 
13 The above copyright notice and this permission notice shall be
14 included in all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
23 
24 /* The setjmp()/longjmp(), sigsetjmp()/siglongjmp().  */
25 
26 #include "compiler.h"
27 
28 #include <setjmp.h>
29 #include <signal.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 int nerrors;
36 int verbose;
37 
38 static jmp_buf jbuf;
39 static sigjmp_buf sigjbuf;
40 static sigset_t sigset4;
41 
42 void
raise_longjmp(jmp_buf jbuf,int i,int n)43 raise_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 
51 void
test_setjmp(void)52 test_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 
79       fprintf (stderr, "%s: raise_longjmp() returned unexpectedly\n",
80 	       __FUNCTION__);
81       ++nerrors;
82     }
83 }
84 
85 
86 void
raise_siglongjmp(sigjmp_buf jbuf,int i,int n)87 raise_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 
95 void
test_sigsetjmp(void)96 test_sigsetjmp (void)
97 {
98   sigjmp_buf jbuf;
99   volatile int i;
100   int ret;
101 
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 
123       fprintf (stderr, "%s: raise_siglongjmp() returned unexpectedly\n",
124 	       __FUNCTION__);
125       ++nerrors;
126     }
127 }
128 
129 void
sighandler(int signal)130 sighandler (int signal)
131 {
132   if (verbose)
133     printf ("%s: got signal %d\n", __FUNCTION__, signal);
134 
135   sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset4);
136   if (verbose)
137     printf ("%s: back from sigprocmask\n", __FUNCTION__);
138 
139   siglongjmp (sigjbuf, 1);
140   printf ("%s: siglongjmp() returned unexpectedly!\n", __FUNCTION__);
141 }
142 
143 int
main(int argc,char ** argv UNUSED)144 main (int argc, char **argv UNUSED)
145 {
146   volatile sigset_t sigset1, sigset2, sigset3;
147   volatile struct sigaction act;
148 
149   if (argc > 1)
150     verbose = 1;
151 
152   memset (&sigset1, 0, sizeof (sigset1));
153   memset (&sigset2, 0, sizeof (sigset2));
154   memset (&sigset3, 0, sizeof (sigset3));
155 
156   sigemptyset ((sigset_t *) &sigset1);
157   sigaddset ((sigset_t *) &sigset1, SIGUSR1);
158   sigemptyset ((sigset_t *) &sigset2);
159   sigaddset ((sigset_t *) &sigset2, SIGUSR2);
160 
161   memset ((void *) &act, 0, sizeof (act));
162   act.sa_handler = sighandler;
163   sigaction (SIGTERM, (struct sigaction *) &act, NULL);
164 
165   test_setjmp ();
166   test_sigsetjmp ();
167 
168   /* _setjmp() MUST NOT change signal mask: */
169   sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
170   if (_setjmp (jbuf))
171     {
172       sigemptyset ((sigset_t *) &sigset3);
173       sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
174       if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2,
175 		  sizeof (sigset_t)) != 0)
176 	{
177 	  fprintf (stderr, "FAILURE: _longjmp() manipulated signal mask!\n");
178 	  ++nerrors;
179 	}
180       else if (verbose)
181 	printf ("OK: _longjmp() seems not to change signal mask\n");
182     }
183   else
184     {
185       sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
186       _longjmp (jbuf, 1);
187     }
188 
189   /* sigsetjmp(jbuf, 1) MUST preserve signal mask: */
190   sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
191   if (sigsetjmp (sigjbuf, 1))
192     {
193       sigemptyset ((sigset_t *) &sigset3);
194       sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
195       if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1,
196 		  sizeof (sigset_t)) != 0)
197 	{
198 	  fprintf (stderr,
199 		   "FAILURE: siglongjmp() didn't restore signal mask!\n");
200 	  ++nerrors;
201 	}
202       else if (verbose)
203 	printf ("OK: siglongjmp() restores signal mask when asked to\n");
204     }
205   else
206     {
207       sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
208       siglongjmp (sigjbuf, 1);
209     }
210 
211   /* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */
212   sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
213   if (sigsetjmp (sigjbuf, 0))
214     {
215       sigemptyset ((sigset_t *) &sigset3);
216       sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
217       if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2,
218 		  sizeof (sigset_t)) != 0)
219 	{
220 	  fprintf (stderr,
221 		   "FAILURE: siglongjmp() changed signal mask!\n");
222 	  ++nerrors;
223 	}
224       else if (verbose)
225 	printf ("OK: siglongjmp() leaves signal mask alone when asked to\n");
226     }
227   else
228     {
229       sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
230       siglongjmp (sigjbuf, 1);
231     }
232 
233   /* sigsetjmp(jbuf, 1) MUST preserve signal mask: */
234   sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
235   if (sigsetjmp (sigjbuf, 1))
236     {
237       sigemptyset ((sigset_t *) &sigset3);
238       sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
239       if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1,
240 		  sizeof (sigset_t)) != 0)
241 	{
242 	  fprintf (stderr,
243 		   "FAILURE: siglongjmp() didn't restore signal mask!\n");
244 	  ++nerrors;
245 	}
246       else if (verbose)
247 	printf ("OK: siglongjmp() restores signal mask when asked to\n");
248     }
249   else
250     {
251       sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
252       kill (getpid (), SIGTERM);
253       fprintf (stderr, "FAILURE: unexpected return from kill()\n");
254       ++nerrors;
255     }
256 
257   /* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */
258   sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
259   if (sigsetjmp (sigjbuf, 0))
260     {
261       sigemptyset ((sigset_t *) &sigset3);
262       sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
263       if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset4,
264 		  sizeof (sigset_t)) != 0)
265 	{
266 	  fprintf (stderr,
267 		   "FAILURE: siglongjmp() changed signal mask!\n");
268 	  ++nerrors;
269 	}
270       else if (verbose)
271 	printf ("OK: siglongjmp() leaves signal mask alone when asked to\n");
272     }
273   else
274     {
275       sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
276       kill (getpid (), SIGTERM);
277       fprintf (stderr, "FAILURE: unexpected return from kill()\n");
278       ++nerrors;
279     }
280 
281   if (nerrors > 0)
282     {
283       fprintf (stderr, "FAILURE: detected %d failures\n", nerrors);
284       exit (-1);
285     }
286   if (verbose)
287     printf ("SUCCESS\n");
288   return 0;
289 }
290