1 // This test checks that the implementation of use-after-return 2 // is async-signal-safe. 3 // RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread && %run %t 4 // RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread -fsanitize-address-use-after-return=never && %run %t 5 // RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread -fsanitize-address-use-after-return=always && %run %t 6 // REQUIRES: stable-runtime 7 #include <signal.h> 8 #include <stdlib.h> 9 #include <stdio.h> 10 #include <sys/time.h> 11 #include <pthread.h> 12 #include <initializer_list> 13 14 int *g; 15 int n_signals; 16 17 typedef void (*Sigaction)(int, siginfo_t *, void *); 18 19 void SignalHandler(int, siginfo_t*, void*) { 20 int local; 21 g = &local; 22 n_signals++; 23 } 24 25 static void EnableSigprof(Sigaction SignalHandler) { 26 struct sigaction sa; 27 sa.sa_sigaction = SignalHandler; 28 sa.sa_flags = SA_RESTART | SA_SIGINFO; 29 sigemptyset(&sa.sa_mask); 30 if (sigaction(SIGPROF, &sa, NULL) != 0) { 31 perror("sigaction"); 32 abort(); 33 } 34 struct itimerval timer; 35 timer.it_interval.tv_sec = 0; 36 timer.it_interval.tv_usec = 1; 37 timer.it_value = timer.it_interval; 38 if (setitimer(ITIMER_PROF, &timer, 0) != 0) { 39 perror("setitimer"); 40 abort(); 41 } 42 } 43 44 void RecursiveFunction(int depth) { 45 if (depth == 0) return; 46 int local; 47 g = &local; 48 // printf("r: %p\n", &local); 49 // printf("[%2d] n_signals: %d\n", depth, n_signals); 50 RecursiveFunction(depth - 1); 51 RecursiveFunction(depth - 1); 52 } 53 54 void *FastThread(void *) { 55 RecursiveFunction(1); 56 return NULL; 57 } 58 59 void *SlowThread(void *) { 60 RecursiveFunction(1); 61 return NULL; 62 } 63 64 int main(int argc, char **argv) { 65 EnableSigprof(SignalHandler); 66 67 for (auto Thread : {&FastThread, &SlowThread}) { 68 for (int i = 0; i < 100; i++) { 69 fprintf(stderr, "."); 70 const int kNumThread = 8; 71 pthread_t t[kNumThread]; 72 for (int i = 0; i < kNumThread; i++) 73 pthread_create(&t[i], 0, Thread, 0); 74 for (int i = 0; i < kNumThread; i++) 75 pthread_join(t[i], 0); 76 } 77 fprintf(stderr, "\n"); 78 } 79 } 80