summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2015-06-19 10:59:28 -0400
committerAndy Schwerin <schwerin@mongodb.com>2015-06-22 16:18:37 -0400
commit65ba4d4d7ebd027141cb96f3252a2271b37b7705 (patch)
tree22a22753103f2faf2665a766bb4f50a9f3795f25 /src
parent7926b2f51f3daeda2a0694ce6701909b3a6e4f16 (diff)
downloadmongo-65ba4d4d7ebd027141cb96f3252a2271b37b7705.tar.gz
SERVER-19046 Make myTerminate call quickExit when re-entered by a single thread.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/util/signal_handlers_synchronous.cpp56
1 files changed, 38 insertions, 18 deletions
diff --git a/src/mongo/util/signal_handlers_synchronous.cpp b/src/mongo/util/signal_handlers_synchronous.cpp
index d2fb677a0f3..65531c51fcc 100644
--- a/src/mongo/util/signal_handlers_synchronous.cpp
+++ b/src/mongo/util/signal_handlers_synchronous.cpp
@@ -47,6 +47,7 @@
#include "mongo/logger/logger.h"
#include "mongo/stdx/thread.h"
#include "mongo/util/concurrency/thread_name.h"
+#include "mongo/util/concurrency/threadlocal.h"
#include "mongo/util/debug_util.h"
#include "mongo/util/debugger.h"
#include "mongo/util/exception_filter_win32.h"
@@ -112,26 +113,45 @@ private:
MallocFreeOStream mallocFreeOStream;
-// This guards mallocFreeOStream. While locking a pthread_mutex isn't guaranteed to be
-// signal-safe, this file does it anyway. The assumption is that the main safety risk to locking
-// a mutex is that you could deadlock with yourself. That risk is protected against by only
-// locking the mutex in fatal functions that log then exit. There is a remaining risk that one
-// of these functions recurses (possible if logging segfaults while handing a segfault). This is
-// currently acceptable because if things are that broken, there is little we can do about it.
-//
-// If in the future, we decide to be more strict about posix signal safety, we could switch to
-// an atomic test-and-set loop, possibly with a mechanism for detecting signals raised while
-// handling other signals.
-stdx::mutex streamMutex;
-
-// must hold streamMutex to call
+/**
+ * Instances of this type guard the mallocFreeOStream. While locking a mutex isn't guaranteed to
+ * be signal-safe, this file does it anyway. The assumption is that the main safety risk to
+ * locking a mutex is that you could deadlock with yourself. That risk is protected against by
+ * only locking the mutex in fatal functions that log then exit. There is a remaining risk that
+ * one of these functions recurses (possible if logging segfaults while handing a
+ * segfault). This is currently acceptable because if things are that broken, there is little we
+ * can do about it.
+ *
+ * If in the future, we decide to be more strict about posix signal safety, we could switch to
+ * an atomic test-and-set loop, possibly with a mechanism for detecting signals raised while
+ * handling other signals.
+ */
+class MallocFreeOStreamGuard {
+public:
+ explicit MallocFreeOStreamGuard() : _lk(_streamMutex, stdx::defer_lock) {
+ if (terminateDepth++) {
+ quickExit(EXIT_ABRUPT);
+ }
+ _lk.lock();
+ }
+
+private:
+ static stdx::mutex _streamMutex;
+ static MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL int terminateDepth;
+ stdx::unique_lock<stdx::mutex> _lk;
+};
+stdx::mutex MallocFreeOStreamGuard::_streamMutex;
+MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL
+int MallocFreeOStreamGuard::terminateDepth = 0;
+
+// must hold MallocFreeOStreamGuard to call
void writeMallocFreeStreamToLog() {
logger::globalLogDomain()->append(logger::MessageEventEphemeral(
Date_t::now(), logger::LogSeverity::Severe(), getThreadName(), mallocFreeOStream.str()));
mallocFreeOStream.rewind();
}
-// must hold streamMutex to call
+// must hold MallocFreeOStreamGuard to call
void printSignalAndBacktrace(int signalNum) {
mallocFreeOStream << "Got signal: " << signalNum << " (" << strsignal(signalNum) << ").\n";
printStackTrace(mallocFreeOStream);
@@ -141,7 +161,7 @@ void printSignalAndBacktrace(int signalNum) {
// this will be called in certain c++ error cases, for example if there are two active
// exceptions
void myTerminate() {
- stdx::lock_guard<stdx::mutex> lk(streamMutex);
+ MallocFreeOStreamGuard lk{};
// In c++11 we can recover the current exception to print it.
if (std::exception_ptr eptr = std::current_exception()) {
@@ -195,7 +215,7 @@ void myTerminate() {
}
void abruptQuit(int signalNum) {
- stdx::lock_guard<stdx::mutex> lk(streamMutex);
+ MallocFreeOStreamGuard lk{};
printSignalAndBacktrace(signalNum);
// Don't go through normal shutdown procedure. It may make things worse.
@@ -233,7 +253,7 @@ void myPureCallHandler() {
#else
void abruptQuitWithAddrSignal(int signalNum, siginfo_t* siginfo, void*) {
- stdx::lock_guard<stdx::mutex> lk(streamMutex);
+ MallocFreeOStreamGuard lk{};
const char* action = (signalNum == SIGSEGV || signalNum == SIGBUS) ? "access" : "operation";
mallocFreeOStream << "Invalid " << action << " at address: " << siginfo->si_addr;
@@ -287,7 +307,7 @@ void setupSynchronousSignalHandlers() {
}
void reportOutOfMemoryErrorAndExit() {
- stdx::lock_guard<stdx::mutex> lk(streamMutex);
+ MallocFreeOStreamGuard lk{};
printStackTrace(mallocFreeOStream << "out of memory.\n");
writeMallocFreeStreamToLog();
quickExit(EXIT_ABRUPT);