Skip to content

Commit

Permalink
Fixes #10237: 任务终止不了
Browse files Browse the repository at this point in the history
  • Loading branch information
dbaeumer committed Aug 26, 2016
1 parent 5121f5b commit ecdfedb
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 11 deletions.
8 changes: 8 additions & 0 deletions src/vs/base/common/processes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,17 @@ export interface ErrorData {

export interface TerminateResponse {
success: boolean;
code?: TerminateResponseCode;
error?: any;
}

export enum TerminateResponseCode {
Success = 0,
Unknown = 1,
AccessDenied = 2,
ProcessNotFound = 3,
}

export namespace Config {
/**
* Options to be passed to the external program or shell
Expand Down
26 changes: 18 additions & 8 deletions src/vs/base/node/processes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import * as TPath from 'vs/base/common/paths';
import * as Platform from 'vs/base/common/platform';

import { LineDecoder } from 'vs/base/node/decoder';
import { CommandOptions, ForkOptions, SuccessData, Source, TerminateResponse, Executable } from 'vs/base/common/processes';
export { CommandOptions, ForkOptions, SuccessData, Source, TerminateResponse };
import { CommandOptions, ForkOptions, SuccessData, Source, TerminateResponse, TerminateResponseCode, Executable } from 'vs/base/common/processes';
export { CommandOptions, ForkOptions, SuccessData, Source, TerminateResponse, TerminateResponseCode };

export interface LineData {
line: string;
Expand All @@ -43,26 +43,36 @@ export interface StreamData {
stderr: NodeJS.ReadableStream;
}

function getWindowsCode(status: number): TerminateResponseCode {
switch (status) {
case 0:
return TerminateResponseCode.Success;
case 1:
return TerminateResponseCode.AccessDenied;
case 128:
return TerminateResponseCode.ProcessNotFound;
default:
return TerminateResponseCode.Unknown;
}
}

export function terminateProcess(process: ChildProcess, cwd?: string): TerminateResponse {
if (Platform.isWindows) {
try {
// This we run in Electron execFileSync is available.
// Ignore stderr since this is otherwise piped to parent.stderr
// which might be already closed.
let options:any = {
stdio: ['pipe', 'pipe', 'ignore']
};
if (cwd) {
options.cwd = cwd;
}
(<any>cp).execFileSync('taskkill', ['/T', '/F', '/PID', process.pid.toString()], options);
cp.execFileSync('taskkill', ['/T', '/F', '/PID', process.pid.toString()], options);
} catch (err) {
return { success: false, error: err };
return { success: false, error: err , code: err.status ? getWindowsCode(err.status) : TerminateResponseCode.Unknown };
}
} else if (Platform.isLinux || Platform.isMacintosh) {
try {
let cmd = URI.parse(require.toUrl('vs/base/node/terminateProcess.sh')).fsPath;
let result = (<any>cp).spawnSync(cmd, [process.pid.toString()]);
let result = cp.spawnSync(cmd, [process.pid.toString()]);
if (result.error) {
return { success: false, error: result.error };
}
Expand Down
13 changes: 10 additions & 3 deletions src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import * as Types from 'vs/base/common/types';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { match } from 'vs/base/common/glob';
import { setTimeout } from 'vs/base/common/platform';
import { TerminateResponse } from 'vs/base/common/processes';
import { TerminateResponse, TerminateResponseCode } from 'vs/base/common/processes';
import * as strings from 'vs/base/common/strings';

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

protected taskService: ITaskService;
protected telemetryService: ITelemetryService;
private messageService: IMessageService;
private contextService: IWorkspaceContextService;
protected messageService: IMessageService;
protected contextService: IWorkspaceContextService;

constructor(id:string, label:string, @ITaskService taskService:ITaskService,
@ITelemetryService telemetryService: ITelemetryService,
Expand Down Expand Up @@ -309,6 +309,8 @@ class TerminateAction extends AbstractTaskAction {
return this.taskService.terminate().then((response) => {
if (response.success) {
return;
} else if (response.code && response.code === TerminateResponseCode.ProcessNotFound) {
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.'));
} else {
return Promise.wrapError(nls.localize('TerminateAction.failed', 'Failed to terminate running task'));
}
Expand Down Expand Up @@ -859,6 +861,11 @@ class TaskService extends EventEmitter implements ITaskService {
this.disposeFileChangesListener();
this.disposeTaskSystemListeners();
return false; // no veto
} else if (response.code && response.code === TerminateResponseCode.ProcessNotFound) {
return !this.messageService.confirm({
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.'),
primaryButton: nls.localize({ key: 'TaskSystem.exitAnyways', comment: ['&& denotes a mnemonic'] }, "&&Exit Anyways")
});
}
return true; // veto
}, (err) => {
Expand Down

0 comments on commit ecdfedb

Please sign in to comment.