Fix race with host_dlopen_handles_
Thread 1 opens an already opened oat file.
Thread 2 dlcloses the oat file and removes it from
host_dlopen_handles_.
Thread 1 checks that it is not already in host_dlopen_handles_ and
proceeds to return the oat file. The problem now is that the BSS is
not cleared since it is the same oat file that was opened earlier.
The fix is to just hold the lock for dlopen / dlclose. This only
affects contention on host.
Bug: 28992179
Bug: 28990799
Bug: 28826195
Change-Id: I126e3d4da69f493b21604205eeea75352a6cf736
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 995ea99..62c723e 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -500,11 +500,12 @@
~DlOpenOatFile() {
if (dlopen_handle_ != nullptr) {
- dlclose(dlopen_handle_);
-
if (!kIsTargetBuild) {
MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
host_dlopen_handles_.erase(dlopen_handle_);
+ dlclose(dlopen_handle_);
+ } else {
+ dlclose(dlopen_handle_);
}
}
}
@@ -660,9 +661,9 @@
#else
UNUSED(oat_file_begin);
static_assert(!kIsTargetBuild, "host_dlopen_handles_ will leak handles");
+ MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
if (dlopen_handle_ != nullptr) {
- MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
dlclose(dlopen_handle_);
dlopen_handle_ = nullptr;