Fix race between dex-file registration and class-loader deletion
We keep track of class-loaders by having a list with jweak references
to the dex-caches. When we register a new dex-file we check that the
dex-cache hasn't already been registered with a different
class-loader. We decoded the jweak and performed this check this
without any locks however meaning we could race with class-loader
cleanup. This could cause CHECK failures as we try to decode a deleted
jweak.
Bug: 147206162
Test: ./art/test/run-test --create-runner --host --prebuild --compact-dex-level fast --optimizing --no-relocate --runtime-option -Xcheck:jni 2001-virtual-structural-multithread
./art/tools/parallel_run.py
Change-Id: Ibeb12ec3d42f7972d09b155b7c24743266897a54
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index f82a7c7..998f739 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -1055,19 +1055,15 @@
ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES(Locks::dex_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- DexCacheData FindDexCacheDataLocked(const DexFile& dex_file)
+ const DexCacheData* FindDexCacheDataLocked(const DexFile& dex_file)
REQUIRES(Locks::dex_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- static ObjPtr<mirror::DexCache> DecodeDexCache(Thread* self, const DexCacheData& data)
- REQUIRES_SHARED(Locks::mutator_lock_);
- // Called to ensure that the dex cache has been registered with the same class loader.
- // If yes, returns the dex cache, otherwise throws InternalError and returns null.
- ObjPtr<mirror::DexCache> EnsureSameClassLoader(Thread* self,
- ObjPtr<mirror::DexCache> dex_cache,
- const DexCacheData& data,
- ObjPtr<mirror::ClassLoader> class_loader)
- REQUIRES(!Locks::dex_lock_)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ static ObjPtr<mirror::DexCache> DecodeDexCacheLocked(Thread* self, const DexCacheData* data)
+ REQUIRES_SHARED(Locks::dex_lock_, Locks::mutator_lock_);
+ bool IsSameClassLoader(ObjPtr<mirror::DexCache> dex_cache,
+ const DexCacheData* data,
+ ObjPtr<mirror::ClassLoader> class_loader)
+ REQUIRES_SHARED(Locks::dex_lock_, Locks::mutator_lock_);
bool InitializeDefaultInterfaceRecursive(Thread* self,
Handle<mirror::Class> klass,