Fix test, also do not read from stack of another thread
authorTudor Bosman <tudorb@fb.com>
Thu, 12 Dec 2013 23:08:05 +0000 (15:08 -0800)
committerJordan DeLong <jdelong@fb.com>
Fri, 20 Dec 2013 21:06:15 +0000 (13:06 -0800)
Summary:
... even though Google's signal handler does it
(https://code.google.com/p/google-glog/source/browse/trunk/src/signalhandler.cc?r=16#235)

Assuming the existence of an invalid pthread_t is a lesser evil than reading
from another thread's stack, IMO.

Test Plan: folly/experimental/symbolizer/test

Reviewed By: simpkins@fb.com

FB internal diff: D1096620

folly/experimental/symbolizer/SignalHandler.cpp
folly/experimental/symbolizer/test/SignalHandlerTest.cpp

index d19cc973ce9823989ad8ddde00cfd6d420e02c77..8346e79bea31ff5420882b64d993033951ce030d 100644 (file)
@@ -206,16 +206,22 @@ void dumpStackTrace() {
   }
 }
 
-std::atomic<pthread_t*> gSignalThread;
+// On Linux, pthread_t is a pointer, so 0 is an invalid value, which we
+// take to indicate "no thread in the signal handler".
+//
+// POSIX defines PTHREAD_NULL for this purpose, but that's not available.
+constexpr pthread_t kInvalidThreadId = 0;
+
+std::atomic<pthread_t> gSignalThread(kInvalidThreadId);
 
 // Here be dragons.
 void innerSignalHandler(int signum, siginfo_t* info, void* uctx) {
   // First, let's only let one thread in here at a time.
   pthread_t myId = pthread_self();
 
-  pthread_t* prevSignalThread = nullptr;
-  while (!gSignalThread.compare_exchange_strong(prevSignalThread, &myId)) {
-    if (pthread_equal(*prevSignalThread, myId)) {
+  pthread_t prevSignalThread = kInvalidThreadId;
+  while (!gSignalThread.compare_exchange_strong(prevSignalThread, myId)) {
+    if (pthread_equal(prevSignalThread, myId)) {
       print("Entered fatal signal handler recursively. We're in trouble.\n");
       return;
     }
@@ -226,7 +232,7 @@ void innerSignalHandler(int signum, siginfo_t* info, void* uctx) {
     ts.tv_nsec = 100L * 1000 * 1000;  // 100ms
     nanosleep(&ts, nullptr);
 
-    prevSignalThread = nullptr;
+    prevSignalThread = kInvalidThreadId;
   }
 
   dumpTimeInfo();
@@ -241,7 +247,7 @@ void signalHandler(int signum, siginfo_t* info, void* uctx) {
   SCOPE_EXIT { fsyncNoInt(STDERR_FILENO); };
   innerSignalHandler(signum, info, uctx);
 
-  gSignalThread = nullptr;
+  gSignalThread = kInvalidThreadId;
   // Kill ourselves with the previous handler.
   callPreviousSignalHandler(signum);
 }
index 89f8159106b025721eef09af289d73e18123a6f5..db58708d191f32f3a0e03c105155c3ad7729acd2 100644 (file)
@@ -45,6 +45,7 @@ TEST(SignalHandler, Simple) {
   addFatalSignalCallback(callback1);
   addFatalSignalCallback(callback2);
   installFatalSignalHandler();
+  installFatalSignalCallbacks();
 
   EXPECT_DEATH(
       failHard(),