Skip to content

Commit 4436f0a

Browse files
committed
Add multi-process support
1 parent bcbbda1 commit 4436f0a

File tree

5 files changed

+73
-13
lines changed

5 files changed

+73
-13
lines changed

package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@
118118
"description": "Prints all GDB calls to the console",
119119
"default": false
120120
},
121+
"multiProcess": {
122+
"type": "boolean",
123+
"description": "Allow multiple process debugging",
124+
"default": false
125+
},
121126
"showDevDebugOutput": {
122127
"type": "boolean",
123128
"description": "Prints all GDB responses to the console",
@@ -219,6 +224,11 @@
219224
"description": "Prints all GDB calls to the console",
220225
"default": false
221226
},
227+
"multiProcess": {
228+
"type": "boolean",
229+
"description": "Allow multiple process debugging",
230+
"default": false
231+
},
222232
"showDevDebugOutput": {
223233
"type": "boolean",
224234
"description": "Prints all GDB responses to the console",

src/backend/backend.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export interface IBackend {
5555
start(): Thenable<boolean>;
5656
stop();
5757
detach();
58-
interrupt(): Thenable<boolean>;
58+
interrupt(all: boolean): Thenable<boolean>;
5959
continue(): Thenable<boolean>;
6060
next(): Thenable<boolean>;
6161
step(): Thenable<boolean>;

src/backend/mi2/mi2.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,16 @@ export class MI2 extends EventEmitter implements IBackend {
198198
cmds.push(this.sendCommand("file-exec-and-symbols \"" + escape(target) + "\""));
199199
if (this.prettyPrint)
200200
cmds.push(this.sendCommand("enable-pretty-printing"));
201+
if (this.multiProcess) {
202+
cmds.push(
203+
this.sendCommand("gdb-set follow-fork-mode parent"),
204+
this.sendCommand("gdb-set detach-on-fork off"),
205+
this.sendCommand("gdb-set non-stop on"),
206+
this.sendCommand("gdb-set schedule-multiple on"),
207+
208+
this.sendCommand("interpreter-exec console \"handle SIGSYS nostop noprint\"")
209+
);
210+
}
201211

202212
return cmds;
203213
}
@@ -356,7 +366,7 @@ export class MI2 extends EventEmitter implements IBackend {
356366
else if (reason == "exited-normally")
357367
this.emit("exited-normally", parsed);
358368
else if (reason == "exited") { // exit with error code != 0
359-
this.log("stderr", "Program exited with code " + parsed.record("exit-code"));
369+
this.log("stderr", "Inferior exited with code " + parsed.record("exit-code"));
360370
this.emit("exited-normally", parsed);
361371
}
362372
else {
@@ -370,6 +380,10 @@ export class MI2 extends EventEmitter implements IBackend {
370380
this.emit("thread-created", parsed);
371381
} else if (record.asyncClass == "thread-exited") {
372382
this.emit("thread-exited", parsed);
383+
} else if (record.asyncClass == "thread-group-started") {
384+
this.emit("thread-group-started", parsed);
385+
} else if (record.asyncClass == "thread-group-exited") {
386+
this.emit("thread-group-exited", parsed);
373387
}
374388
}
375389
}
@@ -432,21 +446,21 @@ export class MI2 extends EventEmitter implements IBackend {
432446
this.sendRaw("-target-detach");
433447
}
434448

435-
interrupt(): Thenable<boolean> {
449+
interrupt(all: boolean = true): Thenable<boolean> {
436450
if (trace)
437451
this.log("stderr", "interrupt");
438452
return new Promise((resolve, reject) => {
439-
this.sendCommand("exec-interrupt").then((info) => {
453+
this.sendCommand("exec-interrupt" + (all ? " --all" : "")).then((info) => {
440454
resolve(info.resultRecords.resultClass == "done");
441455
}, reject);
442456
});
443457
}
444458

445-
continue(reverse: boolean = false): Thenable<boolean> {
459+
continue(reverse: boolean = false, all: boolean = true): Thenable<boolean> {
446460
if (trace)
447461
this.log("stderr", "continue");
448462
return new Promise((resolve, reject) => {
449-
this.sendCommand("exec-continue" + (reverse ? " --reverse" : "")).then((info) => {
463+
this.sendCommand("exec-continue" + (reverse ? " --reverse" : "") + (all ? " --all" : "")).then((info) => {
450464
resolve(info.resultRecords.resultClass == "running");
451465
}, reject);
452466
});
@@ -785,6 +799,7 @@ export class MI2 extends EventEmitter implements IBackend {
785799
}
786800

787801
prettyPrint: boolean = true;
802+
multiProcess: boolean = false;
788803
printCalls: boolean;
789804
debugOutput: boolean;
790805
public procEnv: any;

src/gdb.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArgum
1616
ssh: SSHArguments;
1717
valuesFormatting: ValuesFormattingMode;
1818
printCalls: boolean;
19+
multiProcess: boolean;
1920
showDevDebugOutput: boolean;
2021
}
2122

@@ -31,6 +32,7 @@ export interface AttachRequestArguments extends DebugProtocol.AttachRequestArgum
3132
ssh: SSHArguments;
3233
valuesFormatting: ValuesFormattingMode;
3334
printCalls: boolean;
35+
multiProcess: boolean;
3436
showDevDebugOutput: boolean;
3537
}
3638

@@ -58,6 +60,7 @@ class GDBDebugSession extends MI2DebugSession {
5860
this.debugReady = false;
5961
this.setValuesFormattingMode(args.valuesFormatting);
6062
this.miDebugger.printCalls = !!args.printCalls;
63+
this.miDebugger.multiProcess = !!args.multiProcess;
6164
this.miDebugger.debugOutput = !!args.showDevDebugOutput;
6265
if (args.ssh !== undefined) {
6366
if (args.ssh.forwardX11 === undefined)
@@ -126,6 +129,7 @@ class GDBDebugSession extends MI2DebugSession {
126129
this.debugReady = false;
127130
this.setValuesFormattingMode(args.valuesFormatting);
128131
this.miDebugger.printCalls = !!args.printCalls;
132+
this.miDebugger.multiProcess = !!args.multiProcess;
129133
this.miDebugger.debugOutput = !!args.showDevDebugOutput;
130134
if (args.ssh !== undefined) {
131135
if (args.ssh.forwardX11 === undefined)

src/mibase.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export class MI2DebugSession extends DebugSession {
3737
protected debugReady: boolean;
3838
protected miDebugger: MI2;
3939
protected commandServer: net.Server;
40+
protected threadGroupPids = new Map<string, string>();
41+
protected threadToPid = new Map<number, string>();
4042

4143
public constructor(debuggerLinesStartAt1: boolean, isServer: boolean = false) {
4244
super(debuggerLinesStartAt1, isServer);
@@ -54,6 +56,8 @@ export class MI2DebugSession extends DebugSession {
5456
this.miDebugger.on("signal-stop", this.handlePause.bind(this));
5557
this.miDebugger.on("thread-created", this.threadCreatedEvent.bind(this));
5658
this.miDebugger.on("thread-exited", this.threadExitedEvent.bind(this));
59+
this.miDebugger.on("thread-group-started", this.threadGroupStartedEvent.bind(this));
60+
this.miDebugger.on("thread-group-exited", this.threadGroupExitedEvent.bind(this));
5761
this.sendEvent(new InitializedEvent());
5862
try {
5963
this.commandServer = net.createServer(c => {
@@ -138,16 +142,35 @@ export class MI2DebugSession extends DebugSession {
138142
}
139143

140144
protected threadCreatedEvent(info: MINode) {
141-
this.sendEvent(new ThreadEvent("started", info.record("id")));
145+
let threadId = parseInt(info.record("id"), 10);
146+
147+
let threadPid = this.threadGroupPids.get(info.record("group-id"));
148+
this.threadToPid.set(threadId, threadPid);
149+
150+
this.sendEvent(new ThreadEvent("started", threadId));
142151
}
143152

144153
protected threadExitedEvent(info: MINode) {
145-
this.sendEvent(new ThreadEvent("exited", info.record("id")));
154+
let threadId = parseInt(info.record("id"), 10);
155+
156+
this.threadToPid.delete(info.record("group-id"));
157+
158+
this.sendEvent(new ThreadEvent("exited", threadId));
159+
}
160+
161+
protected threadGroupStartedEvent(info: MINode) {
162+
this.threadGroupPids.set(info.record("id"), info.record("pid"));
146163
}
147164

148-
protected quitEvent() {
149-
this.quit = true;
150-
this.sendEvent(new TerminatedEvent());
165+
protected threadGroupExitedEvent(info: MINode) {
166+
this.threadGroupPids.delete(info.record("id"));
167+
}
168+
169+
protected quitEvent(info?: MINode) {
170+
if (this.threadGroupPids.size == 0) {
171+
this.quit = true;
172+
this.sendEvent(new TerminatedEvent());
173+
}
151174
}
152175

153176
protected launchError(err: any) {
@@ -276,7 +299,13 @@ export class MI2DebugSession extends DebugSession {
276299
if (threadName === undefined) {
277300
threadName = "<unnamed>";
278301
}
279-
response.body.threads.push(new Thread(thread.id, thread.id + ":" + threadName));
302+
if (this.threadGroupPids.size > 1) {
303+
let pid = this.threadToPid.get(thread.id);
304+
threadName = `(${pid}) ${thread.id}:${threadName}`;
305+
} else {
306+
threadName = `${thread.id}:${threadName}`;
307+
}
308+
response.body.threads.push(new Thread(thread.id, threadName));
280309
}
281310
this.sendResponse(response);
282311
});
@@ -584,7 +613,7 @@ export class MI2DebugSession extends DebugSession {
584613
}
585614
}
586615

587-
protected pauseRequest(response: DebugProtocol.ContinueResponse, args: DebugProtocol.ContinueArguments): void {
616+
protected pauseRequest(response: DebugProtocol.PauseResponse, args: DebugProtocol.PauseArguments): void {
588617
this.miDebugger.interrupt().then(done => {
589618
this.sendResponse(response);
590619
}, msg => {
@@ -594,6 +623,7 @@ export class MI2DebugSession extends DebugSession {
594623

595624
protected reverseContinueRequest(response: DebugProtocol.ReverseContinueResponse, args: DebugProtocol.ReverseContinueArguments): void {
596625
this.miDebugger.continue(true).then(done => {
626+
response.body.allThreadsContinued = true;
597627
this.sendResponse(response);
598628
}, msg => {
599629
this.sendErrorResponse(response, 2, `Could not continue: ${msg}`);
@@ -602,6 +632,7 @@ export class MI2DebugSession extends DebugSession {
602632

603633
protected continueRequest(response: DebugProtocol.ContinueResponse, args: DebugProtocol.ContinueArguments): void {
604634
this.miDebugger.continue().then(done => {
635+
response.body.allThreadsContinued = true;
605636
this.sendResponse(response);
606637
}, msg => {
607638
this.sendErrorResponse(response, 2, `Could not continue: ${msg}`);

0 commit comments

Comments
 (0)