summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author hyeeun.jun@samsung.com <hyeeun.jun@samsung.com> 2020-01-29 17:09:06 +0900
committer Narayan Kamath <narayan@google.com> 2020-06-17 13:45:13 +0100
commitf8a1cec8d5d054e16bf2788f3a3f1a06dd20ec4d (patch)
treefa972fc1ff1cbc30e77997419c3cb74f710e6dc9
parente6c5d04a218d3fd2dffce71058254798f509bbce (diff)
Fix Deadlock Issue On AppFuseBridge
There are two locks used by AppFuseBridge. First is it's object lock, and the second is a mutex lock in app fuse library. There are two oppsite routines to get those locks. (Thread A) Got Java lock -> Try to get Native lock (Thread B) Got Native lock -> Try to get Java lock The order must be followed to obtain two locks. If not, the dead lock will be caused. Therefore we change the routine to get the mutex lock first, and the object lock later. Signed-off-by: hyeeun.jun@samsung.com <hyeeun.jun@samsung.com> Bug: https://issuetracker.google.com/issues/145707568 Bug: 157535024 Test: atest --test-mapping apex/blobstore Change-Id: I1f05cc98953d8452147370dd04c223d54c0e5362
-rw-r--r--services/core/java/com/android/server/storage/AppFuseBridge.java12
-rw-r--r--services/core/jni/com_android_server_storage_AppFuseBridge.cpp18
2 files changed, 30 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/storage/AppFuseBridge.java b/services/core/java/com/android/server/storage/AppFuseBridge.java
index 9d6a64701e85..b00540fd2a52 100644
--- a/services/core/java/com/android/server/storage/AppFuseBridge.java
+++ b/services/core/java/com/android/server/storage/AppFuseBridge.java
@@ -56,6 +56,15 @@ public class AppFuseBridge implements Runnable {
public ParcelFileDescriptor addBridge(MountScope mountScope)
throws FuseUnavailableMountException, NativeDaemonConnectorException {
+ /*
+ ** Dead Lock between Java lock (AppFuseBridge.java) and Native lock (FuseBridgeLoop.cc)
+ **
+ ** (Thread A) Got Java lock (addBrdige) -> Try to get Native lock (native_add_brdige)
+ ** (Thread B) Got Native lock (FuseBrdigeLoop.start) -> Try to get Java lock (onClosed)
+ **
+ ** Guarantee the lock order (native lock -> java lock) when adding Bridge.
+ */
+ native_lock();
try {
synchronized (this) {
Preconditions.checkArgument(mScopes.indexOfKey(mountScope.mountId) < 0);
@@ -73,6 +82,7 @@ public class AppFuseBridge implements Runnable {
return result;
}
} finally {
+ native_unlock();
IoUtils.closeQuietly(mountScope);
}
}
@@ -159,4 +169,6 @@ public class AppFuseBridge implements Runnable {
private native void native_delete(long loop);
private native void native_start_loop(long loop);
private native int native_add_bridge(long loop, int mountId, int deviceId);
+ private native void native_lock();
+ private native void native_unlock();
}
diff --git a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
index e51963340ae1..20210abd0ea8 100644
--- a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
+++ b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
@@ -123,6 +123,14 @@ jint com_android_server_storage_AppFuseBridge_add_bridge(
return proxyFd[1].release();
}
+void com_android_server_storage_AppFuseBridge_lock(JNIEnv* env, jobject self) {
+ fuse::FuseBridgeLoop::Lock();
+}
+
+void com_android_server_storage_AppFuseBridge_unlock(JNIEnv* env, jobject self) {
+ fuse::FuseBridgeLoop::Unlock();
+}
+
const JNINativeMethod methods[] = {
{
"native_new",
@@ -143,6 +151,16 @@ const JNINativeMethod methods[] = {
"native_add_bridge",
"(JII)I",
reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_add_bridge)
+ },
+ {
+ "native_lock",
+ "()V",
+ reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_lock)
+ },
+ {
+ "native_unlock",
+ "()V",
+ reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_unlock)
}
};