1 // This test checks that the implementation of use-after-return 2 // is async-signal-safe. 3 // RUN: %clangxx_asan -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 11 int *g; 12 int n_signals; 13 14 typedef void (*Sigaction)(int, siginfo_t *, void *); 15 16 void SignalHandler(int, siginfo_t*, void*) { 17 int local; 18 g = &local; 19 n_signals++; 20 // printf("s: %p\n", &local); 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 *Thread(void *) { 53 RecursiveFunction(18); 54 return NULL; 55 } 56 57 int main(int argc, char **argv) { 58 EnableSigprof(SignalHandler); 59 60 for (int i = 0; i < 4; i++) { 61 fprintf(stderr, "."); 62 const int kNumThread = sizeof(void*) == 8 ? 16 : 8; 63 pthread_t t[kNumThread]; 64 for (int i = 0; i < kNumThread; i++) 65 pthread_create(&t[i], 0, Thread, 0); 66 for (int i = 0; i < kNumThread; i++) 67 pthread_join(t[i], 0); 68 } 69 fprintf(stderr, "\n"); 70 } 71