rawDebugSession.ts 18.9 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

6
import nls = require('vs/nls');
E
Erich Gamma 已提交
7 8
import cp = require('child_process');
import net = require('net');
J
Johannes Rieken 已提交
9
import Event, { Emitter } from 'vs/base/common/event';
E
Erich Gamma 已提交
10
import platform = require('vs/base/common/platform');
I
isidor 已提交
11
import objects = require('vs/base/common/objects');
J
Johannes Rieken 已提交
12
import { Action } from 'vs/base/common/actions';
E
Erich Gamma 已提交
13
import errors = require('vs/base/common/errors');
J
Johannes Rieken 已提交
14
import { TPromise } from 'vs/base/common/winjs.base';
E
Erich Gamma 已提交
15 16
import severity from 'vs/base/common/severity';
import stdfork = require('vs/base/node/stdFork');
J
Johannes Rieken 已提交
17 18
import { IMessageService, CloseAction } from 'vs/platform/message/common/message';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
19
import { ITerminalService } from 'vs/workbench/parts/terminal/common/terminal';
J
Johannes Rieken 已提交
20
import { ITerminalService as IExternalTerminalService } from 'vs/workbench/parts/execution/common/execution';
21
import debug = require('vs/workbench/parts/debug/common/debug');
J
Johannes Rieken 已提交
22
import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter';
23
import v8 = require('vs/workbench/parts/debug/node/v8Protocol');
J
Johannes Rieken 已提交
24 25 26 27
import { IOutputService } from 'vs/workbench/parts/output/common/output';
import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement';
import { TerminalSupport } from 'vs/workbench/parts/debug/electron-browser/terminalSupport';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
28

29 30 31 32 33 34 35 36 37 38 39 40 41 42
export interface SessionExitedEvent extends DebugProtocol.ExitedEvent {
	body: {
		exitCode: number,
		sessionId: string
	};
}

export interface SessionTerminatedEvent extends DebugProtocol.TerminatedEvent {
	body: {
		restart?: boolean,
		sessionId: string
	};
}

43
export class RawDebugSession extends v8.V8Protocol implements debug.ISession {
I
isidor 已提交
44

45 46
	public emittedStopped: boolean;
	public readyForBreakpoints: boolean;
I
isidor 已提交
47

E
Erich Gamma 已提交
48 49
	private serverProcess: cp.ChildProcess;
	private socket: net.Socket = null;
I
isidor 已提交
50
	private cachedInitServer: TPromise<void>;
E
Erich Gamma 已提交
51
	private startTime: number;
52
	public disconnected: boolean;
53
	private sentPromises: TPromise<DebugProtocol.Response>[];
54
	private _capabilities: DebugProtocol.Capabilities;
I
isidor 已提交
55
	private allThreadsContinued: boolean;
E
Erich Gamma 已提交
56

57 58
	private _onDidInitialize: Emitter<DebugProtocol.InitializedEvent>;
	private _onDidStop: Emitter<DebugProtocol.StoppedEvent>;
I
isidor 已提交
59
	private _onDidContinued: Emitter<DebugProtocol.ContinuedEvent>;
60 61
	private _onDidTerminateDebugee: Emitter<SessionTerminatedEvent>;
	private _onDidExitAdapter: Emitter<SessionExitedEvent>;
62 63 64
	private _onDidThread: Emitter<DebugProtocol.ThreadEvent>;
	private _onDidOutput: Emitter<DebugProtocol.OutputEvent>;
	private _onDidBreakpoint: Emitter<DebugProtocol.BreakpointEvent>;
65
	private _onDidEvent: Emitter<DebugProtocol.Event>;
66

E
Erich Gamma 已提交
67
	constructor(
I
isidor 已提交
68
		id: string,
E
Erich Gamma 已提交
69
		private debugServerPort: number,
70
		private adapter: Adapter,
71
		private customTelemetryService: ITelemetryService,
72 73
		@IMessageService private messageService: IMessageService,
		@ITelemetryService private telemetryService: ITelemetryService,
74
		@IOutputService private outputService: IOutputService,
75
		@ITerminalService private terminalService: ITerminalService,
76 77
		@IExternalTerminalService private nativeTerminalService: IExternalTerminalService,
		@IConfigurationService private configurationService: IConfigurationService
E
Erich Gamma 已提交
78
	) {
I
isidor 已提交
79
		super(id);
80 81
		this.emittedStopped = false;
		this.readyForBreakpoints = false;
I
isidor 已提交
82
		this.allThreadsContinued = false;
83
		this.sentPromises = [];
84 85 86

		this._onDidInitialize = new Emitter<DebugProtocol.InitializedEvent>();
		this._onDidStop = new Emitter<DebugProtocol.StoppedEvent>();
I
isidor 已提交
87
		this._onDidContinued = new Emitter<DebugProtocol.ContinuedEvent>();
88 89
		this._onDidTerminateDebugee = new Emitter<SessionTerminatedEvent>();
		this._onDidExitAdapter = new Emitter<SessionExitedEvent>();
90 91 92
		this._onDidThread = new Emitter<DebugProtocol.ThreadEvent>();
		this._onDidOutput = new Emitter<DebugProtocol.OutputEvent>();
		this._onDidBreakpoint = new Emitter<DebugProtocol.BreakpointEvent>();
93
		this._onDidEvent = new Emitter<DebugProtocol.Event>();
94 95 96 97 98 99 100 101 102 103
	}

