Skip to content

Add workbench.action.terminal.sendSignal command #250672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 6, 2025
Merged

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jun 4, 2025

This PR adds a new workbench.action.terminal.sendSignal command that allows sending arbitrary signals to the terminal's foreground process, similar to how workbench.action.terminal.sendSequence allows sending arbitrary text sequences.

Changes

The implementation follows the exact same pattern as the existing sendSequence command:

  • Command Registration: Added SendSignal to TerminalCommandId enum and registered the action with proper metadata
  • Command Handler: Created terminalSendSignalCommand function that validates signal argument and calls instance.sendSignal()
  • Terminal Pipeline: Added sendSignal method throughout the terminal stack:
    • ITerminalInstance and TerminalInstance
    • ITerminalProcessManager and TerminalProcessManager
    • ITerminalChildProcess and implementations (TerminalProcess, ExtHostPseudoterminal)
    • IPtyService and PtyService
  • Remote Support: Added SendSignal to remote terminal channel for remote development scenarios
  • Test Updates: Updated mock implementations to include sendSignal method

Usage

Users can now create keybindings to send signals:

{
    "key": "ctrl+alt+c",
    "command": "workbench.action.terminal.sendSignal",
    "args": { "signal": "SIGINT" },
    "when": "terminalFocus"
}

Common signals include:

  • SIGINT - Interrupt (like Ctrl+C)
  • SIGTERM - Terminate gracefully
  • SIGKILL - Force kill
  • SIGSTOP - Stop process
  • SIGCONT - Continue process

Implementation Notes

  • Minimal Scope: Only 81 lines added across 15 files, zero deletions
  • Graceful Fallbacks: Extension-owned pseudoterminals implement a no-op since they don't have direct process access
  • Signal Support: Leverages node-pty's existing kill(signal) method that supports arbitrary POSIX signals
  • Consistent API: Same argument validation, error handling, and registration pattern as sendSequence

Fixes #250671.

Warning

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.github.com
    • Triggering command: node ./lib/postinstall.js (dns block)
  • http://168.63.129.16:80/machine/
    • Triggering command: /usr/bin/python3 -u bin/WALinuxAgent-2.13.1.1-py3.9.egg -collect-logs (http block)

If you need me to access, download, or install something from one of these locations, you can either:


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: Tyriar <2193314+Tyriar@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Add a workbench.action.terminal.sendSignal command Add workbench.action.terminal.sendSignal command Jun 4, 2025
@Copilot Copilot AI requested a review from Tyriar June 4, 2025 20:21
Copilot finished work on behalf of Tyriar June 4, 2025 20:21
@Tyriar Tyriar added this to the June 2025 milestone Jun 4, 2025
@Tyriar
Copy link
Member

Tyriar commented Jun 5, 2025

@copilot compile errors:


[tsec-compile-check       ] src/vs/platform/terminal/node/ptyHostService.ts(33,14): error TS2420: Class 'PtyHostService' incorrectly implements interface 'IPtyHostService'.
[tsec-compile-check       ]   Property 'sendSignal' is missing in type 'PtyHostService' but required in type 'IPtyHostService'.
[tsec-compile-check       ] src/vs/platform/terminal/node/ptyService.ts(426,33): error TS2339: Property 'sendSignal' does not exist on type 'PersistentTerminalProcess'.
[tsec-compile-check       ] src/vs/server/node/serverServices.ts(216,28): error TS2345: Argument of type 'PtyHostService' is not assignable to parameter of type 'IPtyService | SyncDescriptor<IPtyService>'.
[tsec-compile-check       ]   Property 'sendSignal' is missing in type 'PtyHostService' but required in type 'IPtyService'.
[tsec-compile-check       ] src/vs/server/node/serverServices.ts(229,120): error TS2345: Argument of type 'PtyHostService' is not assignable to parameter of type 'IPtyHostService'.
[tsec-compile-check       ]   Property 'sendSignal' is missing in type 'PtyHostService' but required in type 'IPtyHostService'.
[tsec-compile-check       ] src/vs/workbench/api/browser/mainThreadTerminalService.ts(159,4): error TS2322: Type '((id: number, cols: number, rows: number) => TerminalProcessExtHostProxy) | undefined' is not assignable to type '((terminalId: number, cols: number, rows: number) => ITerminalChildProcess) | undefined'.
[tsec-compile-check       ]   Type '(id: number, cols: number, rows: number) => TerminalProcessExtHostProxy' is not assignable to type '(terminalId: number, cols: number, rows: number) => ITerminalChildProcess'.
[tsec-compile-check       ]     Property 'sendSignal' is missing in type 'TerminalProcessExtHostProxy' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts(1430,5): error TS2322: Type '(id: number, cols: number, rows: number) => TerminalProcessExtHostProxy' is not assignable to type '(terminalId: number, cols: number, rows: number) => ITerminalChildProcess'.
[tsec-compile-check       ]   Property 'sendSignal' is missing in type 'TerminalProcessExtHostProxy' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts(1500,108): error TS2345: Argument of type 'IShellLaunchConfig | undefined' is not assignable to parameter of type 'IShellLaunchConfig'.
[tsec-compile-check       ]   Type 'undefined' is not assignable to type 'IShellLaunchConfig'.
[tsec-compile-check       ] src/vs/workbench/contrib/terminal/browser/remotePty.ts(12,14): error TS2420: Class 'RemotePty' incorrectly implements interface 'ITerminalChildProcess'.
[tsec-compile-check       ]   Property 'sendSignal' is missing in type 'RemotePty' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts(209,3): error TS2741: Property 'sendSignal' is missing in type 'RemotePty' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts(221,4): error TS2741: Property 'sendSignal' is missing in type 'RemotePty' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts(12,14): error TS2420: Class 'TerminalProcessExtHostProxy' incorrectly implements interface 'ITerminalChildProcess'.
[tsec-compile-check       ]   Property 'sendSignal' is missing in type 'TerminalProcessExtHostProxy' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts(13,14): error TS2420: Class 'LocalPty' incorrectly implements interface 'ITerminalChildProcess'.
[tsec-compile-check       ]   Property 'sendSignal' is missing in type 'LocalPty' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts(213,3): error TS2741: Property 'sendSignal' is missing in type 'LocalPty' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts(222,4): error TS2741: Property 'sendSignal' is missing in type 'LocalPty' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/services/terminal/common/embedderTerminalService.ts(65,4): error TS2322: Type '(terminalId: number, cols: number, rows: number) => EmbedderTerminalProcess' is not assignable to type '(terminalId: number, cols: number, rows: number) => ITerminalChildProcess'.
[tsec-compile-check       ]   Property 'sendSignal' is missing in type 'EmbedderTerminalProcess' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] src/vs/workbench/services/terminal/common/embedderTerminalService.ts(74,7): error TS2420: Class 'EmbedderTerminalProcess' incorrectly implements interface 'ITerminalChildProcess'.
[tsec-compile-check       ]   Property 'sendSignal' is missing in type 'EmbedderTerminalProcess' but required in type 'ITerminalChildProcess'.
[tsec-compile-check       ] 
[tsec-compile-check       ] 
[tsec-compile-check       ] Found 17 errors.

