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
11int *g;
12int n_signals;
13
14typedef void (*Sigaction)(int, siginfo_t *, void *);
15
16void SignalHandler(int, siginfo_t*, void*) {
17  int local;
18  g = &local;
19  n_signals++;
20  // printf("s: %p\n", &local);
21}
22
23static 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
42void 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
52void *Thread(void *) {
53  RecursiveFunction(18);
54  return NULL;
55}
56
57int 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