brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.7 KiB · 36fdf81 Raw
101 lines · cpp
1// RUN: %clangxx_asan -O0 -pthread %s -o %t && %env_asan_opts=use_sigaltstack=0 not --crash %run %t 2>&1 | FileCheck %s2 3// Check that fake stack does not discard frames on the main stack, when GC is4// triggered from high alt stack.5 6// This test does not work on iOS simulator7// (https://github.com/llvm/llvm-project/issues/64942).8// UNSUPPORTED: iossim9 10#include <algorithm>11#include <assert.h>12#include <csignal>13#include <cstdint>14#include <pthread.h>15#include <signal.h>16#include <stdio.h>17#include <stdlib.h>18#include <unistd.h>19 20const size_t kStackSize = 0x100000;21 22int *on_thread;23int *p;24 25template <size_t N> void Fn() {26  int t[N];27  p = t;28  if constexpr (N > 1)29    Fn<N - 1>();30}31 32static void Handler(int signo) {33  fprintf(stderr, "Handler Frame:%p\n", __builtin_frame_address(0));34 35  // Trigger GC and create a lot of frame to reuse "Thread" frame if it was36  // discarded.37  for (int i = 0; i < 1000; ++i)38    Fn<100>();39  // If we discarder and reused "Thread" frame, the next line will crash with40  // false report.41  *on_thread = 10;42  fprintf(stderr, "SUCCESS\n");43  // CHECK: SUCCESS44}45 46void *Thread(void *arg) {47  fprintf(stderr, "Thread Frame:%p\n", __builtin_frame_address(0));48  stack_t stack = {};49  stack.ss_sp = arg;50  stack.ss_flags = 0;51  stack.ss_size = kStackSize;52  assert(sigaltstack(&stack, nullptr) == 0);53 54  struct sigaction sa = {};55  sa.sa_handler = Handler;56  sa.sa_flags = SA_ONSTACK;57  sigaction(SIGABRT, &sa, nullptr);58 59  // Store pointer to the local var, so we can access this frame from the signal60  // handler when the frame is still alive.61  int n;62  on_thread = &n;63 64  // Abort should schedule FakeStack GC and call handler on alt stack.65  abort();66}67 68int main(void) {69  // Allocate main and alt stack for future thread.70  void *main_stack;71  void *alt_stack;72  size_t const kPageSize = sysconf(_SC_PAGESIZE);73  assert(posix_memalign(&main_stack, kPageSize, kStackSize) == 0);74  assert(posix_memalign(&alt_stack, kPageSize, kStackSize) == 0);75 76  // Pick the lower stack as the main stack, as we want to trigger GC in77  // FakeStack from alt stack in a such way that main stack is allocated below.78  if ((uintptr_t)main_stack > (uintptr_t)alt_stack)79    std::swap(alt_stack, main_stack);80 81  fprintf(stderr, "main_stack: %p-%p\n", main_stack,82          (char *)main_stack + kStackSize);83  fprintf(stderr, "alt_stack: %p-%p\n", alt_stack,84          (char *)alt_stack + kStackSize);85 86  pthread_attr_t attr;87  assert(pthread_attr_init(&attr) == 0);88  assert(pthread_attr_setstack(&attr, main_stack, kStackSize) == 0);89 90  pthread_t tid;91  assert(pthread_create(&tid, &attr, Thread, alt_stack) == 0);92  assert(pthread_attr_destroy(&attr) == 0);93 94  pthread_join(tid, nullptr);95 96  free(main_stack);97  free(alt_stack);98 99  return 0;100}101