diff options
author | 2024-01-16 12:07:11 +0900 | |
---|---|---|
committer | 2024-01-19 18:15:15 +0000 | |
commit | 3db27d5678932b14d5c47549e3cea4c19d4f43c8 (patch) | |
tree | 8906ebb0a94823c6a4d6cab748f98c0cfe9cb62f /jni/node-inl.h | |
parent | 2619cd4fb8d912f5ec14b742474660e037b5119e (diff) |
Fix deadlock when closing the backing file
A deadlock occurs between FuseDaemon lock and inode lock in the scenario
related to the photo picker. So, to address the deadlock, modify it to
release the FuseDaemon lock before closing the backing file.
In the following, 'the original fuse file' is the source of the picker
path file.
A1. Perform a FUSE_FLUSH on the original fuse file. As a result, inode
attributes are invalidated.
B1. Attempt to close the picker path file. The backing file of the
picker path file is the original fuse file.
B2. Acquire the FuseDaemon lock associated with the FuseDaemon node.
Attempting to close the orignal fuse file.
A2. Perform lseek with the SEEK_END flag. Acquire the inode lock.
A3. Due to the invalidation of inode attributes, request FUSE_GETATTR.
A4. Attempt to acquire the FuseDaemon lock, but wait due to B2.
B3. Attemp to acquire the inode lock in fuse_flush, but waiting due
to A2.
* This issue only occurs when the kernel version is v5.15 or lower.
Test: Execute the following commands simultaneously in two shells.
$ adb root && adb shell
# UID=`ps -en | grep rs.media.module | cut -d ' ' -f 1`; su $UID
$ while true; do cat /sdcard/.transforms/synthetic/picker/0\
/com.android.providers.media.photopicker/media/<id> > /dev/null; done
Change-Id: Idf6a92e160c9994e862cd34a983d3d7b773c7a4c
Signed-off-by: yoonho.shin <yoonho.shin@samsung.com>
Diffstat (limited to 'jni/node-inl.h')
-rw-r--r-- | jni/node-inl.h | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/jni/node-inl.h b/jni/node-inl.h index 15844e3c9..ba3d9268f 100644 --- a/jni/node-inl.h +++ b/jni/node-inl.h @@ -322,12 +322,20 @@ class node { } void DestroyHandle(handle* h) { - std::lock_guard<std::recursive_mutex> guard(*lock_); + // A deadlock occurs between FuseDaemon lock and inode lock in the photo picker scenario. + // In order to address this deadlock, we release the FuseDaemon lock before closing the + // backing file. + std::unique_ptr<handle> temp; + + lock_->lock(); auto comp = [h](const std::unique_ptr<handle>& ptr) { return ptr.get() == h; }; auto it = std::find_if(handles_.begin(), handles_.end(), comp); CHECK(it != handles_.end()); + temp = std::move(*it); handles_.erase(it); + + lock_->unlock(); } bool HasCachedHandle() const { |