diff options
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_fd.cc | 15 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_fd.h | 1 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 15 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_stat.cc | 1 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_stat.h | 1 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_sync.cc | 3 |
6 files changed, 36 insertions, 0 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_fd.cc b/compiler-rt/lib/tsan/rtl/tsan_fd.cc index a27bbccba6f..ecd725d15c0 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_fd.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_fd.cc @@ -114,6 +114,21 @@ void FdInit() { atomic_store(&fdctx.socksync.rc, (u64)-1, memory_order_relaxed); } +void FdOnFork(ThreadState *thr, uptr pc) { + // On fork() we need to reset all fd's, because the child is going + // close all them, and that will cause races between previous read/write + // and the close. + for (int l1 = 0; l1 < kTableSizeL1; l1++) { + FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed); + if (tab == 0) + break; + for (int l2 = 0; l2 < kTableSizeL2; l2++) { + FdDesc *d = &tab[l2]; + MemoryResetRange(thr, pc, (uptr)d, 8); + } + } +} + bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack) { for (int l1 = 0; l1 < kTableSizeL1; l1++) { FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed); diff --git a/compiler-rt/lib/tsan/rtl/tsan_fd.h b/compiler-rt/lib/tsan/rtl/tsan_fd.h index 8f8bafb4428..3bf2c747b69 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_fd.h +++ b/compiler-rt/lib/tsan/rtl/tsan_fd.h @@ -54,6 +54,7 @@ void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd); void FdSocketConnecting(ThreadState *thr, uptr pc, int fd); void FdSocketConnect(ThreadState *thr, uptr pc, int fd); bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack); +void FdOnFork(ThreadState *thr, uptr pc); uptr File2addr(char *path); uptr Dir2addr(char *path); diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index cacad2c82ed..da7356cad6f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -1617,6 +1617,19 @@ TSAN_INTERCEPTOR(int, munlockall, void) { return 0; } +TSAN_INTERCEPTOR(int, fork) { + SCOPED_TSAN_INTERCEPTOR(fork); + // It's intercepted merely to process pending signals. + int pid = REAL(fork)(); + if (pid == 0) { + // child + FdOnFork(thr, pc); + } else if (pid > 0) { + // parent + } + return pid; +} + namespace __tsan { void ProcessPendingSignals(ThreadState *thr) { @@ -1826,6 +1839,8 @@ void InitializeInterceptors() { TSAN_INTERCEPT(mlockall); TSAN_INTERCEPT(munlockall); + TSAN_INTERCEPT(fork); + // Need to setup it, because interceptors check that the function is resolved. // But atexit is emitted directly into the module, so can't be resolved. REAL(atexit) = (int(*)(void(*)()))unreachable; diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.cc b/compiler-rt/lib/tsan/rtl/tsan_stat.cc index 3fa8a03ee19..4bfc9625a0f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.cc @@ -234,6 +234,7 @@ void StatOutput(u64 *stat) { name[StatInt_usleep] = " usleep "; name[StatInt_nanosleep] = " nanosleep "; name[StatInt_gettimeofday] = " gettimeofday "; + name[StatInt_fork] = " fork "; name[StatAnnotation] = "Dynamic annotations "; name[StatAnnotateHappensBefore] = " HappensBefore "; diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.h b/compiler-rt/lib/tsan/rtl/tsan_stat.h index 64b12a6628f..9c3c95aa221 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.h +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.h @@ -233,6 +233,7 @@ enum StatType { StatInt_usleep, StatInt_nanosleep, StatInt_gettimeofday, + StatInt_fork, // Dynamic annotations. StatAnnotation, diff --git a/compiler-rt/lib/tsan/rtl/tsan_sync.cc b/compiler-rt/lib/tsan/rtl/tsan_sync.cc index 38ecc6e8c5f..8951325462e 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_sync.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_sync.cc @@ -60,6 +60,9 @@ SyncVar* SyncTab::GetIfExistsAndLock(uptr addr, bool write_lock) { SyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc, uptr addr, bool write_lock, bool create) { #ifndef TSAN_GO + // Here we ask only PrimaryAllocator, because + // SecondaryAllocator::PointerIsMine() is slow and we have fallback on + // the hashmap anyway. if (PrimaryAllocator::PointerIsMine((void*)addr)) { MBlock *b = user_mblock(thr, (void*)addr); Lock l(&b->mtx); |