diff options
Diffstat (limited to 'compiler-rt/test/tsan/Darwin/write-interpose.c')
-rw-r--r-- | compiler-rt/test/tsan/Darwin/write-interpose.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/compiler-rt/test/tsan/Darwin/write-interpose.c b/compiler-rt/test/tsan/Darwin/write-interpose.c new file mode 100644 index 0000000..cbd9a08 --- /dev/null +++ b/compiler-rt/test/tsan/Darwin/write-interpose.c @@ -0,0 +1,50 @@ +// Test that dylibs interposing write, and then calling functions intercepted +// by TSan don't deadlock (self-lock) + +// RUN: %clang_tsan %s -o %t +// RUN: %clang_tsan %s -o %t.dylib -fno-sanitize=thread -dynamiclib -DSHARED_LIB + +// Note that running the below command with out `lock_during_write` should +// deadlock (self-lock) +// RUN: env DYLD_INSERT_LIBRARIES=%t.dylib TSAN_OPTIONS=verbosity=2:lock_during_write=disable_for_current_process %run %t 2>&1 | FileCheck %s + +#include <stdio.h> + +#if defined(SHARED_LIB) + +// dylib implementation - interposes write() calls +# include <os/lock.h> +# include <unistd.h> + +struct interpose_substitution { + const void *replacement; + const void *original; +}; + +# define INTERPOSE(replacement, original) \ + __attribute__((used)) static const struct interpose_substitution \ + substitution_##original[] \ + __attribute__((section("__DATA, __interpose"))) = { \ + {(const void *)(replacement), (const void *)(original)}} + +static ssize_t my_write(int fd, const void *buf, size_t count) { + struct os_unfair_lock_s lock = OS_UNFAIR_LOCK_INIT; + os_unfair_lock_lock(&lock); + printf("Interposed write called: fd=%d, count=%zu\n", fd, count); + ssize_t res = write(fd, buf, count); + os_unfair_lock_unlock(&lock); + return res; +} +INTERPOSE(my_write, write); + +#else // defined(SHARED_LIB) + +int main() { + printf("Write test completed\n"); + return 0; +} + +#endif // defined(SHARED_LIB) + +// CHECK: Interposed write called: fd={{[0-9]+}}, count={{[0-9]+}} +// CHECK: Write test completed |