diff options
author | Mathieu Chartier <mathieuc@google.com> | 2015-06-26 10:47:08 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2015-06-26 13:34:28 -0700 |
commit | e290896bfccb170f589407c0d10945c8ae0c5807 (patch) | |
tree | 8fb55a86919bf91547e56cc68bb01366dd03082d /runtime | |
parent | 6415013f0b9509fed8367871daaf66c6841223f1 (diff) | |
download | art-e290896bfccb170f589407c0d10945c8ae0c5807.zip art-e290896bfccb170f589407c0d10945c8ae0c5807.tar.gz art-e290896bfccb170f589407c0d10945c8ae0c5807.tar.bz2 |
Require mutator lock for DeleteLocalRef
There was a race condition where suspended threads could call
DeleteLocalRef while the GC was marking their roots. This could
cause the GC to attempt to mark a null object.
(cherry picked from commit dd06afecd67fc6a60856436ab150a4d1b9a8ad29)
Bug: 22119403
Change-Id: I962c717bb87b2acb2a4710a2d7ab16793e031401
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/jni_internal.cc | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 6ab4455..0a01f78 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -554,15 +554,16 @@ class JNI { return soa.AddLocalReference<jobject>(decoded_obj); } - static void DeleteLocalRef(JNIEnv* env, jobject obj) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + static void DeleteLocalRef(JNIEnv* env, jobject obj) { if (obj == nullptr) { return; } - IndirectReferenceTable& locals = reinterpret_cast<JNIEnvExt*>(env)->locals; - - uint32_t cookie = reinterpret_cast<JNIEnvExt*>(env)->local_ref_cookie; - if (!locals.Remove(cookie, obj)) { + // SOA is only necessary to have exclusion between GC root marking and removing. + // We don't want to have the GC attempt to mark a null root if we just removed + // it. b/22119403 + ScopedObjectAccess soa(env); + auto* ext_env = down_cast<JNIEnvExt*>(env); + if (!ext_env->locals.Remove(ext_env->local_ref_cookie, obj)) { // Attempting to delete a local reference that is not in the // topmost local reference frame is a no-op. DeleteLocalRef returns // void and doesn't throw any exceptions, but we should probably |