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