From 7c3c53d23014fa134fd78e9384013fa86cb10593 Mon Sep 17 00:00:00 2001 From: Richard Lawrence Date: Mon, 15 Sep 2025 10:42:25 -0500 Subject: [PATCH 1/2] Remove unused `io::Result` type from `BackgroundSession`, `unmount()`, and friends. This family of functions isn't actually capable of producing a meaningful `io` Error. --- examples/notify_inval_entry.rs | 2 +- examples/notify_inval_inode.rs | 2 +- examples/poll.rs | 2 +- src/lib.rs | 5 ++--- src/session.rs | 11 +++++------ tests/integration_tests.rs | 2 +- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/examples/notify_inval_entry.rs b/examples/notify_inval_entry.rs index cd017e26..51d0eb4e 100644 --- a/examples/notify_inval_entry.rs +++ b/examples/notify_inval_entry.rs @@ -164,7 +164,7 @@ fn main() { let session = fuser::Session::new(fs, opts.mount_point, &options).unwrap(); let notifier = session.notifier(); - let _bg = session.spawn().unwrap(); + let _bg = session.spawn(); loop { let mut fname = fname.lock().unwrap(); diff --git a/examples/notify_inval_inode.rs b/examples/notify_inval_inode.rs index d7ab155c..51f09004 100644 --- a/examples/notify_inval_inode.rs +++ b/examples/notify_inval_inode.rs @@ -202,7 +202,7 @@ fn main() { let session = fuser::Session::new(fs, opts.mount_point, &options).unwrap(); let notifier = session.notifier(); - let _bg = session.spawn().unwrap(); + let _bg = session.spawn(); loop { let mut s = fdata.lock().unwrap(); diff --git a/examples/poll.rs b/examples/poll.rs index aebdf5b5..ad5bcfa8 100644 --- a/examples/poll.rs +++ b/examples/poll.rs @@ -338,7 +338,7 @@ fn main() { let mntpt = std::env::args().nth(1).unwrap(); let session = fuser::Session::new(fs, mntpt, &options).unwrap(); - let bg = session.spawn().unwrap(); + let bg = session.spawn(); producer(&data, &bg.notifier()); } diff --git a/src/lib.rs b/src/lib.rs index 4885f387..96acf9c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1012,8 +1012,7 @@ pub fn spawn_mount<'a, FS: Filesystem + Send + 'static + 'a, P: AsRef>( .map(|x| Some(MountOption::from_str(x.to_str()?))) .collect(); let options = options.ok_or(ErrorKind::InvalidData)?; - Session::new(filesystem, mountpoint.as_ref(), options.as_ref()) - .and_then(session::Session::spawn) + Session::new(filesystem, mountpoint.as_ref(), options.as_ref()).map(session::Session::spawn) } /// Mount the given filesystem to the given mountpoint. This function spawns @@ -1031,5 +1030,5 @@ pub fn spawn_mount2<'a, FS: Filesystem + Send + 'static + 'a, P: AsRef>( options: &[MountOption], ) -> io::Result { check_option_conflicts(options)?; - Session::new(filesystem, mountpoint.as_ref(), options).and_then(session::Session::spawn) + Session::new(filesystem, mountpoint.as_ref(), options).map(session::Session::spawn) } diff --git a/src/session.rs b/src/session.rs index e1393a2d..9b333ac0 100644 --- a/src/session.rs +++ b/src/session.rs @@ -202,9 +202,8 @@ pub struct SessionUnmounter { impl SessionUnmounter { /// Unmount the filesystem - pub fn unmount(&mut self) -> io::Result<()> { + pub fn unmount(&mut self) { drop(std::mem::take(&mut *self.mount.lock().unwrap())); - Ok(()) } } @@ -219,7 +218,7 @@ fn aligned_sub_buf(buf: &mut [u8], alignment: usize) -> &mut [u8] { impl Session { /// Run the session loop in a background thread - pub fn spawn(self) -> io::Result { + pub fn spawn(self) -> BackgroundSession { BackgroundSession::new(self) } } @@ -251,7 +250,7 @@ impl BackgroundSession { /// Create a new background session for the given session by running its /// session loop in a background thread. If the returned handle is dropped, /// the filesystem is unmounted and the given session ends. - pub fn new(se: Session) -> io::Result { + pub fn new(se: Session) -> BackgroundSession { let sender = se.ch.sender(); // Take the fuse_session, so that we can unmount it let mount = std::mem::take(&mut *se.mount.lock().unwrap()).map(|(_, mount)| mount); @@ -259,11 +258,11 @@ impl BackgroundSession { let mut se = se; se.run() }); - Ok(BackgroundSession { + BackgroundSession { guard, sender, _mount: mount, - }) + } } /// Unmount the filesystem and join the background thread. /// # Panics diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index a351d4dd..3effd7f1 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -18,7 +18,7 @@ fn unmount_no_send() { let mut unmounter = session.unmount_callable(); thread::spawn(move || { thread::sleep(Duration::from_secs(1)); - unmounter.unmount().unwrap(); + unmounter.unmount(); }); session.run().unwrap(); } From 23f5f967791eea5cc048837414f5aacf584bb8b1 Mon Sep 17 00:00:00 2001 From: Richard Lawrence Date: Wed, 17 Sep 2025 11:46:51 -0500 Subject: [PATCH 2/2] Unmount and BackgroundSession no longer panic. Instead, treating mount lock poison as a warning. --- src/session.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/session.rs b/src/session.rs index 9b333ac0..410b669a 100644 --- a/src/session.rs +++ b/src/session.rs @@ -178,7 +178,12 @@ impl Session { /// Unmount the filesystem pub fn unmount(&mut self) { - drop(std::mem::take(&mut *self.mount.lock().unwrap())); + drop(std::mem::take(&mut *self.mount.lock().unwrap_or_else( + |poisoned| { + warn!("Ignored poisoned mount lock"); + poisoned.into_inner() + }, + ))); } /// Returns a thread-safe object that can be used to unmount the Filesystem @@ -203,7 +208,12 @@ pub struct SessionUnmounter { impl SessionUnmounter { /// Unmount the filesystem pub fn unmount(&mut self) { - drop(std::mem::take(&mut *self.mount.lock().unwrap())); + drop(std::mem::take(&mut *self.mount.lock().unwrap_or_else( + |poisoned| { + warn!("Ignored poisoned mount lock"); + poisoned.into_inner() + }, + ))); } } @@ -230,7 +240,12 @@ impl Drop for Session { self.destroyed = true; } - if let Some((mountpoint, _mount)) = std::mem::take(&mut *self.mount.lock().unwrap()) { + if let Some((mountpoint, _mount)) = + std::mem::take(&mut *self.mount.lock().unwrap_or_else(|poisoned| { + warn!("Ignored poisoned mount lock"); + poisoned.into_inner() + })) + { info!("unmounting session at {}", mountpoint.display()); } } @@ -253,7 +268,11 @@ impl BackgroundSession { pub fn new(se: Session) -> BackgroundSession { let sender = se.ch.sender(); // Take the fuse_session, so that we can unmount it - let mount = std::mem::take(&mut *se.mount.lock().unwrap()).map(|(_, mount)| mount); + let mount = std::mem::take(&mut *se.mount.lock().unwrap_or_else(|poisoned| { + warn!("Ignored poisoned mount lock"); + poisoned.into_inner() + })) + .map(|(_, mount)| mount); let guard = thread::spawn(move || { let mut se = se; se.run()