	public get onDidInitialize(): Event<DebugProtocol.InitializedEvent> {
		return this._onDidInitialize.event;
	}

	public get onDidStop(): Event<DebugProtocol.StoppedEvent> {
		return this._onDidStop.event;
	}

I
isidor 已提交
104 105 106 107
	public get onDidContinued(): Event<DebugProtocol.ContinuedEvent> {
		return this._onDidContinued.event;
	}

108
	public get onDidTerminateDebugee(): Event<SessionTerminatedEvent> {
109 110 111
		return this._onDidTerminateDebugee.event;
	}

112
	public get onDidExitAdapter(): Event<SessionExitedEvent> {
113 114 115 116 117 118 119 120 121 122 123 124 125
		return this._onDidExitAdapter.event;
	}

	public get onDidThread(): Event<DebugProtocol.ThreadEvent> {
		return this._onDidThread.event;
	}

	public get onDidOutput(): Event<DebugProtocol.OutputEvent> {
		return this._onDidOutput.event;
	}

	public get onDidBreakpoint(): Event<DebugProtocol.BreakpointEvent> {
		return this._onDidBreakpoint.event;
E
Erich Gamma 已提交
126 127
	}

128 129 130 131
	public get onDidEvent(): Event<DebugProtocol.Event> {
		return this._onDidEvent.event;
	}

I
isidor 已提交
132
	private initServer(): TPromise<void> {
E
Erich Gamma 已提交
133 134 135 136 137 138
		if (this.cachedInitServer) {
			return this.cachedInitServer;
		}

		const serverPromise = this.debugServerPort ? this.connectServer(this.debugServerPort) : this.startServer();
		this.cachedInitServer = serverPromise.then(() => {
J
Johannes Rieken 已提交
139 140 141 142
			this.startTime = new Date().getTime();
		}, err => {
			this.cachedInitServer = null;
			return TPromise.wrapError(err);
143
		});
E
Erich Gamma 已提交
144 145 146 147

		return this.cachedInitServer;
	}

148 149 150 151
	public custom(request: string, args: any): TPromise<DebugProtocol.Response> {
		return this.send(request, args);
	}

152
	protected send<R extends DebugProtocol.Response>(command: string, args: any, cancelOnDisconnect = true): TPromise<R> {
153
		return this.initServer().then(() => {
154
			const promise = super.send<R>(command, args).then(response => response, (errorResponse: DebugProtocol.ErrorResponse) => {
155 156 157
				const error = errorResponse && errorResponse.body ? errorResponse.body.error : null;
				const errorMessage = errorResponse ? errorResponse.message : '';
				const telemetryMessage = error ? debug.formatPII(error.format, true, error.variables) : errorMessage;
158
				if (error && error.sendTelemetry) {
159
					this.telemetryService.publicLog('debugProtocolErrorResponse', { error: telemetryMessage });
160
					if (this.customTelemetryService) {
161
						this.customTelemetryService.publicLog('debugProtocolErrorResponse', { error: telemetryMessage });
J
Joao Moreno 已提交
162
					}
163
				}
E
Erich Gamma 已提交
164

165
				const userMessage = error ? debug.formatPII(error.format, false, error.variables) : errorMessage;
166 167
				if (error && error.url) {
					const label = error.urlLabel ? error.urlLabel : nls.localize('moreInfo', "More Info");
168
					return TPromise.wrapError<R>(errors.create(userMessage, {
J
Johannes Rieken 已提交
169
						actions: [CloseAction, new Action('debug.moreInfo', label, null, true, () => {
B
Benjamin Pasero 已提交
170
							window.open(error.url);
J
Johannes Rieken 已提交
171 172 173
							return TPromise.as(null);
						})]
					}));
174 175
				}

176
				return errors.isPromiseCanceledError(errorResponse) ? undefined : TPromise.wrapError<R>(new Error(userMessage));
177
			});
178

179 180 181
			if (cancelOnDisconnect) {
				this.sentPromises.push(promise);
			}
182 183
			return promise;
		});
E
Erich Gamma 已提交
184 185
	}

186 187 188 189 190 191 192 193 194 195 196 197 198
	protected onEvent(event: DebugProtocol.Event): void {
		if (event.body) {
			event.body.sessionId = this.getId();
		} else {
			event.body = { sessionId: this.getId() };
		}

		if (event.event === 'initialized') {
			this.readyForBreakpoints = true;
			this._onDidInitialize.fire(event);
		} else if (event.event === 'stopped') {
			this.emittedStopped = true;
			this._onDidStop.fire(<DebugProtocol.StoppedEvent>event);
I
isidor 已提交
199
		} else if (event.event === 'continued') {
I
isidor 已提交
200
			this.allThreadsContinued = (<DebugProtocol.ContinuedEvent>event).body.allThreadsContinued = false ? false : true;
I
isidor 已提交
201
			this._onDidContinued.fire(<DebugProtocol.ContinuedEvent>event);
202 203 204 205 206 207 208
		} else if (event.event === 'thread') {
			this._onDidThread.fire(<DebugProtocol.ThreadEvent>event);
		} else if (event.event === 'output') {
			this._onDidOutput.fire(<DebugProtocol.OutputEvent>event);
		} else if (event.event === 'breakpoint') {
			this._onDidBreakpoint.fire(<DebugProtocol.BreakpointEvent>event);
		} else if (event.event === 'terminated') {
209
			this._onDidTerminateDebugee.fire(<SessionTerminatedEvent>event);
210
		} else if (event.event === 'exit') {
211
			this._onDidExitAdapter.fire(<SessionExitedEvent>event);
212
		}
213 214

		this._onDidEvent.fire(event);
215 216
	}

217 218
	public get capabilities(): DebugProtocol.Capabilities {
		return this._capabilities || {};
I
isidor 已提交
219 220
	}

E
Erich Gamma 已提交
221
	public initialize(args: DebugProtocol.InitializeRequestArguments): TPromise<DebugProtocol.InitializeResponse> {
222 223 224 225
		return this.send('initialize', args).then(response => this.readCapabilities(response));
	}

