fix: external terminal not registering Ctrl+C with .NET Core (#201020)

Best I can tell, `start` eats process interrupt signals, even though we
don't pass `/b` which is documented to request this behavior. So
instead, in the year 2024, launch using the windows terminal instead of
it exists on the system to sidestep this issue.

Fixes #81322
This commit is contained in:
Connor Peet 2023-12-15 13:34:44 -08:00 committed by GitHub
parent d260879c50
commit 9af00bdd83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as cp from 'child_process';
import { memoize } from 'vs/base/common/decorators';
import { FileAccess } from 'vs/base/common/network';
import * as path from 'vs/base/common/path';
import * as env from 'vs/base/common/platform';
@ -66,14 +67,15 @@ export class WindowsExternalTerminalService extends ExternalTerminalService impl
return new Promise<void>((c, e) => {
const env = getSanitizedEnvironment(process);
const child = spawner.spawn(command, cmdArgs, { cwd, env });
const child = spawner.spawn(command, cmdArgs, { cwd, env, detached: true });
child.on('error', e);
child.on('exit', () => c());
});
}
public runInTerminal(title: string, dir: string, args: string[], envVars: ITerminalEnvironment, settings: IExternalTerminalSettings): Promise<number | undefined> {
public async runInTerminal(title: string, dir: string, args: string[], envVars: ITerminalEnvironment, settings: IExternalTerminalSettings): Promise<number | undefined> {
const exec = 'windowsExec' in settings && settings.windowsExec ? settings.windowsExec : WindowsExternalTerminalService.getDefaultTerminalWindows();
const wt = await WindowsExternalTerminalService.getWtExePath();
return new Promise<number | undefined>((resolve, reject) => {
@ -101,6 +103,11 @@ export class WindowsExternalTerminalService extends ExternalTerminalService impl
// inside it
spawnExec = exec;
cmdArgs = ['-d', '.', WindowsExternalTerminalService.CMD, '/c', command];
} else if (wt) {
// prefer to use the window terminal to spawn if it's available instead
// of start, since that allows ctrl+c handling (#81322)
spawnExec = wt;
cmdArgs = ['-d', dir, exec, '/c', command];
} else {
spawnExec = WindowsExternalTerminalService.CMD;
cmdArgs = ['/c', 'start', title, '/wait', exec, '/c', command];
@ -123,6 +130,16 @@ export class WindowsExternalTerminalService extends ExternalTerminalService impl
}
return WindowsExternalTerminalService._DEFAULT_TERMINAL_WINDOWS;
}
@memoize
private static async getWtExePath() {
try {
const wtPath = await processes.win32.findExecutable('wt');
return await pfs.Promises.exists(wtPath) ? wtPath : undefined;
} catch {
return undefined;
}
}
}
export class MacExternalTerminalService extends ExternalTerminalService implements IExternalTerminalService {