[compiler-rt] r200304 - tsan: relax checking of errno spoiling in signal handlers
Dmitry Vyukov
dvyukov at google.com
Tue Jan 28 01:49:48 PST 2014
Author: dvyukov
Date: Tue Jan 28 03:49:48 2014
New Revision: 200304
URL: http://llvm.org/viewvc/llvm-project?rev=200304&view=rev
Log:
tsan: relax checking of errno spoiling in signal handlers
allow SIGABRT to spoil errno, because some real programs
reset SIGABRT handler in the handler, re-raise SIGABRT and return from the handler
Modified:
compiler-rt/trunk/lib/tsan/lit_tests/signal_errno.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc
Modified: compiler-rt/trunk/lib/tsan/lit_tests/signal_errno.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/signal_errno.cc?rev=200304&r1=200303&r2=200304&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/signal_errno.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/signal_errno.cc Tue Jan 28 03:49:48 2014
@@ -16,10 +16,20 @@ static void MyHandler(int, siginfo_t *s,
}
static void* sendsignal(void *p) {
+ sleep(1);
pthread_kill(mainth, SIGPROF);
return 0;
}
+static __attribute__((noinline)) void loop() {
+ while (done == 0) {
+ volatile char *p = (char*)malloc(1);
+ p[0] = 0;
+ free((void*)p);
+ pthread_yield();
+ }
+}
+
int main() {
mainth = pthread_self();
struct sigaction act = {};
@@ -27,17 +37,14 @@ int main() {
sigaction(SIGPROF, &act, 0);
pthread_t th;
pthread_create(&th, 0, sendsignal, 0);
- while (done == 0) {
- volatile char *p = (char*)malloc(1);
- p[0] = 0;
- free((void*)p);
- pthread_yield();
- }
+ loop();
pthread_join(th, 0);
return 0;
}
// CHECK: WARNING: ThreadSanitizer: signal handler spoils errno
// CHECK: #0 MyHandler(int, siginfo{{(_t)?}}*, void*) {{.*}}signal_errno.cc
+// CHECK: #1 loop
+// CHECK: #2 main
// CHECK: SUMMARY: ThreadSanitizer: signal handler spoils errno{{.*}}MyHandler
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=200304&r1=200303&r2=200304&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Tue Jan 28 03:49:48 2014
@@ -186,8 +186,8 @@ ScopedInterceptor::~ScopedInterceptor()
ThreadIgnoreEnd(thr_, pc_);
}
if (!thr_->ignore_interceptors) {
- FuncExit(thr_);
ProcessPendingSignals(thr_);
+ FuncExit(thr_);
}
}
@@ -1630,23 +1630,24 @@ TSAN_INTERCEPTOR(int, epoll_wait, int ep
namespace __tsan {
-static void CallUserSignalHandler(bool sigact, int sig, my_siginfo_t *info,
- void *uctx) {
+static void CallUserSignalHandler(ThreadState *thr, bool sync, bool sigact,
+ int sig, my_siginfo_t *info, void *uctx) {
// Ensure that the handler does not spoil errno.
const int saved_errno = errno;
- errno = 0;
+ errno = 99;
+ // Need to remember pc before the call, because the handler can reset it.
+ uptr pc = sigact ?
+ (uptr)sigactions[sig].sa_sigaction :
+ (uptr)sigactions[sig].sa_handler;
+ pc += 1; // return address is expected, OutputReport() will undo this
if (sigact)
sigactions[sig].sa_sigaction(sig, info, uctx);
else
sigactions[sig].sa_handler(sig);
- if (flags()->report_bugs && errno != 0) {
+ if (flags()->report_bugs && !sync && errno != 99) {
Context *ctx = CTX();
__tsan::StackTrace stack;
- uptr pc = sigact ?
- (uptr)sigactions[sig].sa_sigaction :
- (uptr)sigactions[sig].sa_handler;
- pc += 1; // return address is expected, OutputReport() will undo this
- stack.Init(&pc, 1);
+ stack.ObtainCurrent(thr, pc);
ThreadRegistryLock l(ctx->thread_registry);
ScopedReport rep(ReportTypeErrnoInSignal);
if (!IsFiredSuppression(ctx, rep, stack)) {
@@ -1673,8 +1674,8 @@ void ProcessPendingSignals(ThreadState *
signal->armed = false;
if (sigactions[sig].sa_handler != SIG_DFL
&& sigactions[sig].sa_handler != SIG_IGN) {
- CallUserSignalHandler(signal->sigaction, sig, &signal->siginfo,
- &signal->ctx);
+ CallUserSignalHandler(thr, false, signal->sigaction,
+ sig, &signal->siginfo, &signal->ctx);
}
}
}
@@ -1685,15 +1686,20 @@ void ProcessPendingSignals(ThreadState *
} // namespace __tsan
+static bool is_sync_signal(SignalContext *sctx, int sig) {
+ return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
+ sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
+ // If we are sending signal to ourselves, we must process it now.
+ (sctx && sig == sctx->int_signal_send);
+}
+
void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
my_siginfo_t *info, void *ctx) {
ThreadState *thr = cur_thread();
SignalContext *sctx = SigCtx(thr);
// Don't mess with synchronous signals.
- if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
- sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
- // If we are sending signal to ourselves, we must process it now.
- (sctx && sig == sctx->int_signal_send) ||
+ const bool sync = is_sync_signal(sctx, sig);
+ if (sync ||
// If we are in blocking function, we can safely process it now
// (but check if we are in a recursive interceptor,
// i.e. pthread_join()->munmap()).
@@ -1705,10 +1711,10 @@ void ALWAYS_INLINE rtl_generic_sighandle
// temporary enbled them again while we are calling user function.
int const i = thr->ignore_interceptors;
thr->ignore_interceptors = 0;
- CallUserSignalHandler(sigact, sig, info, ctx);
+ CallUserSignalHandler(thr, sync, sigact, sig, info, ctx);
thr->ignore_interceptors = i;
} else {
- CallUserSignalHandler(sigact, sig, info, ctx);
+ CallUserSignalHandler(thr, sync, sigact, sig, info, ctx);
}
CHECK_EQ(thr->in_signal_handler, true);
thr->in_signal_handler = false;
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc?rev=200304&r1=200303&r2=200304&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interface_atomic.cc Tue Jan 28 03:49:48 2014
@@ -71,11 +71,11 @@ class ScopedAtomic {
ScopedAtomic(ThreadState *thr, uptr pc, const volatile void *a,
morder mo, const char *func)
: thr_(thr) {
- ProcessPendingSignals(thr);
FuncEntry(thr_, pc);
DPrintf("#%d: %s(%p, %d)\n", thr_->tid, func, a, mo);
}
~ScopedAtomic() {
+ ProcessPendingSignals(thr_);
FuncExit(thr_);
}
private:
More information about the llvm-commits
mailing list