diff options
author | Zachary Turner <zturner@google.com> | 2014-06-13 21:20:44 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2014-06-13 21:20:44 +0000 |
commit | 89e90b25e3c9a0a20a6789b81d2a831ba9e8959e (patch) | |
tree | d6317ef970ddf9c0728424ba49ba2f637c211580 | |
parent | 6140939365cb1d23a7f8ab99b6b30650d41dac42 (diff) | |
download | llvm-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.h | 5 | ||||
-rw-r--r-- | lib/Support/ErrorHandling.cpp | 23 |
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 |