brintos

brintos / llvm-project-archived public Read only

0
0
Text · 1.7 KiB · 2a5b81c Raw
70 lines · cpp
1// TODO(#96597): fix and reenable2// UNSUPPORTED: darwin3 4// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=atexit_sleep_ms=0 %run %t 2>&1 | FileCheck %s5 6// This test models what happens on Mac when fork7// calls malloc/free inside of our atfork callbacks.8// and ensures that we don't deadlock on malloc/free calls.9 10#include "../test.h"11#include "syscall.h"12#include <errno.h>13#include <string.h>14#include <sys/types.h>15#include <sys/wait.h>16 17// disable_sanitizer_instrumentation on __tsan_test_only_on_fork is not18// transitive, so we must apply it here as well.19// Instrumenting alloc_free_blocks() will result in deadlocks in TSan.20__attribute__((disable_sanitizer_instrumentation)) void alloc_free_blocks() {21  // Allocate a bunch of blocks to drain local allocator cache22  // and provoke it to lock allocator global mutexes.23  const int kBlocks = 1000;24  void *blocks[kBlocks];25  for (int i = 0; i < kBlocks; i++) {26    void *p = malloc(10);27    *(volatile char *)p = 0;28    blocks[i] = p;29  }30  for (int i = 0; i < kBlocks; i++)31    free(blocks[i]);32}33 34__attribute__((disable_sanitizer_instrumentation)) extern "C" void35__tsan_test_only_on_fork() {36  const char *msg = "__tsan_test_only_on_fork\n";37  write(2, msg, strlen(msg));38  alloc_free_blocks();39}40 41static void *background(void *p) {42  for (;;)43    alloc_free_blocks();44  return 0;45}46 47int main() {48  pthread_t th;49  pthread_create(&th, 0, background, 0);50  pthread_detach(th);51  for (int i = 0; i < 10; i++) {52    int pid = myfork();53    if (pid < 0) {54      fprintf(stderr, "failed to fork (%d)\n", errno);55      exit(1);56    }57    if (pid == 0) {58      // child59      exit(0);60    }61    // parent62    while (wait(0) < 0) {63    }64  }65  fprintf(stderr, "DONE\n");66}67 68// CHECK: __tsan_test_only_on_fork69// CHECK: DONE70