Fix Reactor memory leaks
LLVM has a known leak, which is addressed by this patch:
https://reviews.llvm.org/. With this patch, and making sure that
llvm::shutdown() is called, AppVerifier on Windows, and LSAN on Linux,
report no more load/unload leaks.
Bug: b/175782868
Bug: chromium:972686
Bug: angleproject:5377
Change-Id: If34a00c3a4b845604445f22bdb5889f51bb5a1d6
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52168
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index bcb5416..18b0c16 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -27,6 +27,7 @@
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/Alignment.h"
+#include "llvm/Support/ManagedStatic.h"
#include "llvm/Transforms/Coroutines.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
@@ -57,6 +58,9 @@
namespace {
+// Used to automatically invoke llvm_shutdown() when driver is unloaded
+llvm::llvm_shutdown_obj llvmShutdownObj;
+
// This has to be a raw pointer because glibc 2.17 doesn't support __cxa_thread_atexit_impl
// for destructing objects at exit. See crbug.com/1074222
thread_local rr::JITBuilder *jit = nullptr;
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index ce4475e..fe53ad7 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -32,6 +32,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_os_ostream.h"
#include "marl/event.h"
@@ -215,6 +216,9 @@
namespace {
+// Used to automatically invoke llvm_shutdown() when driver is unloaded
+llvm::llvm_shutdown_obj llvmShutdownObj;
+
// Default configuration settings. Must be accessed under mutex lock.
std::mutex defaultConfigLock;
rr::Config &defaultConfig()
diff --git a/third_party/llvm-10.0/llvm/lib/Support/ManagedStatic.cpp b/third_party/llvm-10.0/llvm/lib/Support/ManagedStatic.cpp
index 053493f..bfa7e8e 100644
--- a/third_party/llvm-10.0/llvm/lib/Support/ManagedStatic.cpp
+++ b/third_party/llvm-10.0/llvm/lib/Support/ManagedStatic.cpp
@@ -21,6 +21,8 @@
static std::recursive_mutex *ManagedStaticMutex = nullptr;
static llvm::once_flag mutex_init_flag;
+#if 0
+
static void initializeMutex() {
ManagedStaticMutex = new std::recursive_mutex();
}
@@ -30,6 +32,16 @@
return ManagedStaticMutex;
}
+#else
+
+// SwiftShader: from https://reviews.llvm.org/D83372
+static std::recursive_mutex *getManagedStaticMutex() {
+ static std::recursive_mutex m;
+ return &m;
+}
+
+#endif
+
void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
void (*Deleter)(void*)) const {
assert(Creator);
@@ -76,7 +88,11 @@
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
void llvm::llvm_shutdown() {
- std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
+ // SwiftShader: from https://reviews.llvm.org/D83372
+ // This may be called after the mutex is destroyed. Instead of fixing this,
+ // don't bother locking the mutex, and require llvm_shutdown to be called from
+ // exactly one thread.
+ // std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
while (StaticList)
StaticList->destroy();
diff --git a/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
index 97e7470..34958a2 100644
--- a/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
+++ b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
@@ -21,6 +21,8 @@
static std::recursive_mutex *ManagedStaticMutex = nullptr;
LLVM_DEFINE_ONCE_FLAG(mutex_init_flag);
+#if 0
+
static void initializeMutex() {
ManagedStaticMutex = new std::recursive_mutex();
}
@@ -33,6 +35,16 @@
return ManagedStaticMutex;
}
+#else
+
+// SwiftShader: from https://reviews.llvm.org/D83372
+static std::recursive_mutex *getManagedStaticMutex() {
+ static std::recursive_mutex m;
+ return &m;
+}
+
+#endif
+
void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
void (*Deleter)(void*)) const {
assert(Creator);
@@ -68,7 +80,11 @@
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
void llvm::llvm_shutdown() {
- std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
+ // SwiftShader: from https://reviews.llvm.org/D83372
+ // This may be called after the mutex is destroyed. Instead of fixing this,
+ // don't bother locking the mutex, and require llvm_shutdown to be called from
+ // exactly one thread.
+ // std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
while (StaticList)
StaticList->destroy();