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
23sigjmp_buf fault_jmp;
24volatile int fault_expected;
25
26void 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
46int 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