Force UTF-8 locale to keep tab-separated parsing intact - #568
Open
vivek8031 wants to merge 1 commit into
Open
Conversation
…ntact
When this script runs in an environment with empty LC_ALL/LANG (notably
macOS launchd jobs and minimal cron environments) tmux 3.x's `-F`
format substitution renders tab characters (0x09) as underscores
(0x5f). Every save.sh / restore.sh code path uses `IFS=$'\t' read` to
parse this output, so the parser silently sees a single field per line
and produces near-empty resurrect files (only the trailing `state`
line survives, ~8 bytes).
Reproduce on macOS:
$ unset LC_ALL LANG LC_CTYPE
$ tmux list-panes -a -F "pane\t#{session_name}\t#{pane_pid}" \
| head -1 | xxd
00000000: 7061 6e65 5f34 5f31 3335 3934 0a pane_4_13594. ← underscores
$ export LC_ALL=C.UTF-8
$ tmux list-panes -a -F "pane\t#{session_name}\t#{pane_pid}" \
| head -1 | xxd
00000000: 7061 6e65 0934 0931 3335 3934 0a pane.4.13594. ← tabs
This was particularly nasty when used in tandem with tmux-continuum: a
LaunchAgent-driven `continuum_save` could overwrite the `last` symlink
with the broken 8-byte save right before auto-restore ran, so the next
boot restored nothing. (See tmux-continuum issues tmux-plugins#90 / tmux-plugins#94 and
https://joeywrites.dev/posts/fixing-broken-tmux-resurrect-save .)
Fix: in helpers.sh (sourced by every script in this repo), set
LC_ALL=C.UTF-8 if the user has no locale configured at all. Existing
LC_ALL or LANG values are left untouched.
Verified: the patched save.sh, run from a shell with all locale vars
unset, produces a 2 KB resurrect file containing real tabs (xxd 0x09)
and all live sessions, instead of the 8-byte `state__` line that the
unpatched script writes.
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.
Problem
When any script in this repo (
save.sh,restore.sh, the helpers they share) runs in an environment with noLC_ALLorLANGset, tmux 3.x's-Fformat substitution renders tab characters (0x09) as underscores (0x5f). Because this script usesIFS=$'\t' readeverywhere (pane_format,window_format,state_format, …), every line collapses into a single field, the parser bails out, andsave_allwrites a near-empty resurrect file containing only the trailingstateline — about 8 bytes.Common environments that hit this on macOS:
PATHare set butLC_ALL/LANGare not)cronenvironmentsThe result is silent:
save.shexits 0,lastsymlink updates to the broken file, and the next auto-restore brings back nothing.Reproduction (macOS, tmux 3.6a)
This pairs nastily with tmux-continuum: a LaunchAgent / status-bar driven
continuum_saveoverwrites thelastsymlink with the 8-byte file right before auto-restore runs on next boot. Discussed at length in tmux-continuum issues #90 / #94 and at https://joeywrites.dev/posts/fixing-broken-tmux-resurrect-save/, where the documented workaround is toln -sfa known-good save back into place by hand.Fix
In
scripts/helpers.sh(sourced by every script in the repo), setLC_ALL=C.UTF-8if and only if the user has no locale configured at all:C.UTF-8is available on glibc (≥ 2.13) and macOS (Big Sur+), and is a sensible neutral default. ExistingLC_ALLorLANGare left alone, so users who have explicitly chosen a locale see no change.Verification
Compatibility
LC_ALLorLANGalready set.helpers.sh.