	private readCapabilities(response: DebugProtocol.Response): DebugProtocol.Response {
226
		if (response) {
227
			this._capabilities = objects.mixin(this._capabilities, response.body);
228 229
		}

230
		return response;
E
Erich Gamma 已提交
231 232 233
	}

	public launch(args: DebugProtocol.LaunchRequestArguments): TPromise<DebugProtocol.LaunchResponse> {
234
		return this.send('launch', args).then(response => this.readCapabilities(response));
E
Erich Gamma 已提交
235 236 237
	}

	public attach(args: DebugProtocol.AttachRequestArguments): TPromise<DebugProtocol.AttachResponse> {
238
		return this.send('attach', args).then(response => this.readCapabilities(response));
E
Erich Gamma 已提交
239 240
	}

241
	public next(args: DebugProtocol.NextArguments): TPromise<DebugProtocol.NextResponse> {
242 243 244 245
		return this.send('next', args).then(response => {
			this.fireFakeContinued(args.threadId);
			return response;
		});
E
Erich Gamma 已提交
246 247 248
	}

	public stepIn(args: DebugProtocol.StepInArguments): TPromise<DebugProtocol.StepInResponse> {
249 250 251 252
		return this.send('stepIn', args).then(response => {
			this.fireFakeContinued(args.threadId);
			return response;
		});
E
Erich Gamma 已提交
253 254 255
	}

	public stepOut(args: DebugProtocol.StepOutArguments): TPromise<DebugProtocol.StepOutResponse> {
256 257 258 259
		return this.send('stepOut', args).then(response => {
			this.fireFakeContinued(args.threadId);
			return response;
		});
E
Erich Gamma 已提交
260 261 262
	}

