[llvm-commits] [compiler-rt] r157178 - in /compiler-rt/trunk/lib/tsan/rtl: tsan_interceptors.cc tsan_rtl.h tsan_stat.h

Dmitry Vyukov dvyukov at google.com
Mon May 21 01:26:51 PDT 2012


Author: dvyukov
Date: Mon May 21 03:26:51 2012
New Revision: 157178

URL: http://llvm.org/viewvc/llvm-project?rev=157178&view=rev
Log:
tsan: better, more realistic handling of signals

Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h

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=157178&r1=157177&r2=157178&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Mon May 21 03:26:51 2012
@@ -52,6 +52,12 @@
 const int EINVAL = 22;
 const int EBUSY = 16;
 const int EPOLL_CTL_ADD = 1;
+const int SIGILL = 4;
+const int SIGABRT = 6;
+const int SIGFPE = 8;
+const int SIGSEGV = 11;
+const int SIGPIPE = 13;
+const int SIGBUS = 7;
 void *const MAP_FAILED = (void*)-1;
 const int PTHREAD_BARRIER_SERIAL_THREAD = -1;
 const int MAP_FIXED = 0x10;
@@ -76,6 +82,7 @@
 
 const sighandler_t SIG_DFL = (sighandler_t)0;
 const sighandler_t SIG_IGN = (sighandler_t)1;
+const sighandler_t SIG_ERR = (sighandler_t)-1;
 const int SA_SIGINFO = 4;
 const int SIG_SETMASK = 2;
 
@@ -1138,40 +1145,109 @@
   return res;
 }
 
-static void rtl_sighandler(int sig) {
+static void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
+    my_siginfo_t *info, void *ctx) {
   ThreadState *thr = cur_thread();
+  // Don't mess with synchronous signals.
+  if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGABRT ||
+      sig == SIGFPE || sig == SIGPIPE || sig == thr->int_signal_send) {
+    CHECK(thr->in_rtl == 0 || thr->in_rtl == 1);
+    int in_rtl = thr->in_rtl;
+    thr->in_rtl = 0;
+    CHECK_EQ(thr->in_signal_handler, false);
+    thr->in_signal_handler = true;
+    if (sigact)
+      sigactions[sig].sa_sigaction(sig, info, ctx);
+    else
+      sigactions[sig].sa_handler(sig);
+    CHECK_EQ(thr->in_signal_handler, true);
+    thr->in_signal_handler = false;
+    thr->in_rtl = in_rtl;
+    return;
+  }
+
   SignalDesc *signal = &thr->pending_signals[sig];
   if (signal->armed == false) {
     signal->armed = true;
-    signal->sigaction = false;
+    signal->sigaction = sigact;
+    if (info)
+      signal->siginfo = *info;
     thr->pending_signal_count++;
   }
 }
 
