fix: load tmux config from symlink and honor set -q#68
Open
teng-lin wants to merge 2 commits into
Open
Conversation
Two bugs caused rmux to silently ignore a user's tmux config (e.g. oh-my-tmux), both required to reproduce: 1. `set -q` was parsed but discarded, so options removed in newer tmux (`set -q -g status-utf8 on`, `setw -q -g utf8 on`) raised "invalid option" errors. A single config error discards the whole file, so the entire config was dropped. Capture `-q` and suppress unknown/ambiguous option errors (returning a no-op), matching tmux semantics. 2. The tmux-fallback reader rejected all symlinks via symlink_metadata + O_NOFOLLOW, silently skipping the symlinked ~/.config/tmux/tmux.conf that oh-my-tmux installs (the error is swallowed on the best-effort path). Follow symlinks but stat the target so FIFOs/dirs/devices are still skipped; keep O_NONBLOCK as a second guard against blocking. Add a regression test that the best-effort tmux fallback follows a symlink to a regular file.
Config `run-shell` commands run synchronously during startup config load, and the config-loading guard they hold gates client readiness. A command that blocks therefore makes `rmux` startup hang until the client's 20s deadline expires. oh-my-tmux triggers this: it shells out to the tmux binary against rmux's socket (TMUX_PROGRAM detection / _apply_configuration), which stalls ~20s. Release the readiness guard after a short budget (2s) while the config keeps executing in the background, so a slow command no longer blocks startup. Normal configs finish far inside the budget and are never delayed; only a pathologically slow config releases readiness early. Execution is not cancelled, so the commands still complete and nothing is orphaned. Add a regression test that readiness clears before a blocking run-shell finishes (with a short test-only budget).
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.
Fixes #67.
rmux silently ignores a standard oh-my-tmux install when used as the tmux-config fallback, and — once the config does load — startup hangs ~20s. Three independent issues, fixed in three commits.
1 —
set -qis parsed but discardedoh-my-tmux uses
set -q -g status-utf8 on/setw -q -g utf8 onfor options removed in newer tmux. tmux’s-qsuppresses “unknown/ambiguous option” errors; rmux parsed-qand threw it away, so those lines raisedinvalid option: status-utf8. A single config error discards the entire file, so the whole config was dropped.Now
-qis captured intoSetOptionFlags.quietand suppresses unknown/ambiguous-option errors fromresolve_set_option_scope(returning a no-op), matching tmux.2 — the tmux-fallback reader rejects all symlinks
read_tmux_compat_source_entryusedsymlink_metadata+O_NOFOLLOWand rejected any symlink. Because the fallback path is best-effort, the error is swallowed — no message, no config. oh-my-tmux installs~/.config/tmux/tmux.confas a symlink, so it was silently skipped.The symlink hardening (commit 2fd8872) was only meant to avoid blocking on a symlink→FIFO. Now the reader follows symlinks but stats the target (
fs::metadata, which never blocks on a FIFO) to still skip FIFOs/dirs/devices, and keepsO_NONBLOCKas a second guard.3 — a slow config
run-shellfreezes startupConfig
run-shellcommands run synchronously during startup config load, and the config-loading guard they hold gates client readiness. A command that blocks therefore makesrmuxstartup hang until the client’s 20s deadline. oh-my-tmux triggers this: itsTMUX_PROGRAMdetection /_apply_configurationshell out to thetmuxbinary against rmux’s socket and stall ~20s.The daemon now releases the readiness guard after a short budget (2s) while the config keeps executing in the background — so a slow command no longer blocks startup. Normal configs finish far inside the budget and are never delayed; execution is not cancelled, so commands still complete and nothing is orphaned.
Verification
Real symlinked oh-my-tmux: startup drops from ~20s (hang) to ~2s, exit 0, options applied:
A plain rmux config still starts in ~0.02s (budget never triggers).
Tests
tmux_best_effort_source_follows_symlink_to_regular_file— symlink→regular-file is loaded.startup_readiness_clears_before_a_blocking_run_shell_finishes— readiness clears before a blocking run-shell finishes (asserts the load task is still running, so it genuinely exercises the budget path).tmux_best_effort_source_skips_symlink_to_fifo_without_blockingstill passes.rmux-server(1648) andrmux-core(77); clippy clean.Out of scope
Full oh-my-tmux theming still won’t work — it depends on the
tmuxbinary via$TMUX_PROGRAM(re-detected vialsof, which rejects rmux’s internal daemon binary) and a deep_apply_configurationpipeline of baretmux/rmuxsubcommands. This PR makes rmux load the config’s plain options and not hang; full oh-my-tmux compat is a separate effort tracked in #67.