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