brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.7 KiB · 5f26ba2 Raw
113 lines · c
1// RUN: %clang -O0 %s -o %t && %env_tool_opts=die_after_fork=0 %run %t2 3// The test uses pthread barriers which are not available on Darwin.4// UNSUPPORTED: darwin5 6// FIXME: It probably hangs on this platform.7// UNSUPPORTED: ppc8 9// FIXME: False stack overflow report10// UNSUPPORTED: android && asan11 12// FIXME: Requires `FutexWait` implementation. See __asan::InstallAtForkHandler.13// UNSUPPORTED: target={{.*solaris.*}}14// UNSUPPORTED: target={{.*netbsd.*}}15// UNSUPPORTED: target={{.*apple.*}}16 17// Forking in multithread environment is unsupported. However we already have18// some workarounds, and will add more, so this is the test.19// The test try to check two things:20//  1. Internal mutexes used by `inparent` thread do not deadlock `inchild`21//     thread.22//  2. Stack poisoned by `inparent` is not poisoned in `inchild` thread.23 24// Stack tagging is unsupported.25// UNSUPPORTED: hwasan-aliasing26 27#include <assert.h>28#include <pthread.h>29#include <stdint.h>30#include <stdio.h>31#include <stdlib.h>32#include <sys/types.h>33#include <sys/wait.h>34#include <unistd.h>35 36#include "sanitizer_common/sanitizer_specific.h"37 38static const size_t kBufferSize = 8192;39 40pthread_barrier_t bar;41 42// Without appropriate workarounds this code can cause the forked process to43// start with locked internal mutexes.44void ShouldNotDeadlock() {45  // Don't bother with leaks, we try to trigger allocator or lsan deadlock.46  __lsan_disable();47  void *volatile p = malloc(10);48  __lsan_do_recoverable_leak_check();49  // Allocator still in broken state, `free` may report errors.50  // free(p);51  __lsan_enable();52}53 54// Prevent stack buffer cleanup by instrumentation.55#define NOSAN __attribute__((no_sanitize("address", "hwaddress", "memory")))56 57NOSAN static void *inparent(void *arg) {58  char t[kBufferSize];59  make_mem_bad(t, sizeof(t));60 61  pthread_barrier_wait(&bar);62 63  for (;;)64    ShouldNotDeadlock();65 66  return 0;67}68 69NOSAN static void *inchild(void *arg) {70  char t[kBufferSize];71  check_mem_is_good(t, sizeof(t));72  ShouldNotDeadlock();73  return 0;74}75 76int main(void) {77#if __has_feature(hwaddress_sanitizer)78  __hwasan_enable_allocator_tagging();79#endif80 81  pid_t pid;82 83  pthread_barrier_init(&bar, NULL, 2);84  pthread_t thread_id;85  while (pthread_create(&thread_id, 0, &inparent, 0) != 0) {86  }87  pthread_barrier_wait(&bar);88 89  pid = fork();90  switch (pid) {91  case -1:92    perror("fork");93    return -1;94  case 0:95    ShouldNotDeadlock();96    while (pthread_create(&thread_id, 0, &inchild, 0) != 0) {97    }98    pthread_join(thread_id, NULL);99    _exit(0);100    break;101  default: {102    int status;103    pid_t child = waitpid(pid, &status, /*options=*/0);104    assert(pid == child);105    assert(WIFEXITED(status));106    assert(WEXITSTATUS(status) == 0);107    break;108  }109  }110 111  return 0;112}113