Repository navigation
Conversation
The mount was torn down as soon as every holder of the keepalive pipe's read end was gone. Launchers that close inherited fds (e.g. sandboxing ones) while the app keeps running caused 'Transport endpoint is not connected' errors. Before terminating, wait until no process has its cwd, exe, open files or mappings inside the mount. Fixes #144 Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01PvYeShdbCf9Row4sKDiMMj
|
Build for testing: |
TheAssassin
left a comment
There was a problem hiding this comment.
Overall, the code could be structured a bit better and there is a dire need for better in-line documentation. For instance, the sleeping is quite arbitrary and it's not clear why one would just wait for 3 attempts and why there shouldn't be variable backoff times (pretty standard nowadays)
| idle_checks = 0; | ||
| else | ||
| idle_checks++; | ||
| usleep(500 * 1000); |
There was a problem hiding this comment.
Not a fan of a sync wait here, but it should be fine. Why have such a quick timeout, though? What's the rationale behind these figures?
The fixed 3 x 500 ms polling had no stated rationale and no backoff, so the daemon either scanned /proc too often while an app ran or reacted arbitrarily slowly. The wait now lives in its own function with named constants: it polls with exponential backoff (100 ms to 2 s) while the mount is busy and only tears it down after it has been unused for a 1 s quiet period, which bridges the gap between a launcher exiting and the next process starting.
|
Thanks for the review. Pushed an update:
The wait loop was only tested standalone (returns after ~1.1 s on an unused mount); a verification against the Bottles reproduction is still needed. |
|
Build for testing: |
Problem
Fixes #144. Apps such as the Bottles AppImage fail when run mounted but work with
APPIMAGE_EXTRACT_AND_RUN=1, with errors likeOSError: [Errno 107] Transport endpoint is not connected: '/usr/lib/python3.13/...'(see ivan-hc/Bottles-appimage#20).Cause
The FUSE daemon writes to a keepalive pipe and terminates itself on
EPIPE, i.e. as soon as every holder of the pipe's read end is gone. The read end is only held via fd inheritance, so any launcher that closes inherited fds (sandboxes/containers such as the JuNest/bwrap setup used by Bottles) drops it while the app is still running from the mount. The daemon then kills the mount underneath the app.Fix
On
EPIPE, the daemon no longer terminates immediately. It scans/procfor processes whose cwd, root, exe, open fds or memory maps lie inside the mount and only terminates after the mount has been unused for a 1s quiet period (polling with exponential backoff, 100ms to 2s, while it is in use).Testing
I could not build the full runtime or reproduce with Bottles in my environment (squashfuse headers unavailable). I only compiled and ran the detection helpers and the wait loop standalone: they report a mount as in use when a process has its cwd there and as unused otherwise. This needs verification against the Bottles reproduction before merging.