summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2014-06-13 21:20:44 +0000
committerZachary Turner <zturner@google.com>2014-06-13 21:20:44 +0000
commit89e90b25e3c9a0a20a6789b81d2a831ba9e8959e (patch)
treed6317ef970ddf9c0728424ba49ba2f637c211580
parent6140939365cb1d23a7f8ab99b6b30650d41dac42 (diff)
downloadllvm-89e90b25e3c9a0a20a6789b81d2a831ba9e8959e.tar.gz
llvm-89e90b25e3c9a0a20a6789b81d2a831ba9e8959e.tar.bz2
llvm-89e90b25e3c9a0a20a6789b81d2a831ba9e8959e.tar.xz
Make the error-handling functions thread-safe.
Prior to this change, error handling functions must be installed and removed only inside of an llvm_[start/stop]_multithreading pair. This change allows error handling functions to be installed any time, and from any thread. Reviewed by: chandlerc Differential Revision: http://reviews.llvm.org/D4140 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210937 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Support/ErrorHandling.h5
-rw-r--r--lib/Support/ErrorHandling.cpp23
2 files changed, 19 insertions, 9 deletions
diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h
index ac3a4d8646..9afd52d1ab 100644
--- a/include/llvm/Support/ErrorHandling.h
+++ b/include/llvm/Support/ErrorHandling.h
@@ -30,9 +30,6 @@ namespace llvm {
/// install_fatal_error_handler - Installs a new error handler to be used
/// whenever a serious (non-recoverable) error is encountered by LLVM.
///
- /// If you are using llvm_start_multithreaded, you should register the handler
- /// before doing that.
- ///
/// If no error handler is installed the default is to print the error message
/// to stderr, and call exit(1). If an error handler is installed then it is
/// the handler's responsibility to log the message, it will no longer be
@@ -50,8 +47,6 @@ namespace llvm {
void *user_data = nullptr);
/// Restores default error handling behaviour.
- /// This must not be called between llvm_start_multithreaded() and
- /// llvm_stop_multithreaded().
void remove_fatal_error_handler();
/// ScopedFatalErrorHandler - This is a simple helper class which just
diff --git a/lib/Support/ErrorHandling.cpp b/lib/Support/ErrorHandling.cpp
index 342c4f05cc..ae1d64db4b 100644
--- a/lib/Support/ErrorHandling.cpp
+++ b/lib/Support/ErrorHandling.cpp
@@ -19,6 +19,8 @@
#include "llvm/Config/config.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
@@ -37,17 +39,20 @@ using namespace llvm;
static fatal_error_handler_t ErrorHandler = nullptr;
static void *ErrorHandlerUserData = nullptr;
+static sys::Mutex ErrorHandlerMutex;
+
void llvm::install_fatal_error_handler(fatal_error_handler_t handler,
void *user_data) {
- assert(!llvm_is_multithreaded() &&
- "Cannot register error handlers after starting multithreaded mode!\n");
+ llvm::MutexGuard Lock(ErrorHandlerMutex);
assert(!ErrorHandler && "Error handler already registered!\n");
ErrorHandler = handler;
ErrorHandlerUserData = user_data;
}
void llvm::remove_fatal_error_handler() {
+ llvm::MutexGuard Lock(ErrorHandlerMutex);
ErrorHandler = nullptr;
+ ErrorHandlerUserData = nullptr;
}
void llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) {
@@ -63,8 +68,18 @@ void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) {
}
void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
- if (ErrorHandler) {
- ErrorHandler(ErrorHandlerUserData, Reason.str(), GenCrashDiag);
+ llvm::fatal_error_handler_t handler = nullptr;
+ void* handlerData = nullptr;
+ {
+ // Only acquire the mutex while reading the handler, so as not to invoke a
+ // user-supplied callback under a lock.
+ llvm::MutexGuard Lock(ErrorHandlerMutex);
+ handler = ErrorHandler;
+ handlerData = ErrorHandlerUserData;
+ }
+
+ if (handler) {
+ handler(handlerData, Reason.str(), GenCrashDiag);
} else {
// Blast the result out to stderr. We don't try hard to make sure this
// succeeds (e.g. handling EINTR) and we can't use errs() here because