Skip to content

Commit 3ed72de

Browse files
committed
Detect errors in spawned process
1 parent 2d9fa56 commit 3ed72de

File tree

3 files changed

+72
-10
lines changed

3 files changed

+72
-10
lines changed

arduino-debugger-extension/src/node/debug-adapter/arduino-debug-session.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,6 @@ export class ArduinoDebugSession extends GDBDebugSession {
6565
}
6666
}
6767

68-
protected async stackTraceRequest(response: DebugProtocol.StackTraceResponse, args: DebugProtocol.StackTraceArguments): Promise<void> {
69-
try {
70-
71-
return super.stackTraceRequest(response, args);
72-
} catch (err) {
73-
this.sendErrorResponse(response, 1, err.message);
74-
}
75-
}
76-
7768
protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void {
7869
try {
7970
const frame: FrameVariableReference = {

arduino-debugger-extension/src/node/debug-adapter/arduino-gdb-backend.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@ import { spawn } from 'child_process';
44
import { GDBBackend } from 'cdt-gdb-adapter/dist/GDBBackend';
55
import { MIFrameInfo } from 'cdt-gdb-adapter/dist/mi';
66
import { ArduinoLaunchRequestArguments } from './arduino-debug-session';
7+
import { ArduinoParser } from './arduino-parser';
78

89
export class ArduinoGDBBackend extends GDBBackend {
910

11+
constructor() {
12+
super();
13+
this.parser = new ArduinoParser(this);
14+
}
15+
1016
spawn(requestArgs: ArduinoLaunchRequestArguments): Promise<void> {
1117
if (!requestArgs.sketch) {
1218
throw new Error('Missing argument: sketch');
@@ -26,7 +32,7 @@ export class ArduinoGDBBackend extends GDBBackend {
2632
const proc = spawn(command, args);
2733
this.proc = proc;
2834
this.out = proc.stdin;
29-
return this.parser.parse(proc.stdout);
35+
return (this.parser as ArduinoParser).parseFull(proc);
3036
}
3137

3238
sendFileExecAndSymbols(): Promise<void> {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { ChildProcessWithoutNullStreams } from 'child_process';
2+
import { Readable } from 'stream';
3+
import { MIParser } from "cdt-gdb-adapter/dist/MIParser";
4+
5+
const READY_TIMEOUT = 7000;
6+
const LINE_REGEX = /(.*)(\r?\n)/;
7+
8+
export class ArduinoParser extends MIParser {
9+
10+
parseFull(proc: ChildProcessWithoutNullStreams): Promise<void> {
11+
return new Promise((resolve, reject) => {
12+
proc.on('error', reject);
13+
let ready = false;
14+
proc.on('exit', () => {
15+
if (!ready) {
16+
reject(new Error('The gdb debugger terminated unexpectedly.'));
17+
}
18+
});
19+
20+
const timeout = setTimeout(() => {
21+
reject(new Error(`No response from gdb after ${READY_TIMEOUT} ms.`));
22+
}, READY_TIMEOUT);
23+
this.waitReady = () => {
24+
ready = true;
25+
clearTimeout(timeout);
26+
resolve();
27+
}
28+
this.readInputStream(proc.stdout);
29+
this.readErrorStream(proc.stderr, reject);
30+
});
31+
}
32+
33+
private readInputStream(stream: Readable) {
34+
let buff = '';
35+
stream.on('data', chunk => {
36+
buff += chunk.toString();
37+
let regexArray = LINE_REGEX.exec(buff);
38+
while (regexArray) {
39+
this.line = regexArray[1];
40+
this.pos = 0;
41+
this.handleLine();
42+
buff = buff.substring(regexArray[1].length + regexArray[2].length);
43+
regexArray = LINE_REGEX.exec(buff);
44+
}
45+
});
46+
}
47+
48+
private readErrorStream(stream: Readable, reject: (reason?: any) => void) {
49+
let buff = '';
50+
stream.on('data', chunk => {
51+
buff += chunk.toString();
52+
let regexArray = LINE_REGEX.exec(buff);
53+
while (regexArray) {
54+
const line = regexArray[1];
55+
this.gdb.emit('consoleStreamOutput', line + '\n', 'stderr');
56+
if (line.toLowerCase().startsWith('error')) {
57+
reject(new Error(line));
58+
}
59+
buff = buff.substring(regexArray[1].length + regexArray[2].length);
60+
regexArray = LINE_REGEX.exec(buff);
61+
}
62+
});
63+
}
64+
65+
}

0 commit comments

Comments
 (0)