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