fix: detect interrupted commands in terminal exit code hack - #307256
Merged
Dmitriy Vasyura (dmitrivMS) merged 6 commits intoJul 30, 2026
Merged
Conversation
When a command is interrupted with Ctrl+C, the shell integration's history-based command detection incorrectly inherits the previous command's exit code. This happens because bash's `history` deduplicates identical commands, so the hack that compensates for this sees the same command text with an undefined exit code and assigns the last known one. Fix by checking if the raw command line in the terminal buffer ends with ^C before applying the history-merge heuristic. When interrupted, report exit code 130 (128 + SIGINT) instead of inheriting. Closes microsoft#237517
Megan Rogge (meganrogge)
previously approved these changes
Apr 2, 2026
Megan Rogge (meganrogge)
left a comment
Collaborator
There was a problem hiding this comment.
Thanks!
Dmitriy Vasyura (dmitrivMS)
previously approved these changes
Jul 29, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes terminal shell execution exit codes for commands interrupted with Ctrl+C.
Changes:
- Detects raw command lines ending in
^Cand reports exit code 130. - Adds regression tests for interrupted and duplicate commands.
Show a summary per file
| File | Description |
|---|---|
commandDetectionCapability.ts |
Adds interrupted-command detection. |
commandDetectionCapability.test.ts |
Adds regression tests; both assertions currently omit the initial command and fail. |
Review details
Comments suppressed due to low confidence (2)
src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts:176
- The first
printStandardCommandis still present when this assertion runs, soassertCommandscompares two actual commands against one expected command and the test fails. Keep the prior command in the expected list since it is required for the inheritance scenario.
assertCommands([
{ command: 'echo test', exitCode: 0, cwd: undefined, marker: { line: 2 } }
]);
src/vs/workbench/contrib/terminal/test/browser/capabilities/commandDetectionCapability.test.ts:170
- The method parameter is
number | undefined, making thisanycast unnecessary and contrary to the repository's no-anyguideline.
capability.handleCommandFinished(undefined as any);
- Files reviewed: 2/2 changed files
- Comments generated: 2
- Review effort level: Medium
Dmitriy Vasyura (dmitrivMS)
disabled auto-merge
July 29, 2026 05:56
Use the prompt input model's Ctrl+C signal to avoid applying the duplicate-history exit code workaround to canceled commands. Update the regression tests to cover the real duplicate-history command line and retain prior commands in expectations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Dmitriy Vasyura (dmitrivMS)
dismissed stale reviews from Megan Rogge (meganrogge) and themself
via
July 29, 2026 06:13
cfa3acd
Contributor
|
Updated the fix in cfa3acd:
Validation:
|
Dmitriy Vasyura (dmitrivMS)
enabled auto-merge (squash)
July 29, 2026 06:15
Dmitriy Vasyura (dmitrivMS)
approved these changes
Jul 29, 2026
Alex Ross (alexr00)
approved these changes
Jul 29, 2026
Anthony Kim (anthonykim1)
approved these changes
Jul 30, 2026
Dmitriy Vasyura (dmitrivMS)
merged commit Jul 30, 2026
3670eec
into
microsoft:main
46 of 47 checks passed
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.
What kind of change does this PR introduce?
Bug fix
What is the current behavior?
When a command is typed and interrupted with Ctrl+C (for example,
echo test^C), theTerminalShellExecutionend event can report an exit code inherited from the previous execution of the same command.For example:
This happens because
handleCommandFinishedcontains a workaround for versions of bash whosehistoryoutput merges identical commands. When bash reports anundefinedexit code and the shell integration reports the same command text as the previous command, the workaround reuses the previous exit code. An interrupted duplicate command therefore looks like the history-merge case and incorrectly inherits the previous result.Closes #237517
What is the new behavior?
CommandDetectionCapabilitynow listens to the existingPromptInputModel.onDidInterruptevent, which detects the Ctrl+C/ETX input directly. When the current command was interrupted, the duplicate-history workaround is skipped and theundefinedexit code reported by the shell is preserved. This matches the documentedTerminalShellExecutionEndEvent.exitCodecontract for commands canceled via Ctrl+C.The interrupted state is reset when the next prompt starts. Non-interrupted duplicate commands continue to use the existing bash history workaround unchanged.
Using the prompt input model's interrupt signal also avoids inferring cancellation from rendered
^Ctext, so a literal command ending in^Cis not treated as interrupted.Additional context
The regression tests verify that:
undefinedexit code instead of inheriting the previous command's exit code.^C.The tests also retain the initial command in their expected command lists and no longer use unnecessary
anycasts.Validation:
commandDetectionCapability.test.ts: 10 passingnpm run precommit: passed