|  | 
|  | 1 | +// Test that dylibs interposing write, and then calling functions intercepted | 
|  | 2 | +// by TSan don't deadlock (self-lock) | 
|  | 3 | + | 
|  | 4 | +// RUN: %clang_tsan %s -o %t | 
|  | 5 | +// RUN: %clang_tsan %s -o %t.dylib -fno-sanitize=thread -dynamiclib -DSHARED_LIB | 
|  | 6 | + | 
|  | 7 | +// Note that running the below command with out `lock_during_write` should | 
|  | 8 | +// deadlock (self-lock) | 
|  | 9 | +// RUN: env DYLD_INSERT_LIBRARIES=%t.dylib TSAN_OPTIONS=verbosity=2:lock_during_write=disable_for_current_process %run %t 2>&1 | FileCheck %s | 
|  | 10 | +// | 
|  | 11 | +// UNSUPPORTED: ios | 
|  | 12 | + | 
|  | 13 | +#include <stdio.h> | 
|  | 14 | + | 
|  | 15 | +#if defined(SHARED_LIB) | 
|  | 16 | + | 
|  | 17 | +// dylib implementation - interposes write() calls | 
|  | 18 | +#  include <os/lock.h> | 
|  | 19 | +#  include <unistd.h> | 
|  | 20 | + | 
|  | 21 | +struct interpose_substitution { | 
|  | 22 | +  const void *replacement; | 
|  | 23 | +  const void *original; | 
|  | 24 | +}; | 
|  | 25 | + | 
|  | 26 | +#  define INTERPOSE(replacement, original)                                     \ | 
|  | 27 | +    __attribute__((used)) static const struct interpose_substitution           \ | 
|  | 28 | +        substitution_##original[]                                              \ | 
|  | 29 | +        __attribute__((section("__DATA, __interpose"))) = {                    \ | 
|  | 30 | +            {(const void *)(replacement), (const void *)(original)}} | 
|  | 31 | + | 
|  | 32 | +static ssize_t my_write(int fd, const void *buf, size_t count) { | 
|  | 33 | +  struct os_unfair_lock_s lock = OS_UNFAIR_LOCK_INIT; | 
|  | 34 | +  os_unfair_lock_lock(&lock); | 
|  | 35 | +  printf("Interposed write called: fd=%d, count=%zu\n", fd, count); | 
|  | 36 | +  ssize_t res = write(fd, buf, count); | 
|  | 37 | +  os_unfair_lock_unlock(&lock); | 
|  | 38 | +  return res; | 
|  | 39 | +} | 
|  | 40 | +INTERPOSE(my_write, write); | 
|  | 41 | + | 
|  | 42 | +#else // defined(SHARED_LIB) | 
|  | 43 | + | 
|  | 44 | +int main() { | 
|  | 45 | +  printf("Write test completed\n"); | 
|  | 46 | +  return 0; | 
|  | 47 | +} | 
|  | 48 | + | 
|  | 49 | +#endif // defined(SHARED_LIB) | 
|  | 50 | + | 
|  | 51 | +// CHECK: Interposed write called: fd={{[0-9]+}}, count={{[0-9]+}} | 
|  | 52 | +// CHECK: Write test completed | 
0 commit comments