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