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