places-sidebar: keep ejecting devices visible until the eject completes - #3816
Open
LucaBoschetto wants to merge 1 commit into
Open
places-sidebar: keep ejecting devices visible until the eject completes#3816LucaBoschetto wants to merge 1 commit into
LucaBoschetto wants to merge 1 commit into
Conversation
A GMount's mount-removed signal fires at the start of an eject, while
flushing cached writes to the device can take minutes. The sidebar
rebuilt on that early signal and rendered the device as a plain
unmounted volume ('Mount and open ...'), the strongest possible 'safe
to unplug' cue at exactly the moment it is least true - inviting
silent data loss and filesystem corruption on removable media.
Track devices with an eject in progress (process-global, so every
window agrees) and, while flushing:
- render the device as busy: '<name> (ejecting, do not remove)' with
a synchronizing emblem and explanatory tooltip, in both unmounted-
volume render paths;
- ignore activation on the row, which previously started a re-MOUNT
of the device mid-flush (a likely trigger of the 'operation already
pending' spam in linuxmint#3463);
- remove the entry in the eject completion callbacks (success or
failure), the one place that knows the device is truly done, and
refresh the sidebar;
- sweep entries whose volume is gone (physical yank) on every rebuild.
The completion callbacks now carry an EjectData (window keep-alive as
before, plus a weak pointer to the sidebar, which can be destroyed
during a long eject, and the device key).
No change to the eject operation itself, which was always correct;
only the UI no longer claims completion ~90s early.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
When a removable drive is ejected from the sidebar, its row disappears within about one second, while the kernel may still be flushing cached writes to the device for a minute or more. The only warning is a desktop notification ("Writing data..."), which is transient, easily missed, and may be disabled altogether; nothing in the file manager's own UI indicates the device is still busy. The user may reasonably conclude the eject is done, and unplugs. The files that were still in flight are truncated and the filesystem is left dirty.
This is easy to hit in real life: copying a large file to a USB stick returns almost immediately (the data lands in the page cache), the user clicks eject, the row vanishes, they pull the stick. On a 2 GB backlog I measured about 90 seconds between the row disappearing and the device actually being safe to remove (desktop system, source file on an NVMe SSD so the copy is cache-speed, ordinary consumer USB 3 flash sticks with exFAT sustaining roughly 20-50 MB/s; the size of the window is essentially backlog size over the stick's sequential write speed).
The eject operation itself (GVFS/udisks) is correct: it flushes everything and only reports completion when the device is truly safe. Only the sidebar UI reacts to the wrong signal.
Root cause
Verified at runtime with an isolation harness that makes the exact GIO calls Nemo makes, on Mint 22.3 / Nemo 6.6.3 / GVFS 1.54.4, with a 2 GB write-back backlog on an exFAT USB stick:
mount-removedfires at the start of the eject, not at completion. The GVolume however stays present the whole time, so on rebuild the device falls into the "unmounted volume" branch ofupdate_places ()and is rendered as a plain unmounted device: no eject button, a "Mount and open ..." tooltip, looks finished. The eject completion callbacks (mount_eject_cband friends), the one place that knows the device is truly safe, do nothing on success.Two extra consequences of the current behavior:
The fix
All in
nemo-places-sidebar.c, UI-only; the eject operation itself is untouched.do_eject ()records the device before starting the operation.xsi-emblem-synchronizing-symbolic) in the same spot the user clicked, and the tooltip reads "Still writing data to . Do not unplug it yet."update_places ()drops entries whose volume is gone, so a physically yanked device can never leave a stale "ejecting" row.The resulting semantics are simple and truthful: row present and marked busy = not safe to unplug; row gone = safe. This also lines up with the existing "can be safely unplugged" notification, which fires at the same moment the row now disappears.
Testing
Tested on Linux Mint 22.3 (Cinnamon 6.6.9, X11), Nemo built from this branch at 6.6.3, GVFS 1.54.4, kernels 6.17 and 7.0, against exFAT USB sticks, driven both manually and by a scripted harness that timestamps every GVolumeMonitor signal alongside /proc/meminfo Dirty. The branch was subsequently rebased onto current master (6.7.4-dev, 932438f) and re-verified there with a live large-backlog eject cycle: busy state renders, the re-trigger guard holds, completion clears the row, no kernel I/O errors. Detailed results:
Notes for reviewers
xsi-emblem-synchronizing-symbolicwas chosen instead: the xsi set ships with libxapp (already a hard dependency) and matches the sidebar's existing icons, so it resolves everywhere Nemo runs and is the closest portable fit semantically.show-unmount-progressfires only at start and completion; verified with the harness).Related issues
The reproduction harness (Python/GIO, ~60 lines) is available on request; happy to attach it or adapt this patch based on feedback.