/* Test whether sigaltstack works per thread. */ #include #include #include #include #include #include #include #include #include /* Correct the value of SIGSTKSZ on some systems. AIX 64-bit: original value 4096 is too small. HP-UX: original value 8192 is too small. */ #if defined _AIX && defined _ARCH_PPC64 # undef SIGSTKSZ # define SIGSTKSZ 8192 #endif #if defined __hpux || (defined __sun && (defined __x86_64__ || defined __amd64__)) # undef SIGSTKSZ # define SIGSTKSZ 16384 #endif static void* thread2_func (void *ignored) { stack_t current; stack_t alt_stack; char mystack_storage[SIGSTKSZ + 31]; char *mystack = (char *)((uintptr_t) mystack_storage | 31); fprintf (stderr, "thread2 running\n"); if (sigaltstack (NULL, ¤t) < 0) { perror ("thread2 sigaltstack"); exit (1); } fprintf (stderr, "thread2 sigaltstack: enabled=%s onstack=%s sp=0x%lx size=0x%lx\n", (current.ss_flags & SS_DISABLE) ? "no" : "yes", (current.ss_flags & SS_ONSTACK) ? "yes" : "no", (unsigned long) current.ss_sp, (unsigned long) current.ss_size); if ((current.ss_flags & SS_DISABLE) == 0 && current.ss_size > 0) { fprintf (stderr, "thread2 sigaltstack already enabled! Per-thread not supported.\n"); exit (1); } alt_stack.ss_flags = 0; alt_stack.ss_sp = mystack; alt_stack.ss_size = SIGSTKSZ; if (sigaltstack (&alt_stack, NULL) < 0) { perror ("thread2 sigaltstack set"); exit (1); } fprintf (stderr, "thread2 alternate stack installed\n"); if (sigaltstack (NULL, ¤t) < 0) { perror ("thread2 sigaltstack"); exit (1); } fprintf (stderr, "thread2 sigaltstack now: enabled=%s onstack=%s sp=0x%lx size=0x%lx\n", (current.ss_flags & SS_DISABLE) ? "no" : "yes", (current.ss_flags & SS_ONSTACK) ? "yes" : "no", (unsigned long) current.ss_sp, (unsigned long) current.ss_size); return 0; } int main () { stack_t alt_stack; stack_t current; stack_t last; pthread_t thread2; struct timeval sleeptime; char mystack_storage[SIGSTKSZ + 31]; char *mystack = (char *)((uintptr_t) mystack_storage | 31); alt_stack.ss_flags = 0; alt_stack.ss_sp = mystack; alt_stack.ss_size = SIGSTKSZ; if (sigaltstack (&alt_stack, NULL) < 0) { perror ("main-thread sigaltstack set"); exit (1); } fprintf (stderr, "alternate stack installed\n"); if (sigaltstack (NULL, ¤t) < 0) { perror ("main-thread sigaltstack"); exit (1); } fprintf (stderr, "main-thread sigaltstack: enabled=%s onstack=%s sp=0x%lx size=0x%lx\n", (current.ss_flags & SS_DISABLE) ? "no" : "yes", (current.ss_flags & SS_ONSTACK) ? "yes" : "no", (unsigned long) current.ss_sp, (unsigned long) current.ss_size); last = current; if (pthread_create (&thread2, NULL, thread2_func, NULL)) { fprintf (stderr, "creating of thread2 failed\n"); exit (1); } /* Sleep 2 sec. */ sleeptime.tv_sec = 2; sleeptime.tv_usec = 0; if (select (0, NULL, NULL, NULL, &sleeptime) < 0) { perror ("main-thread sleep"); exit (1); } if (sigaltstack (NULL, ¤t) < 0) { perror ("main-thread sigaltstack"); exit (1); } fprintf (stderr, "main-thread sigaltstack: enabled=%s onstack=%s sp=0x%lx size=0x%lx\n", (current.ss_flags & SS_DISABLE) ? "no" : "yes", (current.ss_flags & SS_ONSTACK) ? "yes" : "no", (unsigned long) current.ss_sp, (unsigned long) current.ss_size); if (!(current.ss_flags == last.ss_flags && current.ss_sp == last.ss_sp && current.ss_size == last.ss_size)) { fprintf (stderr, "main-thread sigaltstack has changed!\n"); exit (1); } fprintf (stderr, "SUPPORTED\n"); exit (0); } /* Results: Linux SUPPORTED Hurd SUPPORTED although "enabled=yes onstack=no sp=0x0 size=0x0" Mac OS X 10.5 SUPPORTED FreeBSD 11 SUPPORTED NetBSD 7 thread2 sigaltstack already enabled! Per-thread not supported. NetBSD 8 SUPPORTED OpenBSD 6.0 SUPPORTED AIX 7.1 SUPPORTED HP-UX 11.31 SUPPORTED IRIX 6.5 thread2 sigaltstack already enabled! Per-thread not supported. Solaris 9, 10 SUPPORTED Haiku SUPPORTED Cygwin SUPPORTED */