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