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
(cherry picked from commit c7d3f4b8c294f36209ea2c129f9714a36ae1ec6b)
Change-Id: Ib462720fab26427d8ca0c6323080604878edb8b5
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d2e23aa..b369e10 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2092,6 +2092,21 @@
reinterpret_cast<ArtMethod**>(raw_arrays + layout.MethodsOffset());
ArtField** fields = (dex_file.NumFieldIds() == 0u) ? nullptr :
reinterpret_cast<ArtField**>(raw_arrays + layout.FieldsOffset());
+ if (kIsDebugBuild) {
+ // Sanity check to make sure all the dex cache arrays are empty. b/28992179
+ for (size_t i = 0; i < dex_file.NumStringIds(); ++i) {
+ CHECK(strings[i].Read<kWithoutReadBarrier>() == nullptr);
+ }
+ for (size_t i = 0; i < dex_file.NumTypeIds(); ++i) {
+ CHECK(types[i].Read<kWithoutReadBarrier>() == nullptr);
+ }
+ for (size_t i = 0; i < dex_file.NumMethodIds(); ++i) {
+ CHECK(mirror::DexCache::GetElementPtrSize(methods, i, image_pointer_size_) == nullptr);
+ }
+ for (size_t i = 0; i < dex_file.NumFieldIds(); ++i) {
+ CHECK(mirror::DexCache::GetElementPtrSize(fields, i, image_pointer_size_) == nullptr);
+ }
+ }
dex_cache->Init(&dex_file,
location.Get(),
strings,