	public continue(args: DebugProtocol.ContinueArguments): TPromise<DebugProtocol.ContinueResponse> {
263
		return this.send<DebugProtocol.ContinueResponse>('continue', args).then(response => {
I
isidor 已提交
264
			this.fireFakeContinued(args.threadId, this.allThreadsContinued);
265 266
			return response;
		});
E
Erich Gamma 已提交
267 268 269 270 271 272
	}

	public pause(args: DebugProtocol.PauseArguments): TPromise<DebugProtocol.PauseResponse> {
		return this.send('pause', args);
	}

A
Andre Weinand 已提交
273
	public setVariable(args: DebugProtocol.SetVariableArguments): TPromise<DebugProtocol.SetVariableResponse> {
274
		return this.send<DebugProtocol.SetVariableResponse>('setVariable', args);
I
isidor 已提交
275 276
	}

I
isidor 已提交
277 278 279 280 281
	public restartFrame(args: DebugProtocol.RestartFrameArguments, threadId: number): TPromise<DebugProtocol.RestartFrameResponse> {
		return this.send('restartFrame', args).then(response => {
			this.fireFakeContinued(threadId);
			return response;
		});;
A
Andre Weinand 已提交
282 283
	}

I
isidor 已提交
284
	public completions(args: DebugProtocol.CompletionsArguments): TPromise<DebugProtocol.CompletionsResponse> {
285
		return this.send<DebugProtocol.CompletionsResponse>('completions', args);
I
isidor 已提交
286 287
	}

288
	public disconnect(restart = false, force = false): TPromise<DebugProtocol.DisconnectResponse> {
289
		if (this.disconnected && force) {
290 291
			return this.stopServer();
		}
292

293
		// Cancel all sent promises on disconnect so debug trees are not left in a broken state #3666.
294 295
		// Give a 1s timeout to give a chance for some promises to complete.
		setTimeout(() => {
I
isidor 已提交
296
			this.sentPromises.forEach(p => p && p.cancel());
297 298
			this.sentPromises = [];
		}, 1000);
299

300
		if ((this.serverProcess || this.socket) && !this.disconnected) {
301
			// point of no return: from now on don't report any errors
302
			this.disconnected = true;
303
			return this.send('disconnect', { restart: restart }, false).then(() => this.stopServer(), () => this.stopServer());
E
Erich Gamma 已提交
304 305
		}

A
Alex Dima 已提交
306
		return TPromise.as(null);
E
Erich Gamma 已提交
307 308 309
	}

	public setBreakpoints(args: DebugProtocol.SetBreakpointsArguments): TPromise<DebugProtocol.SetBreakpointsResponse> {
310
		return this.send<DebugProtocol.SetBreakpointsResponse>('setBreakpoints', args);
E
Erich Gamma 已提交
311 312
	}

I
isidor 已提交
313
	public setFunctionBreakpoints(args: DebugProtocol.SetFunctionBreakpointsArguments): TPromise<DebugProtocol.SetFunctionBreakpointsResponse> {
314
		return this.send<DebugProtocol.SetFunctionBreakpointsResponse>('setFunctionBreakpoints', args);
I
isidor 已提交
315 316
	}

E
Erich Gamma 已提交
317
	public setExceptionBreakpoints(args: DebugProtocol.SetExceptionBreakpointsArguments): TPromise<DebugProtocol.SetExceptionBreakpointsResponse> {
318
		return this.send<DebugProtocol.SetExceptionBreakpointsResponse>('setExceptionBreakpoints', args);
E
Erich Gamma 已提交
319 320
	}

321 322 323 324
	public configurationDone(): TPromise<DebugProtocol.ConfigurationDoneResponse> {
		return this.send('configurationDone', null);
	}

E
Erich Gamma 已提交
325
	public stackTrace(args: DebugProtocol.StackTraceArguments): TPromise<DebugProtocol.StackTraceResponse> {
326
		return this.send<DebugProtocol.StackTraceResponse>('stackTrace', args);
E
Erich Gamma 已提交
327 328
	}

329
	public exceptionInfo(args: DebugProtocol.ExceptionInfoArguments): TPromise<DebugProtocol.ExceptionInfoResponse> {
330
		return this.send<DebugProtocol.ExceptionInfoResponse>('exceptionInfo', args);
331 332
	}

E
Erich Gamma 已提交
333
	public scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse> {
334
		return this.send<DebugProtocol.ScopesResponse>('scopes', args);
E
Erich Gamma 已提交
335 336
	}

337
	public variables(args: DebugProtocol.VariablesArguments): TPromise<DebugProtocol.VariablesResponse> {
338
		return this.send<DebugProtocol.VariablesResponse>('variables', args);
E
Erich Gamma 已提交
339 340
	}

341
	public source(args: DebugProtocol.SourceArguments): TPromise<DebugProtocol.SourceResponse> {
342
		return this.send<DebugProtocol.SourceResponse>('source', args);
E
Erich Gamma 已提交
343 344 345
	}

