[llvm] r210937 - Make the error-handling functions thread-safe.

Zachary Turner zturner at google.com
Fri Jun 13 14:20:44 PDT 2014


Author: zturner
Date: Fri Jun 13 16:20:44 2014
New Revision: 210937

URL: http://llvm.org/viewvc/llvm-project?rev=210937&view=rev
Log:
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

Modified:
    llvm/trunk/include/llvm/Support/ErrorHandling.h
    llvm/trunk/lib/Support/ErrorHandling.cpp

Modified: llvm/trunk/include/llvm/Support/ErrorHandling.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ErrorHandling.h?rev=210937&r1=210936&r2=210937&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/ErrorHandling.h (original)
+++ llvm/trunk/include/llvm/Support/ErrorHandling.h Fri Jun 13 16:20:44 2014
@@ -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

Modified: llvm/trunk/lib/Support/ErrorHandling.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/ErrorHandling.cpp?rev=210937&r1=210936&r2=210937&view=diff
==============================================================================
--- llvm/trunk/lib/Support/ErrorHandling.cpp (original)
+++ llvm/trunk/lib/Support/ErrorHandling.cpp Fri Jun 13 16:20:44 2014
@@ -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
 }
 
 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





More information about the llvm-commits mailing list