mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-23 19:26:35 +00:00
[debug] Shut down previous session properly before starting a new one
This commit is contained in:
parent
68db44fa49
commit
2ba95947de
@ -0,0 +1,55 @@
|
|||||||
|
import { DebugSessionManager } from "@theia/debug/lib/browser/debug-session-manager";
|
||||||
|
import { DebugSessionOptions } from "@theia/debug/lib/browser/debug-session-options";
|
||||||
|
import { DebugSession } from "@theia/debug/lib/browser/debug-session";
|
||||||
|
|
||||||
|
export class ArduinoDebugSessionManager extends DebugSessionManager {
|
||||||
|
|
||||||
|
static readonly COOL_DOWN_TIME = 5000;
|
||||||
|
|
||||||
|
protected arduinoSession?: Promise<DebugSession | undefined>;
|
||||||
|
protected lastSessionStopTime?: DOMHighResTimeStamp;
|
||||||
|
|
||||||
|
start(options: DebugSessionOptions) {
|
||||||
|
if (options.configuration.type === 'arduino') {
|
||||||
|
if (this.arduinoSession) {
|
||||||
|
this.messageService.info('A debug session is already running. You must stop the running session before starting a new one.')
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
const superStart = super.start.bind(this);
|
||||||
|
const promise = (async resolve => {
|
||||||
|
if (this.lastSessionStopTime) {
|
||||||
|
const now = performance.now();
|
||||||
|
if (now - this.lastSessionStopTime < ArduinoDebugSessionManager.COOL_DOWN_TIME) {
|
||||||
|
const waitTime = ArduinoDebugSessionManager.COOL_DOWN_TIME - Math.max(now - this.lastSessionStopTime, 0);
|
||||||
|
if (waitTime > 2000) {
|
||||||
|
const userWaitTime = Math.round(waitTime / 100) / 10;
|
||||||
|
this.messageService.info(`The previous debug session is cooling down. Waiting ${userWaitTime} seconds before starting a new session...`)
|
||||||
|
}
|
||||||
|
await new Promise(resolve => setTimeout(resolve, waitTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return superStart(options);
|
||||||
|
})();
|
||||||
|
this.arduinoSession = promise;
|
||||||
|
promise.then(session => {
|
||||||
|
if (!session)
|
||||||
|
this.arduinoSession = undefined;
|
||||||
|
});
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
return super.start(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy(sessionId?: string): void {
|
||||||
|
if (this.arduinoSession) {
|
||||||
|
this.arduinoSession.then(session => {
|
||||||
|
if (session && sessionId === session.id) {
|
||||||
|
this.arduinoSession = undefined;
|
||||||
|
this.lastSessionStopTime = performance.now();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
super.destroy(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,14 +1,17 @@
|
|||||||
import { ContainerModule } from 'inversify';
|
import { ContainerModule } from 'inversify';
|
||||||
import { VariableContribution } from '@theia/variable-resolver/lib/browser';
|
import { VariableContribution } from '@theia/variable-resolver/lib/browser';
|
||||||
import { ArduinoVariableResolver } from './arduino-variable-resolver';
|
import { ArduinoVariableResolver } from './arduino-variable-resolver';
|
||||||
|
import { DebugSessionManager } from '@theia/debug/lib/browser/debug-session-manager';
|
||||||
import { DebugFrontendApplicationContribution } from '@theia/debug/lib/browser/debug-frontend-application-contribution';
|
import { DebugFrontendApplicationContribution } from '@theia/debug/lib/browser/debug-frontend-application-contribution';
|
||||||
import { DebugConfigurationManager } from '@theia/debug/lib/browser/debug-configuration-manager';
|
import { DebugConfigurationManager } from '@theia/debug/lib/browser/debug-configuration-manager';
|
||||||
import { ArduinoDebugConfigurationManager } from './arduino-debug-configuration-manager';
|
import { ArduinoDebugConfigurationManager } from './arduino-debug-configuration-manager';
|
||||||
import { ArduinoDebugFrontendApplicationContribution } from './arduino-debug-frontend-application-contribution';
|
import { ArduinoDebugFrontendApplicationContribution } from './arduino-debug-frontend-application-contribution';
|
||||||
|
import { ArduinoDebugSessionManager } from './arduino-debug-session-manager';
|
||||||
|
|
||||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||||
bind(ArduinoVariableResolver).toSelf().inSingletonScope();
|
bind(ArduinoVariableResolver).toSelf().inSingletonScope();
|
||||||
bind(VariableContribution).toService(ArduinoVariableResolver);
|
bind(VariableContribution).toService(ArduinoVariableResolver);
|
||||||
|
rebind(DebugSessionManager).to(ArduinoDebugSessionManager).inSingletonScope();
|
||||||
rebind(DebugConfigurationManager).to(ArduinoDebugConfigurationManager).inSingletonScope();
|
rebind(DebugConfigurationManager).to(ArduinoDebugConfigurationManager).inSingletonScope();
|
||||||
rebind(DebugFrontendApplicationContribution).to(ArduinoDebugFrontendApplicationContribution);
|
rebind(DebugFrontendApplicationContribution).to(ArduinoDebugFrontendApplicationContribution);
|
||||||
});
|
});
|
||||||
|
@ -65,7 +65,7 @@ export class ArduinoDebugAdapterContribution implements DebugAdapterContribution
|
|||||||
args = args.concat([path.join(__dirname, 'debug-adapter', 'main')]);
|
args = args.concat([path.join(__dirname, 'debug-adapter', 'main')]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
command: 'node',
|
command: process.execPath,
|
||||||
args: args,
|
args: args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,11 @@ export abstract class AbstractServer extends EventEmitter {
|
|||||||
protected launchReject?: (error: any) => void;
|
protected launchReject?: (error: any) => void;
|
||||||
protected timer?: NodeJS.Timer;
|
protected timer?: NodeJS.Timer;
|
||||||
|
|
||||||
public spawn(args: CmsisRequestArguments): Promise<void> {
|
get isRunning(): boolean {
|
||||||
|
return !!this.process && !this.process.killed;
|
||||||
|
}
|
||||||
|
|
||||||
|
spawn(args: CmsisRequestArguments): Promise<void> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
this.launchResolve = resolve;
|
this.launchResolve = resolve;
|
||||||
this.launchReject = reject;
|
this.launchReject = reject;
|
||||||
@ -80,7 +84,7 @@ export abstract class AbstractServer extends EventEmitter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public kill() {
|
kill() {
|
||||||
if (this.process) {
|
if (this.process) {
|
||||||
this.process.kill('SIGINT');
|
this.process.kill('SIGINT');
|
||||||
}
|
}
|
||||||
|
@ -262,18 +262,14 @@ export class CmsisDebugSession extends GDBDebugSession {
|
|||||||
this.sendEvent(new OutputEvent(`Starting debugger: ${JSON.stringify(args)}`));
|
this.sendEvent(new OutputEvent(`Starting debugger: ${JSON.stringify(args)}`));
|
||||||
await this.gdbServer.spawn(args);
|
await this.gdbServer.spawn(args);
|
||||||
await this.spawn(args);
|
await this.spawn(args);
|
||||||
if (gdbServerErrors.length > 0) {
|
this.checkServerErrors(gdbServerErrors);
|
||||||
throw new Error(gdbServerErrors.join('\n'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send commands
|
// Send commands
|
||||||
await mi.sendTargetAsyncOn(this.gdb);
|
await mi.sendTargetAsyncOn(this.gdb);
|
||||||
await mi.sendTargetSelectRemote(this.gdb, remote);
|
await mi.sendTargetSelectRemote(this.gdb, remote);
|
||||||
await mi.sendMonitorResetHalt(this.gdb);
|
await mi.sendMonitorResetHalt(this.gdb);
|
||||||
this.sendEvent(new OutputEvent(`Attached to debugger on port ${port}`));
|
this.sendEvent(new OutputEvent(`Attached to debugger on port ${port}`));
|
||||||
if (gdbServerErrors.length > 0) {
|
this.checkServerErrors(gdbServerErrors);
|
||||||
throw new Error(gdbServerErrors.join('\n'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Download image
|
// Download image
|
||||||
const progressListener = (percent: number) => this.progressEvent(percent, 'Loading Image');
|
const progressListener = (percent: number) => this.progressEvent(percent, 'Loading Image');
|
||||||
@ -291,9 +287,7 @@ export class CmsisDebugSession extends GDBDebugSession {
|
|||||||
await mi.sendBreakOnFunction(this.gdb);
|
await mi.sendBreakOnFunction(this.gdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gdbServerErrors.length > 0) {
|
this.checkServerErrors(gdbServerErrors);
|
||||||
throw new Error(gdbServerErrors.join('\n'));
|
|
||||||
}
|
|
||||||
this.sendEvent(new OutputEvent(`Image loaded: ${args.program}`));
|
this.sendEvent(new OutputEvent(`Image loaded: ${args.program}`));
|
||||||
this.sendEvent(new InitializedEvent());
|
this.sendEvent(new InitializedEvent());
|
||||||
|
|
||||||
@ -304,6 +298,12 @@ export class CmsisDebugSession extends GDBDebugSession {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private checkServerErrors(errors: any[]): void {
|
||||||
|
if (errors.length > 0) {
|
||||||
|
throw new Error(errors.join('\n'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected spawn(args: CmsisRequestArguments): Promise<void> {
|
protected spawn(args: CmsisRequestArguments): Promise<void> {
|
||||||
const varRegexp = /\$\{.*\}/;
|
const varRegexp = /\$\{.*\}/;
|
||||||
if (args.gdb && varRegexp.test(args.gdb)) {
|
if (args.gdb && varRegexp.test(args.gdb)) {
|
||||||
@ -427,11 +427,19 @@ export class CmsisDebugSession extends GDBDebugSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stop gdb client and server - we give GDB five seconds to exit orderly before we kill the GDB server
|
// Stop gdb client and server - we give GDB five seconds to exit orderly before we kill the GDB server
|
||||||
setTimeout(() => this.gdbServer.kill(), 5000);
|
if (this.gdbServer.isRunning) {
|
||||||
try {
|
const killPromise = new Promise(resolve => {
|
||||||
await this.gdb.sendGDBExit();
|
setTimeout(() => {
|
||||||
} catch (e) {
|
this.gdbServer.kill();
|
||||||
// Need to catch here in case the connection has already been closed
|
resolve();
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await this.gdb.sendGDBExit();
|
||||||
|
} catch (e) {
|
||||||
|
// Need to catch here in case the connection has already been closed
|
||||||
|
}
|
||||||
|
await killPromise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user