	public threads(): TPromise<DebugProtocol.ThreadsResponse> {
346
		return this.send<DebugProtocol.ThreadsResponse>('threads', null);
E
Erich Gamma 已提交
347 348 349
	}

	public evaluate(args: DebugProtocol.EvaluateArguments): TPromise<DebugProtocol.EvaluateResponse> {
350
		return this.send<DebugProtocol.EvaluateResponse>('evaluate', args);
E
Erich Gamma 已提交
351 352
	}

I
isidor 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365 366
	public stepBack(args: DebugProtocol.StepBackArguments): TPromise<DebugProtocol.StepBackResponse> {
		return this.send('stepBack', args).then(response => {
			this.fireFakeContinued(args.threadId);
			return response;
		});
	}

	public reverseContinue(args: DebugProtocol.ReverseContinueArguments): TPromise<DebugProtocol.ReverseContinueResponse> {
		return this.send('reverseContinue', args).then(response => {
			this.fireFakeContinued(args.threadId);
			return response;
		});
	}

E
Erich Gamma 已提交
367 368 369 370
	public getLengthInSeconds(): number {
		return (new Date().getTime() - this.startTime) / 1000;
	}

371
	protected dispatchRequest(request: DebugProtocol.Request, response: DebugProtocol.Response): void {
372 373

		if (request.command === 'runInTerminal') {
374

375
			TerminalSupport.runInTerminal(this.terminalService, this.nativeTerminalService, this.configurationService, <DebugProtocol.RunInTerminalRequestArguments>request.arguments, <DebugProtocol.RunInTerminalResponse>response).then(() => {
376 377 378
				this.sendResponse(response);
			}, e => {
				response.success = false;
379
				response.message = e.message;
380 381
				this.sendResponse(response);
			});
A
Andre Weinand 已提交
382 383
		} else if (request.command === 'handshake') {
			try {
A
Andre Weinand 已提交
384
				const vsda = <any>require.__$__nodeRequire('vsda');
A
Andre Weinand 已提交
385 386 387 388 389 390 391 392 393 394 395
				const obj = new vsda.signer();
				const sig = obj.sign(request.arguments.value);
				response.body = {
					signature: sig
				};
				this.sendResponse(response);
			} catch (e) {
				response.success = false;
				response.message = e.message;
				this.sendResponse(response);
			}
396
		} else {
397 398 399
			response.success = false;
			response.message = `unknown request '${request.command}'`;
			this.sendResponse(response);
400
		}
401 402
	}

I
isidor 已提交
403
	private fireFakeContinued(threadId: number, allThreadsContinued = false): void {
404 405 406 407
		this._onDidContinued.fire({
			type: 'event',
			event: 'continued',
			body: {
I
isidor 已提交
408 409
				threadId,
				allThreadsContinued
410 411 412 413 414
			},
			seq: undefined
		});
	}

I
isidor 已提交
415 416
	private connectServer(port: number): TPromise<void> {
		return new TPromise<void>((c, e) => {
417
			this.socket = net.createConnection(port, '127.0.0.1', () => {
E
Erich Gamma 已提交
418 419 420 421 422 423
				this.connect(this.socket, <any>this.socket);
				c(null);
			});
			this.socket.on('error', (err: any) => {
				e(err);
			});
I
isidor 已提交
424
			this.socket.on('close', () => this.onServerExit());
E
Erich Gamma 已提交
425 426 427
		});
	}

I
isidor 已提交
428
	private startServer(): TPromise<any> {
A
Andre Weinand 已提交
429
		return this.adapter.getAdapterExecutable().then(ae => this.launchServer(ae).then(() => {
E
Erich Gamma 已提交
430 431 432
			this.serverProcess.on('error', (err: Error) => this.onServerError(err));
			this.serverProcess.on('exit', (code: number, signal: string) => this.onServerExit());

I
isidor 已提交
433 434 435 436
			const sanitize = (s: string) => s.toString().replace(/\r?\n$/mg, '');
			// this.serverProcess.stdout.on('data', (data: string) => {
			// 	console.log('%c' + sanitize(data), 'background: #ddd; font-style: italic;');
			// });
E
Erich Gamma 已提交
437
			this.serverProcess.stderr.on('data', (data: string) => {
438
				this.outputService.getChannel(ExtensionsChannelId).append(sanitize(data));
E
Erich Gamma 已提交
439 440 441 442 443 444
			});

			this.connect(this.serverProcess.stdout, this.serverProcess.stdin);
		}));
	}

445
	private launchServer(launch: debug.IAdapterExecutable): TPromise<void> {
I
isidor 已提交
446
		return new TPromise<void>((c, e) => {
E
Erich Gamma 已提交
447
			if (launch.command === 'node') {
448 449 450 451 452 453 454 455 456 457 458
				if (Array.isArray(launch.args) && launch.args.length > 0) {
					stdfork.fork(launch.args[0], launch.args.slice(1), {}, (err, child) => {
						if (err) {
							e(new Error(nls.localize('unableToLaunchDebugAdapter', "Unable to launch debug adapter from '{0}'.", launch.args[0])));
						}
						this.serverProcess = child;
						c(null);
					});
				} else {
					e(new Error(nls.localize('unableToLaunchDebugAdapterNoArgs', "Unable to launch debug adapter.")));
				}
E
Erich Gamma 已提交
459
			} else {
460
				this.serverProcess = cp.spawn(launch.command, launch.args, {
E
Erich Gamma 已提交
461 462 463 464 465 466
					stdio: [
						'pipe', 	// stdin
						'pipe', 	// stdout
						'pipe'		// stderr
					],
				});
I
isidor 已提交
467
				c(null);
E
Erich Gamma 已提交
468 469 470 471
			}
		});
	}

I
isidor 已提交
472
	private stopServer(): TPromise<any> {
E
Erich Gamma 已提交
473 474 475 476 477 478

		if (this.socket !== null) {
			this.socket.end();
			this.cachedInitServer = null;
		}

479
		this.onEvent({ event: 'exit', type: 'event', seq: 0 });
E
Erich Gamma 已提交
480
		if (!this.serverProcess) {
I
isidor 已提交
481
			return TPromise.as(null);
E
Erich Gamma 已提交
482 483
		}

484
		this.disconnected = true;
E
Erich Gamma 已提交
485

I
isidor 已提交
486
		let ret: TPromise<void>;
E
Erich Gamma 已提交
487 488 489 490
		// when killing a process in windows its child
		// processes are *not* killed but become root
		// processes. Therefore we use TASKKILL.EXE
		if (platform.isWindows) {
I
isidor 已提交
491
			ret = new TPromise<void>((c, e) => {
I
isidor 已提交
492
				const killer = cp.exec(`taskkill /F /T /PID ${this.serverProcess.pid}`, function (err, stdout, stderr) {
E
Erich Gamma 已提交
493 494 495 496 497 498 499 500 501
					if (err) {
						return e(err);
					}
				});
				killer.on('exit', c);
				killer.on('error', e);
			});
		} else {
			this.serverProcess.kill('SIGTERM');
I
isidor 已提交
502
			ret = TPromise.as(null);
E
Erich Gamma 已提交
503 504 505 506 507
		}

		return ret;
	}

508 509
	protected onServerError(err: Error): void {
		this.messageService.show(severity.Error, nls.localize('stoppingDebugAdapter', "{0}. Stopping the debug adapter.", err.message));
E
Erich Gamma 已提交
510 511 512 513 514 515
		this.stopServer().done(null, errors.onUnexpectedError);
	}

	private onServerExit(): void {
		this.serverProcess = null;
		this.cachedInitServer = null;
516
		if (!this.disconnected) {
517
			this.messageService.show(severity.Error, nls.localize('debugAdapterCrash', "Debug adapter process has terminated unexpectedly"));
E
Erich Gamma 已提交
518
		}
519
		this.onEvent({ event: 'exit', type: 'event', seq: 0 });
E
Erich Gamma 已提交
520
	}
I
isidor 已提交
521 522 523 524

	public dispose(): void {
		this.disconnect().done(null, errors.onUnexpectedError);
	}
E
Erich Gamma 已提交
525
}