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
-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();
// 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;
}
print("Entered fatal signal handler recursively. We're in trouble.\n");
return;
}
ts.tv_nsec = 100L * 1000 * 1000; // 100ms
nanosleep(&ts, nullptr);
ts.tv_nsec = 100L * 1000 * 1000; // 100ms
nanosleep(&ts, nullptr);
- prevSignalThread = nullptr;
+ prevSignalThread = kInvalidThreadId;
SCOPE_EXIT { fsyncNoInt(STDERR_FILENO); };
innerSignalHandler(signum, info, uctx);
SCOPE_EXIT { fsyncNoInt(STDERR_FILENO); };
innerSignalHandler(signum, info, uctx);
- gSignalThread = nullptr;
+ gSignalThread = kInvalidThreadId;
// Kill ourselves with the previous handler.
callPreviousSignalHandler(signum);
}
// Kill ourselves with the previous handler.
callPreviousSignalHandler(signum);
}
addFatalSignalCallback(callback1);
addFatalSignalCallback(callback2);
installFatalSignalHandler();
addFatalSignalCallback(callback1);
addFatalSignalCallback(callback2);
installFatalSignalHandler();
+ installFatalSignalCallbacks();
EXPECT_DEATH(
failHard(),
EXPECT_DEATH(
failHard(),