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