Skip to content

Fix mksh input-byte loss from unreliable peek probe#8

Merged
alganet merged 1 commit into
mainfrom
mksh-fix
Jun 13, 2026
Merged

Fix mksh input-byte loss from unreliable peek probe#8
alganet merged 1 commit into
mainfrom
mksh-fix

Conversation

@alganet

@alganet alganet commented Jun 13, 2026

Copy link
Copy Markdown
Owner

tuish_init chooses how tuish_has_pending_input peeks the next byte based on whether read -t0 consumes a byte or only checks availability. It decided this with a heredoc probe — but mksh's own read -d '' -n 1 -t0 on a heredoc is non-deterministic: it intermittently reports no data even though the heredoc byte is present.

When the probe came back empty, tui.sh installed the two-read peek (_tuish_get_byte -t0 && _tuish_get_byte). On mksh's tty, however, the first -t0 read does consume a byte, so the second read consumed and stashed a different one — dropping one input byte on every peek that found input. During a glued key burst that silently lost ~4 of 10 events, which is the mksh flakiness seen on CI (e.g. "events: 6" instead of "events: 10" in test_redraw_coalesce).

ksh93 and mksh both set KSH_VERSION and both consume on -t0, so select the single-read peek by shell identity instead of probing. bash/busybox do not set KSH_VERSION and their heredoc probe is stable (always reports no data), so they keep the two-read consume path.

Verified: heredoc probe under mksh flips between consumed/empty across runs; with the fix, test_redraw_coalesce passes 12/12 under mksh (was ~1-in-3 failing). redraw_coalesce also passes 3/3 under bash, ksh93, busybox; keyboard/characters/special/mouse integration and all unit suites pass under mksh.

tuish_init chooses how tuish_has_pending_input peeks the next byte based
on whether `read -t0` consumes a byte or only checks availability. It
decided this with a heredoc probe — but mksh's own
`read -d '' -n 1 -t0` on a heredoc is non-deterministic: it intermittently
reports no data even though the heredoc byte is present.

When the probe came back empty, tui.sh installed the two-read peek
(`_tuish_get_byte -t0 && _tuish_get_byte`). On mksh's tty, however, the
first `-t0` read *does* consume a byte, so the second read consumed and
stashed a different one — dropping one input byte on every peek that
found input. During a glued key burst that silently lost ~4 of 10
events, which is the mksh flakiness seen on CI (e.g. "events: 6" instead
of "events: 10" in test_redraw_coalesce).

ksh93 and mksh both set KSH_VERSION and both consume on -t0, so select
the single-read peek by shell identity instead of probing. bash/busybox
do not set KSH_VERSION and their heredoc probe is stable (always reports
no data), so they keep the two-read consume path.

Verified: heredoc probe under mksh flips between consumed/empty across
runs; with the fix, test_redraw_coalesce passes 12/12 under mksh (was
~1-in-3 failing). redraw_coalesce also passes 3/3 under bash, ksh93,
busybox; keyboard/characters/special/mouse integration and all unit
suites pass under mksh.
@alganet
alganet merged commit cd3b0fe into main Jun 13, 2026
10 checks passed
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.

1 participant