mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-27 05:06:42 +00:00
Improved error detection to catch more cases
This commit is contained in:
parent
3ed72de810
commit
f6a8dceabc
@ -70,8 +70,7 @@ export class ArduinoDebugAdapterContribution implements DebugAdapterContribution
|
|||||||
fqbn: '${fqbn}',
|
fqbn: '${fqbn}',
|
||||||
uploadPort: '${port}',
|
uploadPort: '${port}',
|
||||||
initCommands: [
|
initCommands: [
|
||||||
`-break-insert -t --function ${startFunction}`,
|
`-break-insert -t --function ${startFunction}`
|
||||||
'-interpreter-exec console "monitor reset halt"'
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
if (!res.sketch) {
|
if (!res.sketch) {
|
||||||
|
@ -43,6 +43,7 @@ export class ArduinoDebugSession extends GDBDebugSession {
|
|||||||
|
|
||||||
protected async configurationDoneRequest(response: DebugProtocol.ConfigurationDoneResponse): Promise<void> {
|
protected async configurationDoneRequest(response: DebugProtocol.ConfigurationDoneResponse): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
await this.gdb.sendCommand('-interpreter-exec console "monitor reset halt"')
|
||||||
await mi.sendExecContinue(this.gdb);
|
await mi.sendExecContinue(this.gdb);
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -48,9 +48,9 @@ export class ArduinoGDBBackend extends GDBBackend {
|
|||||||
return this.sendCommand(command);
|
return this.sendCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendStackInfoFrame(gdb: GDBBackend, threadId: number, frameId: number): Promise<{ frame: MIFrameInfo }> {
|
sendStackInfoFrame(threadId: number, frameId: number): Promise<{ frame: MIFrameInfo }> {
|
||||||
const command = `-stack-info-frame --thread ${threadId} --frame ${frameId}`;
|
const command = `-stack-info-frame --thread ${threadId} --frame ${frameId}`;
|
||||||
return gdb.sendCommand(command);
|
return this.sendCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendTargetDetach(): Promise<void> {
|
sendTargetDetach(): Promise<void> {
|
||||||
|
@ -7,26 +7,35 @@ const LINE_REGEX = /(.*)(\r?\n)/;
|
|||||||
|
|
||||||
export class ArduinoParser extends MIParser {
|
export class ArduinoParser extends MIParser {
|
||||||
|
|
||||||
|
protected rejectReady?: (error: Error) => void;
|
||||||
|
|
||||||
parseFull(proc: ChildProcessWithoutNullStreams): Promise<void> {
|
parseFull(proc: ChildProcessWithoutNullStreams): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
// Detect errors when the child process could not be spawned
|
||||||
proc.on('error', reject);
|
proc.on('error', reject);
|
||||||
let ready = false;
|
// Detect hanging process (does not print command prompt or error)
|
||||||
proc.on('exit', () => {
|
|
||||||
if (!ready) {
|
|
||||||
reject(new Error('The gdb debugger terminated unexpectedly.'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
reject(new Error(`No response from gdb after ${READY_TIMEOUT} ms.`));
|
reject(new Error(`No response from gdb after ${READY_TIMEOUT} ms.`));
|
||||||
}, READY_TIMEOUT);
|
}, READY_TIMEOUT);
|
||||||
|
|
||||||
this.waitReady = () => {
|
this.waitReady = () => {
|
||||||
ready = true;
|
this.rejectReady = undefined;
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
|
this.rejectReady = (error: Error) => {
|
||||||
|
this.waitReady = undefined;
|
||||||
|
clearTimeout(timeout);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
// Detect unexpected termination
|
||||||
|
proc.on('exit', () => {
|
||||||
|
if (this.rejectReady) {
|
||||||
|
this.rejectReady(new Error('The gdb debugger terminated unexpectedly.'));
|
||||||
|
}
|
||||||
|
});
|
||||||
this.readInputStream(proc.stdout);
|
this.readInputStream(proc.stdout);
|
||||||
this.readErrorStream(proc.stderr, reject);
|
this.readErrorStream(proc.stderr);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,16 +45,25 @@ export class ArduinoParser extends MIParser {
|
|||||||
buff += chunk.toString();
|
buff += chunk.toString();
|
||||||
let regexArray = LINE_REGEX.exec(buff);
|
let regexArray = LINE_REGEX.exec(buff);
|
||||||
while (regexArray) {
|
while (regexArray) {
|
||||||
this.line = regexArray[1];
|
const line = regexArray[1];
|
||||||
|
this.line = line;
|
||||||
this.pos = 0;
|
this.pos = 0;
|
||||||
this.handleLine();
|
this.handleLine();
|
||||||
|
// Detect error emitted as log message
|
||||||
|
if (line.startsWith('&"error') && this.rejectReady) {
|
||||||
|
this.line = line;
|
||||||
|
this.pos = 0;
|
||||||
|
this.next();
|
||||||
|
this.rejectReady(new Error(this.handleCString() || regexArray[1]));
|
||||||
|
this.rejectReady = undefined;
|
||||||
|
}
|
||||||
buff = buff.substring(regexArray[1].length + regexArray[2].length);
|
buff = buff.substring(regexArray[1].length + regexArray[2].length);
|
||||||
regexArray = LINE_REGEX.exec(buff);
|
regexArray = LINE_REGEX.exec(buff);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private readErrorStream(stream: Readable, reject: (reason?: any) => void) {
|
private readErrorStream(stream: Readable) {
|
||||||
let buff = '';
|
let buff = '';
|
||||||
stream.on('data', chunk => {
|
stream.on('data', chunk => {
|
||||||
buff += chunk.toString();
|
buff += chunk.toString();
|
||||||
@ -53,8 +71,10 @@ export class ArduinoParser extends MIParser {
|
|||||||
while (regexArray) {
|
while (regexArray) {
|
||||||
const line = regexArray[1];
|
const line = regexArray[1];
|
||||||
this.gdb.emit('consoleStreamOutput', line + '\n', 'stderr');
|
this.gdb.emit('consoleStreamOutput', line + '\n', 'stderr');
|
||||||
if (line.toLowerCase().startsWith('error')) {
|
// Detect error emitted on the stderr stream
|
||||||
reject(new Error(line));
|
if (line.toLowerCase().startsWith('error') && this.rejectReady) {
|
||||||
|
this.rejectReady(new Error(line));
|
||||||
|
this.rejectReady = undefined;
|
||||||
}
|
}
|
||||||
buff = buff.substring(regexArray[1].length + regexArray[2].length);
|
buff = buff.substring(regexArray[1].length + regexArray[2].length);
|
||||||
regexArray = LINE_REGEX.exec(buff);
|
regexArray = LINE_REGEX.exec(buff);
|
||||||
|
@ -48,7 +48,7 @@ export class ArduinoVariableHandler {
|
|||||||
async getStaticVariables(frameHandle: number): Promise<DebugProtocol.Variable[]> {
|
async getStaticVariables(frameHandle: number): Promise<DebugProtocol.Variable[]> {
|
||||||
throw new Error('Static variables are not supported yet.');
|
throw new Error('Static variables are not supported yet.');
|
||||||
const frame = this.frameHandles.get(frameHandle);
|
const frame = this.frameHandles.get(frameHandle);
|
||||||
const result = await this.gdb.sendStackInfoFrame(this.gdb, frame.threadId, frame.frameId);
|
const result = await this.gdb.sendStackInfoFrame(frame.threadId, frame.frameId);
|
||||||
const file = path.normalize(result.frame.file || '');
|
const file = path.normalize(result.frame.file || '');
|
||||||
const symbolInfo: any[] = [] // this.symbolTable.getStaticVariables(file);
|
const symbolInfo: any[] = [] // this.symbolTable.getStaticVariables(file);
|
||||||
const variables: DebugProtocol.Variable[] = [];
|
const variables: DebugProtocol.Variable[] = [];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user