Skip to content

Commit ecdfedb

Browse files
committed
Fixes microsoft#10237: 任务终止不了
1 parent 5121f5b commit ecdfedb

3 files changed

Lines changed: 36 additions & 11 deletions

File tree

src/vs/base/common/processes.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,17 @@ export interface ErrorData {
8585

8686
export interface TerminateResponse {
8787
success: boolean;
88+
code?: TerminateResponseCode;
8889
error?: any;
8990
}
9091

92+
export enum TerminateResponseCode {
93+
Success = 0,
94+
Unknown = 1,
95+
AccessDenied = 2,
96+
ProcessNotFound = 3,
97+
}
98+
9199
export namespace Config {
92100
/**
93101
* Options to be passed to the external program or shell

src/vs/base/node/processes.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import * as TPath from 'vs/base/common/paths';
2424
import * as Platform from 'vs/base/common/platform';
2525

2626
import { LineDecoder } from 'vs/base/node/decoder';
27-
import { CommandOptions, ForkOptions, SuccessData, Source, TerminateResponse, Executable } from 'vs/base/common/processes';
28-
export { CommandOptions, ForkOptions, SuccessData, Source, TerminateResponse };
27+
import { CommandOptions, ForkOptions, SuccessData, Source, TerminateResponse, TerminateResponseCode, Executable } from 'vs/base/common/processes';
28+
export { CommandOptions, ForkOptions, SuccessData, Source, TerminateResponse, TerminateResponseCode };
2929

3030
export interface LineData {
3131
line: string;
@@ -43,26 +43,36 @@ export interface StreamData {
4343
stderr: NodeJS.ReadableStream;
4444
}
4545

46+
function getWindowsCode(status: number): TerminateResponseCode {
47+
switch (status) {
48+
case 0:
49+
return TerminateResponseCode.Success;
50+
case 1:
51+
return TerminateResponseCode.AccessDenied;
52+
case 128:
53+
return TerminateResponseCode.ProcessNotFound;
54+
default:
55+
return TerminateResponseCode.Unknown;
56+
}
57+
}
58+
4659
export function terminateProcess(process: ChildProcess, cwd?: string): TerminateResponse {
4760
if (Platform.isWindows) {
4861
try {
49-
// This we run in Electron execFileSync is available.
50-
// Ignore stderr since this is otherwise piped to parent.stderr
51-
// which might be already closed.
5262
let options:any = {
5363
stdio: ['pipe', 'pipe', 'ignore']
5464
};
5565
if (cwd) {
5666
options.cwd = cwd;
5767
}
58-
(<any>cp).execFileSync('taskkill', ['/T', '/F', '/PID', process.pid.toString()], options);
68+
cp.execFileSync('taskkill', ['/T', '/F', '/PID', process.pid.toString()], options);
5969
} catch (err) {
60-
return { success: false, error: err };
70+
return { success: false, error: err , code: err.status ? getWindowsCode(err.status) : TerminateResponseCode.Unknown };
6171
}
6272
} else if (Platform.isLinux || Platform.isMacintosh) {
6373
try {
6474
let cmd = URI.parse(require.toUrl('vs/base/node/terminateProcess.sh')).fsPath;
65-
let result = (<any>cp).spawnSync(cmd, [process.pid.toString()]);
75+
let result = cp.spawnSync(cmd, [process.pid.toString()]);
6676
if (result.error) {
6777
return { success: false, error: result.error };
6878
}

src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import * as Types from 'vs/base/common/types';
2323
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
2424
import { match } from 'vs/base/common/glob';
2525
import { setTimeout } from 'vs/base/common/platform';
26-
import { TerminateResponse } from 'vs/base/common/processes';
26+
import { TerminateResponse, TerminateResponseCode } from 'vs/base/common/processes';
2727
import * as strings from 'vs/base/common/strings';
2828

2929
import { Registry } from 'vs/platform/platform';
@@ -77,8 +77,8 @@ class AbstractTaskAction extends Action {
7777

7878
protected taskService: ITaskService;
7979
protected telemetryService: ITelemetryService;
80-
private messageService: IMessageService;
81-
private contextService: IWorkspaceContextService;
80+
protected messageService: IMessageService;
81+
protected contextService: IWorkspaceContextService;
8282

8383
constructor(id:string, label:string, @ITaskService taskService:ITaskService,
8484
@ITelemetryService telemetryService: ITelemetryService,
@@ -309,6 +309,8 @@ class TerminateAction extends AbstractTaskAction {
309309
return this.taskService.terminate().then((response) => {
310310
if (response.success) {
311311
return;
312+
} else if (response.code && response.code === TerminateResponseCode.ProcessNotFound) {
313+
this.messageService.show(Severity.Error, nls.localize('TerminateAction.noProcess', 'The launched process doesn\'t exist anymore. If the task spawned background tasks exiting VS Code might result in orphaned processes.'));
312314
} else {
313315
return Promise.wrapError(nls.localize('TerminateAction.failed', 'Failed to terminate running task'));
314316
}
@@ -859,6 +861,11 @@ class TaskService extends EventEmitter implements ITaskService {
859861
this.disposeFileChangesListener();
860862
this.disposeTaskSystemListeners();
861863
return false; // no veto
864+
} else if (response.code && response.code === TerminateResponseCode.ProcessNotFound) {
865+
return !this.messageService.confirm({
866+
message: nls.localize('TaskSystem.noProcess', 'The launched task doesn\'t exist anymore. If the task spawned background processes exiting VS Code might result in orphaned processes. To avoid this start the last background process with a wait flag.'),
867+
primaryButton: nls.localize({ key: 'TaskSystem.exitAnyways', comment: ['&& denotes a mnemonic'] }, "&&Exit Anyways")
868+
});
862869
}
863870
return true; // veto
864871
}, (err) => {

0 commit comments

Comments
 (0)