From 262465c12666e9d5165505301ce5919b5e638269 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 15 Nov 2012 17:40:49 +0000 Subject: [PATCH] tsan: eevn better handling of signals add interceptor for poll() in addition process signals in every atomic op in addition process signals in blocking libc functions llvm-svn: 168050 --- compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 68 ++++++++++++++++------- compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc | 1 + compiler-rt/lib/tsan/rtl/tsan_rtl.h | 1 + compiler-rt/lib/tsan/rtl/tsan_stat.cc | 1 + compiler-rt/lib/tsan/rtl/tsan_stat.h | 1 + 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index e8aa7d5..af92912 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -115,6 +115,7 @@ struct SignalDesc { }; struct SignalContext { + int in_blocking_func; int int_signal_send; int pending_signal_count; SignalDesc pending_signals[kSigCount]; @@ -136,8 +137,6 @@ static SignalContext *SigCtx(ThreadState *thr) { static unsigned g_thread_finalize_key; -static void process_pending_signals(ThreadState *thr); - ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc) : thr_(thr) @@ -156,28 +155,45 @@ ScopedInterceptor::~ScopedInterceptor() { thr_->in_rtl--; if (thr_->in_rtl == 0) { FuncExit(thr_); - process_pending_signals(thr_); + ProcessPendingSignals(thr_); } CHECK_EQ(in_rtl_, thr_->in_rtl); } +#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name)) + +struct BlockingCall { + BlockingCall(ThreadState *thr) + : ctx(SigCtx(thr)) { + CHECK_EQ(ctx->in_blocking_func, 0); + ctx->in_blocking_func++; + } + + ~BlockingCall() { + ctx->in_blocking_func--; + CHECK_EQ(ctx->in_blocking_func, 0); + } + + SignalContext *ctx; +}; + TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) { SCOPED_TSAN_INTERCEPTOR(sleep, sec); - unsigned res = sleep(sec); + unsigned res = BLOCK_REAL(sleep)(sec); AfterSleep(thr, pc); return res; } TSAN_INTERCEPTOR(int, usleep, long_t usec) { SCOPED_TSAN_INTERCEPTOR(usleep, usec); - int res = usleep(usec); + int res = BLOCK_REAL(usleep)(usec); AfterSleep(thr, pc); return res; } TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) { SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem); - int res = nanosleep(req, rem); + int res = BLOCK_REAL(nanosleep)(req, rem); AfterSleep(thr, pc); return res; } @@ -677,7 +693,7 @@ TSAN_INTERCEPTOR(int, pthread_create, TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) { SCOPED_TSAN_INTERCEPTOR(pthread_join, th, ret); int tid = ThreadTid(thr, pc, (uptr)th); - int res = REAL(pthread_join)(th, ret); + int res = BLOCK_REAL(pthread_join)(th, ret); if (res == 0) { ThreadJoin(thr, pc, tid); } @@ -980,7 +996,7 @@ TSAN_INTERCEPTOR(int, sem_destroy, void *s) { TSAN_INTERCEPTOR(int, sem_wait, void *s) { SCOPED_TSAN_INTERCEPTOR(sem_wait, s); - int res = REAL(sem_wait)(s); + int res = BLOCK_REAL(sem_wait)(s); if (res == 0) { Acquire(thr, pc, (uptr)s); } @@ -989,7 +1005,7 @@ TSAN_INTERCEPTOR(int, sem_wait, void *s) { TSAN_INTERCEPTOR(int, sem_trywait, void *s) { SCOPED_TSAN_INTERCEPTOR(sem_trywait, s); - int res = REAL(sem_trywait)(s); + int res = BLOCK_REAL(sem_trywait)(s); if (res == 0) { Acquire(thr, pc, (uptr)s); } @@ -998,7 +1014,7 @@ TSAN_INTERCEPTOR(int, sem_trywait, void *s) { TSAN_INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) { SCOPED_TSAN_INTERCEPTOR(sem_timedwait, s, abstime); - int res = REAL(sem_timedwait)(s, abstime); + int res = BLOCK_REAL(sem_timedwait)(s, abstime); if (res == 0) { Acquire(thr, pc, (uptr)s); } @@ -1190,13 +1206,19 @@ TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) { SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout); - int res = REAL(epoll_wait)(epfd, ev, cnt, timeout); + int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout); if (res > 0) { Acquire(thr, pc, epollfd2addr(epfd)); } return res; } +TSAN_INTERCEPTOR(int, poll, void *fds, long_t nfds, int timeout) { + SCOPED_TSAN_INTERCEPTOR(poll, fds, nfds, timeout); + int res = BLOCK_REAL(poll)(fds, nfds, timeout); + return res; +} + static void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig, my_siginfo_t *info, void *ctx) { ThreadState *thr = cur_thread(); @@ -1204,7 +1226,10 @@ static void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig, // Don't mess with synchronous signals. if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || - (sctx && sig == sctx->int_signal_send)) { + // If we are sending signal to ourselves, we must process it now. + (sctx && sig == sctx->int_signal_send) || + // If we are in blocking function, we can safely process it now. + (sctx && sctx->in_blocking_func)) { CHECK(thr->in_rtl == 0 || thr->in_rtl == 1); int in_rtl = thr->in_rtl; thr->in_rtl = 0; @@ -1318,7 +1343,15 @@ TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) { return res; } -static void process_pending_signals(ThreadState *thr) { +TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) { + SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz); + // It's intercepted merely to process pending signals. + return REAL(gettimeofday)(tv, tz); +} + +namespace __tsan { + +void ProcessPendingSignals(ThreadState *thr) { CHECK_EQ(thr->in_rtl, 0); SignalContext *sctx = SigCtx(thr); if (sctx == 0 || sctx->pending_signal_count == 0 || thr->in_signal_handler) @@ -1365,14 +1398,6 @@ static void process_pending_signals(ThreadState *thr) { thr->in_signal_handler = false; } -TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) { - SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz); - // It's intercepted merely to process pending signals. - return REAL(gettimeofday)(tv, tz); -} - -namespace __tsan { - void InitializeInterceptors() { CHECK_GT(cur_thread()->in_rtl, 0); @@ -1489,6 +1514,7 @@ void InitializeInterceptors() { TSAN_INTERCEPT(epoll_ctl); TSAN_INTERCEPT(epoll_wait); + TSAN_INTERCEPT(poll); TSAN_INTERCEPT(sigaction); TSAN_INTERCEPT(signal); diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc index c29f23e..89b0e15 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc @@ -104,6 +104,7 @@ static morder ConvertOrder(morder mo) { mo = ConvertOrder(mo); \ mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \ ThreadState *const thr = cur_thread(); \ + ProcessPendingSignals(thr); \ const uptr pc = (uptr)__builtin_return_address(0); \ AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \ ScopedAtomic sa(thr, pc, __FUNCTION__); \ diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index dc555a6..39ad4a9 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -494,6 +494,7 @@ void ThreadJoin(ThreadState *thr, uptr pc, int tid); void ThreadDetach(ThreadState *thr, uptr pc, int tid); void ThreadFinalize(ThreadState *thr); int ThreadCount(ThreadState *thr); +void ProcessPendingSignals(ThreadState *thr); void MutexCreate(ThreadState *thr, uptr pc, uptr addr, bool rw, bool recursive, bool linker_init); diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.cc b/compiler-rt/lib/tsan/rtl/tsan_stat.cc index d8fbd0c..cb294bf 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.cc @@ -196,6 +196,7 @@ void StatOutput(u64 *stat) { name[StatInt_opendir] = " opendir "; name[StatInt_epoll_ctl] = " epoll_ctl "; name[StatInt_epoll_wait] = " epoll_wait "; + name[StatInt_poll] = " poll "; name[StatInt_sigaction] = " sigaction "; name[StatInt_sleep] = " sleep "; name[StatInt_usleep] = " usleep "; diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.h b/compiler-rt/lib/tsan/rtl/tsan_stat.h index 3b81aca..cf493e6 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.h +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.h @@ -195,6 +195,7 @@ enum StatType { StatInt_opendir, StatInt_epoll_ctl, StatInt_epoll_wait, + StatInt_poll, StatInt_sigaction, StatInt_signal, StatInt_raise, -- 2.7.4