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