…lasses

Co-authored-by: Tyriar <2193314+Tyriar@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jun 5, 2025

@copilot compile errors:

...

Fixed all compilation errors by implementing the missing sendSignal method in classes that implement ITerminalChildProcess and related interfaces. The implementation follows the established patterns: delegation to proxies for service classes, forwarding to underlying terminal processes for wrapper classes, and no-op implementations for extension/external terminals. See commit d7cc9b3.

Warning

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • electronjs.org
    • Triggering command: node-gyp (dns block)
  • http://168.63.129.16:80/machine/
    • Triggering command: /usr/bin/python3 -u bin/WALinuxAgent-2.13.1.1-py3.9.egg -collect-logs (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of Tyriar June 5, 2025 10:56
Comment on lines 141 to 149
const instance = accessor.get(ITerminalService).activeInstance;
if (instance) {
const signal = isObject(args) && 'signal' in args ? toOptionalString(args.signal) : undefined;
if (!signal) {
return;
}
instance.sendSignal(signal);
}
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should show a quick pick with all possible signals when there is no argument provided.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added signal quick pick when no argument is provided. The command now shows a list of 9 common POSIX signals with descriptions when invoked without arguments. See commit 31db9c4.

Co-authored-by: Tyriar <2193314+Tyriar@users.noreply.github.com>
Copilot finished work on behalf of Tyriar June 5, 2025 12:35
Tyriar
Tyriar previously requested changes Jun 5, 2025
Comment on lines 151 to 161
const signalOptions: IQuickPickItem[] = [
{ label: 'SIGINT', description: 'Interrupt process (Ctrl+C)' },
{ label: 'SIGTERM', description: 'Terminate process gracefully' },
{ label: 'SIGKILL', description: 'Force kill process' },
{ label: 'SIGSTOP', description: 'Stop process' },
{ label: 'SIGCONT', description: 'Continue process' },
{ label: 'SIGHUP', description: 'Hangup' },
{ label: 'SIGQUIT', description: 'Quit process' },
{ label: 'SIGUSR1', description: 'User-defined signal 1' },
{ label: 'SIGUSR2', description: 'User-defined signal 2' }
];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide another option after a separator "Manually enter signal" which provides a text input to use.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added separator and manual signal input option to the signal picker. When no argument is provided, users can now select from predefined signals or choose "Manually enter signal" to provide a custom signal name. See commit b9db1ff.

Co-authored-by: Tyriar <2193314+Tyriar@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jun 5, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • electronjs.org
    • Triggering command: node-gyp (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of Tyriar June 5, 2025 12:51
@Tyriar Tyriar requested a review from meganrogge June 5, 2025 13:41
@Tyriar Tyriar marked this pull request as ready for review June 5, 2025 13:41
@Tyriar Tyriar enabled auto-merge June 6, 2025 14:31
@Tyriar Tyriar closed this Jun 6, 2025
auto-merge was automatically disabled June 6, 2025 14:32

Pull request was closed

@Tyriar Tyriar reopened this Jun 6, 2025
@Tyriar Tyriar enabled auto-merge June 6, 2025 14:32
@Tyriar Tyriar merged commit 887037b into main Jun 6, 2025
12 checks passed
@Tyriar Tyriar deleted the copilot/fix-250671 branch June 6, 2025 14:48
@vs-code-engineering vs-code-engineering bot locked and limited conversation to collaborators Jul 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Error loading sessions

Retrying.

Successfully merging this pull request may close these issues.

Add a workbench.action.terminal.sendSignal command
3 participants