fix: solve #3028 — forward DA1 query responses during shell init#3030
Merged
Conversation
Fish shell sends a DA1 escape sequence (ESC[c) at startup to detect terminal capabilities. The headless emulator (xterm.js) correctly generates a response, but it was being dropped during the "pending" shell-ready state. This caused fish to wait 10 seconds before timing out and disabling optional features like cursor shape and reflow. The fix removes the shellReadyState gate from the headless emulator's onData callback. Unlike renderer-generated responses (which go through session.write() and are correctly dropped to avoid appearing as typed text), headless emulator responses are written directly to the PTY and consumed by the shell as protocol data.
Contributor
Author
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
zombopanda
added a commit
to zombopanda/superset
that referenced
this pull request
Mar 31, 2026
The `emulator.onData` callback only forwarded terminal query responses (DA1, DSR) to the PTY subprocess when `attachedClients.size === 0`. When a renderer client is attached (the normal case when viewing a terminal), the headless emulator's DA1 response was silently dropped. This caused fish shell to wait 10 seconds for a DA1 response that never arrived, then print: "warning: fish could not read response to Primary Device Attribute query after waiting for 10 seconds" The previous fix in superset-sh#3030 removed the `shellReadyState === "pending"` guard but left the `attachedClients.size === 0` check intact. The renderer's xterm also generates DA1 responses, but those go through `write()` which drops all escape sequences during shell init — so neither path delivered the response to fish. Remove the `attachedClients.size === 0` condition so the headless emulator always forwards query responses to the subprocess. This is safe because `sendWriteToSubprocess` writes directly to the PTY via IPC, bypassing the renderer's write path entirely. Fixes superset-sh#3028
4 tasks
This was referenced Mar 31, 2026
Kitenite
added a commit
that referenced
this pull request
Apr 3, 2026
The `emulator.onData` callback only forwarded terminal query responses (DA1, DSR) to the PTY subprocess when `attachedClients.size === 0`. When a renderer client is attached (the normal case when viewing a terminal), the headless emulator's DA1 response was silently dropped. This caused fish shell to wait 10 seconds for a DA1 response that never arrived, then print: "warning: fish could not read response to Primary Device Attribute query after waiting for 10 seconds" The previous fix in #3030 removed the `shellReadyState === "pending"` guard but left the `attachedClients.size === 0` check intact. The renderer's xterm also generates DA1 responses, but those go through `write()` which drops all escape sequences during shell init — so neither path delivered the response to fish. Remove the `attachedClients.size === 0` condition so the headless emulator always forwards query responses to the subprocess. This is safe because `sendWriteToSubprocess` writes directly to the PTY via IPC, bypassing the renderer's write path entirely. Fixes #3028 Co-authored-by: zombopanda <1810282+zombopanda@users.noreply.github.com> Co-authored-by: Kiet Ho <hoakiet98@gmail.com>
MocA-Love
pushed a commit
to MocA-Love/superset
that referenced
this pull request
Apr 5, 2026
…ing shell init (superset-sh#3030)" (superset-sh#3127) This reverts commit 3194568.
MocA-Love
pushed a commit
to MocA-Love/superset
that referenced
this pull request
Apr 5, 2026
…rset-sh#3054) The `emulator.onData` callback only forwarded terminal query responses (DA1, DSR) to the PTY subprocess when `attachedClients.size === 0`. When a renderer client is attached (the normal case when viewing a terminal), the headless emulator's DA1 response was silently dropped. This caused fish shell to wait 10 seconds for a DA1 response that never arrived, then print: "warning: fish could not read response to Primary Device Attribute query after waiting for 10 seconds" The previous fix in superset-sh#3030 removed the `shellReadyState === "pending"` guard but left the `attachedClients.size === 0` check intact. The renderer's xterm also generates DA1 responses, but those go through `write()` which drops all escape sequences during shell init — so neither path delivered the response to fish. Remove the `attachedClients.size === 0` condition so the headless emulator always forwards query responses to the subprocess. This is safe because `sendWriteToSubprocess` writes directly to the PTY via IPC, bypassing the renderer's write path entirely. Fixes superset-sh#3028 Co-authored-by: zombopanda <1810282+zombopanda@users.noreply.github.com> Co-authored-by: Kiet Ho <hoakiet98@gmail.com>
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.
Summary
ESC[c) at startup to detect terminal capabilities, but the response was dropped during the "pending" shell-ready state, causing a 10-second timeoutshellReadyState === "pending"gate from the headless emulator'sonDatacallback so query responses (DA1, DSR, etc.) are forwarded to the subprocess immediatelyRoot cause
In
session.ts, the headless emulator'sonDatacallback had a guard that dropped all terminal query responses whileshellReadyState === "pending". This was intended to prevent responses from appearing as typed text, but the headless emulator writes directly to the PTY (viasendWriteToSubprocess), not through the pre-ready stdin queue. The shell reads these as protocol data, not user input.Fish sends DA1 during this exact "pending" window and waits up to 10 seconds for a reply. Without a response, fish disables cursor shape changes, reflow detection, and other optional features.
Test plan
Closes #3028
Summary by cubic
Forward terminal query responses (DA1, DSR) from the headless emulator during shell init so shells like fish don’t hang for 10s or disable features. Fixes #3028.
shellReadyState === "pending"guard in the headless emulatoronDataso DA1/DSR responses are written to the PTY immediately.Written for commit e807b39. Summary will update on new commits.