1 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s 2 3 // Test case for longjumping out of signal handler: 4 // https://github.com/google/sanitizers/issues/482 5 6 // This test fails on powerpc64 BE (VMA=44), a segmentation fault 7 // error happens at the second assignment 8 // "((volatile int *volatile)mem)[1] = 1". 9 // XFAIL: powerpc64-unknown-linux-gnu 10 11 #include <setjmp.h> 12 #include <signal.h> 13 #include <stdlib.h> 14 #include <stdio.h> 15 #include <sys/mman.h> 16 17 #ifdef __APPLE__ 18 #define SIGNAL_TO_HANDLE SIGBUS 19 #else 20 #define SIGNAL_TO_HANDLE SIGSEGV 21 #endif 22 23 sigjmp_buf fault_jmp; 24 volatile int fault_expected; 25 26 void sigfault_handler(int sig) { 27 if (!fault_expected) 28 abort(); 29 30 /* just return from sighandler to proper place */ 31 fault_expected = 0; 32 siglongjmp(fault_jmp, 1); 33 } 34 35 #define MUST_FAULT(code) do { \ 36 fault_expected = 1; \ 37 if (!sigsetjmp(fault_jmp, 1)) { \ 38 code; /* should pagefault -> sihandler does longjmp */ \ 39 fprintf(stderr, "%s not faulted\n", #code); \ 40 abort(); \ 41 } else { \ 42 fprintf(stderr, "%s faulted ok\n", #code); \ 43 } \ 44 } while (0) 45 46 int main() { 47 struct sigaction act; 48 act.sa_handler = sigfault_handler; 49 act.sa_flags = 0; 50 if (sigemptyset(&act.sa_mask)) { 51 perror("sigemptyset"); 52 exit(1); 53 } 54 55 if (sigaction(SIGNAL_TO_HANDLE, &act, NULL)) { 56 perror("sigaction"); 57 exit(1); 58 } 59 60 void *mem = mmap(0, 4096, PROT_NONE, MAP_PRIVATE | MAP_ANON, 61 -1, 0); 62 63 MUST_FAULT(((volatile int *volatile)mem)[0] = 0); 64 MUST_FAULT(((volatile int *volatile)mem)[1] = 1); 65 MUST_FAULT(((volatile int *volatile)mem)[3] = 1); 66 67 // Ensure that tsan does not think that we are 68 // in a signal handler. 69 void *volatile p = malloc(10); 70 ((volatile int*)p)[1] = 1; 71 free((void*)p); 72 73 munmap(p, 4096); 74 75 fprintf(stderr, "DONE\n"); 76 return 0; 77 } 78 79 // CHECK-NOT: WARNING: ThreadSanitizer 80 // CHECK: DONE 81