[ORC] Lock ThreadSafeContext during Module destructing in ThreadSafeModule.
authorLang Hames <lhames@gmail.com>
Thu, 27 Sep 2018 20:36:08 +0000 (20:36 +0000)
committerLang Hames <lhames@gmail.com>
Thu, 27 Sep 2018 20:36:08 +0000 (20:36 +0000)
Failure to lock the context can lead to data races if other threads are
operating on other ThreadSafeModules that share the same context.

llvm-svn: 343261

llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h

index c5490a0..f763b9b 100644 (file)
@@ -102,15 +102,29 @@ public:
   /// unique_ptr<LLVMContext>. This creates a new ThreadSafeContext from the
   /// given context.
   ThreadSafeModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> Ctx)
-      : TSCtx(std::move(Ctx)), M(std::move(M)) {}
+      : M(std::move(M)), TSCtx(std::move(Ctx)) {}
 
+  /// Construct a ThreadSafeModule from a unique_ptr<Module> and an
+  /// existing ThreadSafeContext.
   ThreadSafeModule(std::unique_ptr<Module> M, ThreadSafeContext TSCtx)
-      : TSCtx(std::move(TSCtx)), M(std::move(M)) {}
+      : M(std::move(M)), TSCtx(std::move(TSCtx)) {}
 
+  ~ThreadSafeModule() {
+    // We need to lock the context while we destruct the module.
+    if (M) {
+      auto L = getContextLock();
+      M = nullptr;
+    }
+  }
+
+  /// Get the module wrapped by this ThreadSafeModule.
   Module* getModule() { return M.get(); }
 
+  /// Take out a lock on the ThreadSafeContext for this module.
   ThreadSafeContext::Lock getContextLock() { return TSCtx.getLock(); }
 
+  /// Boolean conversion: This ThreadSafeModule will evaluate to true if it
+  /// wraps a non-null module.
   explicit operator bool() {
     if (M) {
       assert(TSCtx.getContext() && "Non-null module must have non-null context");
@@ -120,8 +134,8 @@ public:
   }
 
 private:
-  ThreadSafeContext TSCtx;
   std::unique_ptr<Module> M;
+  ThreadSafeContext TSCtx;
 };
 
 using GVPredicate = std::function<bool(const GlobalValue&)>;