Skip to content

CSI 6 n response is 18 bytes (non-canonical, expected 6) #367

@deblasis

Description

@deblasis

Surfaced via wintty-bench diagnostic instrumentation. Wintty replies to a CSI 6 n cursor-position request with an 18-byte payload before the terminating 'R', vs the canonical 6 bytes (\e[<row>;<col>) that Windows Terminal and the VT100 spec emit.

Evidence

From a cursor-query throughput measurement run via wintty-bench (--cells=C5 --terminals=wintty,wt), with bash diagnostic capturing read -d R exit code and response length:

WT (11 iters):     stty_exit=0  read_exit=0  resp_len=6
Wintty (11 iters): stty_exit=1  read_exit=0  resp_len=18

Both stty-related symptoms (libghostty's PTY appears to ignore stty -icanon -echo) and resp_len divergence are wintty-side. WT under the same fixture matches the spec.

Why it matters

  • Spec deviation: any conformance-checking VT client (vtebench, applications using cursor-position queries for layout, etc.) may misbehave or flag this.
  • Performance side-effect: clients reading byte-by-byte until 'R' do 3x more stdin work per query under wintty than under spec-compliant terminals.
  • Concrete impact: wintty-bench C5/wsl-unicode cell drifts ~35% under its baseline because of the extra stdin I/O per cursor-query iter.

Likely causes (theories, not yet confirmed)

  1. Wintty's CSI 6 n handler emits a parameterized form (e.g. \e[?<row>;<col>;<flag>R) instead of canonical \e[<row>;<col>R.
  2. Wintty's libghostty PTY is concatenating the cursor reply with another auto-response (DA1, OSC, etc.).
  3. Wintty double-replies because it processes the query through both its internal parser and a forwarded path.

Reproduce

From a real pwsh terminal:

cd C:\Users\Alessandro\CODE\OSS\wintty-bench
# Add `printf 'hex='; printf '%s' "$_resp" | xxd -p; printf '\n'` after the read in BuildWslCommand
dotnet run --project harness -- --mode=ci --cells=C5 --terminals=wintty --target="<release Wintty.exe>"
Get-Content ${env:TEMP}\wintty-bench-scripts\C5-*.log

The hex of _resp pins the exact byte sequence wintty emits.

Scope

Investigate where wintty handles CSI 6 n (likely in libghostty's terminal/parser layer or in the PTY response path) and ensure the response is the canonical \e[<row>;<col>R form. Add a regression test if the parser/terminal layer has unit-test coverage.

Tracked from wintty-bench side at deblasis/wintty-bench # 25 (closed; cross-reference for context).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions