Skip to content

Unmount FUSE filesystems before suspend/hibernate#4940

Merged
dhh merged 8 commits intobasecamp:devfrom
alansikora:unmount-fuse-before-sleep
Mar 10, 2026
Merged

Unmount FUSE filesystems before suspend/hibernate#4940
dhh merged 8 commits intobasecamp:devfrom
alansikora:unmount-fuse-before-sleep

Conversation

@alansikora
Copy link
Copy Markdown
Contributor

@alansikora alansikora commented Mar 8, 2026

Problem

FUSE daemons — primarily gvfsd-fuse from Nautilus — can block the kernel's process freeze during suspend/hibernate. The daemon gets stuck in uninterruptible sleep (D state) waiting for FUSE I/O responses, the freeze times out after 20 seconds, and suspend silently fails. The system stays fully awake while appearing suspended, draining the battery.

This affects every Omarchy system since Nautilus (and therefore gvfs/fuse) is installed by default. It was confirmed as the root cause of excessive battery drain on Framework 13 AMD in #4184, and likely contributes to other suspend issues reported in #1556 and #2501.

Fix

Adds a systemd system-sleep hook that lazy-unmounts all FUSE filesystems before suspend/hibernate, following the same pattern as the existing keyboard-backlight and force-igpu hooks.

  • Fires on pre for both suspend and hibernate
  • Parses /proc/mounts generically — handles all users, all FUSE types (gvfsd-fuse, portal, rclone, sshfs)
  • fusermount3 -uz returns immediately (lazy unmount), non-destructive
  • On post, restarts gvfs-daemon for each logged-in user in the background (gvfsd-fuse doesn't self-restart; backgrounded with a delay to avoid blocking user.slice thaw)
  • Harmless no-op if no FUSE mounts exist

Blast radius

  • During normal usage: Zero impact — the hook only runs during suspend/hibernate
  • Pre-sleep unmount: Every Omarchy system has gvfsd-fuse (via Nautilus), so this benefits all users. Systems without FUSE mounts are unaffected (no-op)
  • Post-sleep restart: Backgrounded with a 5-second delay, cannot block resume. Silently fails if gvfs-daemon.service doesn't exist
  • Edge case: If a user is actively copying files over MTP/NFS/SMB via Nautilus when suspend triggers, the lazy unmount will interrupt that transfer. The alternative (suspend failing entirely) is worse, and this is an unlikely scenario

Changes

File Action
default/systemd/system-sleep/unmount-fuse New hook script
migrations/1773012889.sh Installs hook on existing systems
bin/omarchy-hibernation-setup Also installs hook during fresh hibernation setup

Testing

Tested on Framework 13 AMD (Ryzen, s2idle only):

  • Process freeze completes in 0.001s (previously timed out at 20s)
  • Resume completes instantly (no userspace thaw delay)
  • gvfs-daemon restarts automatically ~5s after wake
  • Nautilus and file manager features work normally after wake

References

Copilot AI review requested due to automatic review settings March 8, 2026 23:40
@alansikora alansikora marked this pull request as draft March 8, 2026 23:41
The read command had an extra _ placeholder that was swallowing the
fstype field, causing the fuse.* pattern to never match.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a systemd system-sleep hook to lazy-unmount all FUSE filesystems before suspend/hibernate, preventing FUSE daemons (primarily gvfsd-fuse from Nautilus) from blocking the kernel's process freeze and causing suspend to silently fail. This addresses battery drain issues reported on Framework 13 AMD and other laptops in #4184, #1556, and #2501.

Changes:

  • New system-sleep hook (unmount-fuse) that parses /proc/mounts for FUSE filesystems and lazy-unmounts them before suspend/hibernate using fusermount3/fusermount with fallback
  • Migration script to install the hook on existing systems
  • Integration into the hibernation setup script for fresh installs

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.

File Description
default/systemd/system-sleep/unmount-fuse New bash hook that lazy-unmounts all FUSE filesystems on pre-suspend/hibernate
migrations/1773012889.sh Migration to deploy the hook to existing Omarchy installations
bin/omarchy-hibernation-setup Adds hook installation during fresh hibernation setup, alongside the existing keyboard-backlight hook

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread migrations/1773012889.sh Outdated
gvfsd-fuse is spawned by gvfsd during init and not respawned if it
dies. After lazy-unmounting in pre-sleep, restart gvfs-daemon.service
in post-sleep so the FUSE mount at /run/user/*/gvfs is restored.
cp -p preserves the original user ownership from ~/.local/share/omarchy,
which would allow an unprivileged user to modify a script that runs as
root during suspend/hibernate.
Copilot AI review requested due to automatic review settings March 9, 2026 01:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 3 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@alansikora alansikora force-pushed the unmount-fuse-before-sleep branch from d841697 to a89c4f8 Compare March 9, 2026 01:41
The post-sleep hook runs before systemd thaws user.slice, so a
synchronous systemctl --user restart hangs for ~90 seconds waiting
for the frozen user manager to respond — blocking the entire resume.

Background the restart with a short delay so it executes after
user.slice is thawed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 9, 2026 02:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread default/systemd/system-sleep/unmount-fuse
Comment thread default/systemd/system-sleep/unmount-fuse
/proc/mounts uses octal escaping for special characters (e.g. \040 for
spaces). Decode with printf before passing to fusermount so paths with
spaces are handled correctly.

Add disown after backgrounding the gvfs restart so it survives
systemd-sleep's cgroup cleanup when the hook script exits.
@alansikora
Copy link
Copy Markdown
Contributor Author

Testing these changes locally on a Framework 13 AMD (Ryzen, s2idle) before marking ready for review. Suspend/wake cycle is working — will report back after extended testing.

Unmounting all FUSE filesystems breaks xdg-document-portal and AppImages
that rely on FUSE to stay mounted. It also doesn't restart them.
Copilot AI review requested due to automatic review settings March 9, 2026 14:28
Copy link
Copy Markdown
Member

@dhh dhh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I've pushed a fix to restrict the unmount to fuse.gvfsd-fuse only. Unmounting all fuse.* mounts broke things like xdg-document-portal (which is used by flatpaks) and any running AppImages, because only gvfsd-daemon was being restarted. I also added env to the sudo call to ensure the environment variables are explicitly passed rather than relying on sudo's VAR=value command parsing policy. Looks good!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 3 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@alansikora alansikora closed this Mar 9, 2026
@alansikora alansikora reopened this Mar 9, 2026
@alansikora alansikora marked this pull request as ready for review March 9, 2026 15:41
@alansikora
Copy link
Copy Markdown
Contributor Author

@dhh I think we are ready.

@dhh
Copy link
Copy Markdown
Member

dhh commented Mar 9, 2026

Think we need it somewhere else than in the hibernation setup. I think it needs its own installer, since it's relevant for suspend as well?

The hook prevents gvfsd-fuse from blocking suspend, not just
hibernation. Install it during the config phase so every system
gets it, not only those that run hibernation setup.
@alansikora
Copy link
Copy Markdown
Contributor Author

Ah you're right, completely overlooked that. Pushed a commit to give it its own installer in the config phase so it's always there regardless of hibernation setup.

@alansikora
Copy link
Copy Markdown
Contributor Author

Tested the latest changes locally. Multiple suspend/wake cycles, all clean:

  • Process freeze completes in 0.001s every time, zero failures
  • No hyprlock freezes on wake
  • Overnight test: 100% → 85% over ~12h40m suspended (~1.2%/hr, normal for s2idle on Framework 13 AMD)
  • Single clean suspend/wake cycle the entire night — no spurious wakes or failed freezes

@dhh dhh merged commit d508d84 into basecamp:dev Mar 10, 2026
@siebertm
Copy link
Copy Markdown

Since a few days (somewhere between 2026-03-03 and 2026-03-09), I have the issue that, after suspend, the system screen turns on, shows the "enter password" dialog but it totally frozen otherwise.

Could this one here be my issue or am I chasing a ghost?

@dhh
Copy link
Copy Markdown
Member

dhh commented Mar 13, 2026

I saw that issue once too. Did you try with this fix in place or without?

@siebertm
Copy link
Copy Markdown

Nope, that's not my bug :/
Would've been too easy.

(I upgraded again from my working snapshot to latest, verified it broke, added /usr/lib/systemd/system-sleep/unmount-fuse, chmod +x, reboot, suspend, froze)

@alansikora
Copy link
Copy Markdown
Contributor Author

@siebertm I had this all the time before the fix from this PR, but completely gone after it.

What is the hardware are you using?

@alansikora
Copy link
Copy Markdown
Contributor Author

@siebertm can you test adding #4941 to your system?

I closed it because I thought it was not necessary, but I had the impression this helped in one of the attempts.

@siebertm
Copy link
Copy Markdown

@siebertm can you test adding #4941 to your system?

I closed it because I thought it was not necessary, but I had the impression this helped in one of the attempts.

@alansikora nope, didnt work, even though the description is exactly what I experience:

lock screen being visible but completely unresponsive to input — no cursor blinking, no keyboard input, no trackpad — requiring a hard reboot

I can reproduce this 100% of the time and I have a working state and a non-working state which I can trigger at will by using snapper. Which means this is one of the (unfortunately many) updates that have been done between these 2 snapshots.

I think I'll dig deeper myself, possibly doing some bisecting - I dont think I need to "use" your time for that until I can put my finger on the thing that broke it.

@alansikora
Copy link
Copy Markdown
Contributor Author

@siebertm I was able to reproduce something similar here — suspend works fine on its own, but I noticed freezes when suspend-then-hibernate kicks in.

#5041 and #5051 should help with that.

Just want to make sure I’m not missing anything on my endL would you mind checking your journals to see if hibernation is being triggered there as well?

@siebertm
Copy link
Copy Markdown

@alansikora I just updated all packages from a "broken" state (no "ormachy" release update, just normal packages) - and sleep/wake works again for me.
I'm not using hibernate and I'm too scared to try that now - not touching that setup here...

I was not able to pinpoint the package which broke it. I suspect a linux-kernel or linux-firmware, but have no proof.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants