diff options
author | 2024-10-25 17:18:22 -0700 | |
---|---|---|
committer | 2024-10-27 02:47:36 +0000 | |
commit | 5be7f7dab782b2a0629314f2b14a73b2ead301ce (patch) | |
tree | 0aeae4b4c614b140b1c4a54de82b0c058d8fe6d3 | |
parent | e60598cab98ba513c7507d0ee63969bdc5dff38f (diff) |
Don't block for long in UnloadNativeLibraries()
If we can't get jni_libraries_lock_ quickly give up, and let the next
call to UnloadNativeLibraries() handle it.
Bug: 74209523
Test: Treehugger
Change-Id: I42bc812a38916bb626b025fde96118f670112c13
-rw-r--r-- | runtime/jni/java_vm_ext.cc | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/runtime/jni/java_vm_ext.cc b/runtime/jni/java_vm_ext.cc index 60b436984d..3012539b3c 100644 --- a/runtime/jni/java_vm_ext.cc +++ b/runtime/jni/java_vm_ext.cc @@ -353,7 +353,19 @@ class Libraries { Thread* const self = Thread::Current(); std::vector<SharedLibrary*> unload_libraries; { - MutexLock mu(self, *Locks::jni_libraries_lock_); + // jni_libraries_lock_ appears to be held long enough that we just retry once, rather than + // spinning. + int retries = 0; + static constexpr int MAX_RETRIES = 5; + while (!Locks::jni_libraries_lock_->ExclusiveTryLock(self)) { + if (++retries > MAX_RETRIES) { + // We do not want to block indefinitely here, for fear of timeouts. See b/374209523. + LOG(WARNING) << "Deferring native library unloading due to contention"; + return; + } + ScopedTrace("sleep 1 msec for jni_libraries_lock_"); + usleep(1000); + } for (auto it = libraries_.begin(); it != libraries_.end(); ) { SharedLibrary* const library = it->second; // If class loader is null then it was unloaded, call JNI_OnUnload. @@ -367,6 +379,7 @@ class Libraries { ++it; } } + Locks::jni_libraries_lock_->ExclusiveUnlock(self); } ScopedThreadSuspension sts(self, ThreadState::kNative); // Do this without holding the jni libraries lock to prevent possible deadlocks. |