+static void rtl_sighandler(int sig) {
+  rtl_generic_sighandler(false, sig, 0, 0);
+}
+
 static void rtl_sigaction(int sig, my_siginfo_t *info, void *ctx) {
-  ThreadState *thr = cur_thread();
-  SignalDesc *signal = &thr->pending_signals[sig];
-  if (signal->armed == false) {
-    signal->armed = true;
-    signal->sigaction = true;
-    signal->siginfo = *info;
-    thr->pending_signal_count++;
-  }
+  rtl_generic_sighandler(true, sig, info, ctx);
 }
 
 TSAN_INTERCEPTOR(int, sigaction, int sig, sigaction_t *act, sigaction_t *old) {
   SCOPED_TSAN_INTERCEPTOR(sigaction, sig, act, old);
-  int res = 0;
-  if (act == 0 || act->sa_handler == SIG_IGN || act->sa_handler == SIG_DFL) {
-    res = REAL(sigaction)(sig, act, old);
-  } else {
-    sigactions[sig] = *act;
-    sigaction_t newact = *act;
+  if (old)
+    *old = sigactions[sig];
+  if (act == 0)
+    return 0;
+  sigactions[sig] = *act;
+  sigaction_t newact = *act;
+  if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) {
     if (newact.sa_flags & SA_SIGINFO)
       newact.sa_sigaction = rtl_sigaction;
     else
       newact.sa_handler = rtl_sighandler;
-    res = REAL(sigaction)(sig, &newact, old);
+  }
+  int res = REAL(sigaction)(sig, &newact, 0);
+  return res;
+}
+
+TSAN_INTERCEPTOR(sighandler_t, signal, int sig, sighandler_t h) {
+  sigaction_t act = {};
+  act.sa_handler = h;
+  internal_memset(&act.sa_mask, -1, sizeof(act.sa_mask));
+  act.sa_flags = 0;
+  sigaction_t old = {};
+  int res = sigaction(sig, &act, &old);
+  if (res)
+    return SIG_ERR;
+  return old.sa_handler;
+}
+
+TSAN_INTERCEPTOR(int, raise, int sig) {
+  SCOPED_TSAN_INTERCEPTOR(raise, sig);
+  CHECK_EQ(thr->int_signal_send, 0);
+  thr->int_signal_send = sig;
+  int res = REAL(raise)(sig);
+  CHECK_EQ(thr->int_signal_send, sig);
+  thr->int_signal_send = 0;
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
+  SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
+  if (pid == GetPid()) {
+    CHECK_EQ(thr->int_signal_send, 0);
+    thr->int_signal_send = sig;
+  }
+  int res = REAL(kill)(pid, sig);
+  if (pid == GetPid()) {
+    CHECK_EQ(thr->int_signal_send, sig);
+    thr->int_signal_send = 0;
+  }
+  return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
+  SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
+  if (tid == pthread_self()) {
+    CHECK_EQ(thr->int_signal_send, 0);
+    thr->int_signal_send = sig;
+  }
+  int res = REAL(pthread_kill)(tid, sig);
+  if (tid == pthread_self()) {
+    CHECK_EQ(thr->int_signal_send, sig);
+    thr->int_signal_send = 0;
   }
   return res;
 }
@@ -1180,6 +1256,7 @@
   CHECK_EQ(thr->in_rtl, 0);
   if (thr->pending_signal_count == 0 || thr->in_signal_handler)
     return;
+  CHECK_EQ(thr->in_signal_handler, false);
   thr->in_signal_handler = true;
   thr->pending_signal_count = 0;
   // These are too big for stack.
@@ -1192,10 +1269,13 @@
     SignalDesc *signal = &thr->pending_signals[sig];
     if (signal->armed) {
       signal->armed = false;
-      if (signal->sigaction)
-        sigactions[sig].sa_sigaction(sig, &signal->siginfo, &uctx);
-      else
-        sigactions[sig].sa_handler(sig);
+      if (sigactions[sig].sa_handler != SIG_DFL
+          && sigactions[sig].sa_handler != SIG_IGN) {
+        if (signal->sigaction)
+          sigactions[sig].sa_sigaction(sig, &signal->siginfo, &uctx);
+        else
+          sigactions[sig].sa_handler(sig);
+      }
     }
   }
   pthread_sigmask(SIG_SETMASK, &oldset, 0);
@@ -1341,6 +1421,10 @@
   TSAN_INTERCEPT(epoll_wait);
 
   TSAN_INTERCEPT(sigaction);
+  TSAN_INTERCEPT(signal);
+  TSAN_INTERCEPT(raise);
+  TSAN_INTERCEPT(kill);
+  TSAN_INTERCEPT(pthread_kill);
 
   atexit_ctx = new(internal_alloc(MBlockAtExit, sizeof(AtExitContext)))
       AtExitContext();

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=157178&r1=157177&r2=157178&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Mon May 21 03:26:51 2012
@@ -257,6 +257,7 @@
   DeadlockDetector deadlock_detector;
 
   bool in_signal_handler;
+  int int_signal_send;
   int pending_signal_count;
   SignalDesc pending_signals[kSigCount];
 

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=157178&r1=157177&r2=157178&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Mon May 21 03:26:51 2012
@@ -193,6 +193,10 @@
   StatInt_epoll_ctl,
   StatInt_epoll_wait,
   StatInt_sigaction,
+  StatInt_signal,
+  StatInt_raise,
+  StatInt_kill,
+  StatInt_pthread_kill,
 
   // Dynamic annotations.
   StatAnnotation,





More information about the llvm-commits mailing list