1 // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
2 
3 #include <pthread.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <setjmp.h>
7 #include <string.h>
8 
bar(jmp_buf env)9 void bar(jmp_buf env) {
10   volatile int x = 42;
11   jmp_buf env2;
12   memcpy(env2, env, sizeof(jmp_buf));
13   longjmp(env2, 42);
14   x++;
15 }
16 
foo(jmp_buf env)17 void foo(jmp_buf env) {
18   volatile int x = 42;
19   bar(env);
20   x++;
21 }
22 
badguy()23 void badguy() __attribute__((noinline)) {
24   pthread_mutex_t mtx;
25   pthread_mutex_init(&mtx, 0);
26   pthread_mutex_lock(&mtx);
27   pthread_mutex_destroy(&mtx);
28 }
29 
mymain()30 void mymain() __attribute__((noinline)) {
31   jmp_buf env;
32   if (setjmp(env) == 42) {
33     badguy();
34     return;
35   }
36   foo(env);
37   fprintf(stderr, "FAILED\n");
38 }
39 
main()40 int main() {
41   volatile int x = 42;
42   mymain();
43   return x;
44 }
45 
46 // CHECK-NOT: FAILED
47 // CHECK: WARNING: ThreadSanitizer: destroy of a locked mutex
48 // CHECK:   #0 pthread_mutex_destroy
49 // CHECK:   #1 badguy
50 // CHECK:   #2 mymain
51 // CHECK:   #3 main
52 
53