Skip to content

Commit ac70e85

Browse files
datphan9798Dat Phan
andauthored
Skip pausing target at startup if request has no breakpoints (#467)
In configuration phase, without this commit, breakpoint requests are still sent to gdb even when there is no breakpoints to set. When client does any of the various set breakpoint requests, interrupt and continue command could be sent to gdb and those commands could change the state of target unexpectedly. Therefore this change makes it so breakpoint requests don't pause the target during configuration phase if the request has no breakpoints. Co-authored-by: Dat Phan <[email protected]>
1 parent cccabb8 commit ac70e85

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

src/gdb/GDBDebugSessionBase.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
124124
protected gdb!: IGDBBackend;
125125
protected auxGdb?: IGDBBackend;
126126

127+
protected isBreakpointSent = false;
128+
protected isDataBreakpointSent = false;
129+
protected isFunctionBreakpointSent = false;
130+
protected isInstructionBreakpointSent = false;
131+
127132
protected isAttach = false;
128133
/**
129134
* True if GDB is using the "remote" or "extended-remote" target. In
@@ -717,6 +722,19 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
717722
response: DebugProtocol.SetDataBreakpointsResponse,
718723
args: DebugProtocol.SetDataBreakpointsArguments
719724
): Promise<void> {
725+
// If this is the first time sending this breakpoint and there are no breakpoints to set,
726+
// do not change state of the target by avoiding an unnecessary pause
727+
if (!this.isDataBreakpointSent) {
728+
if (args.breakpoints.length === 0) {
729+
response.body = {
730+
breakpoints: [],
731+
};
732+
this.sendResponse(response);
733+
return;
734+
}
735+
this.isDataBreakpointSent = true;
736+
}
737+
720738
await this.pauseIfNeeded();
721739
// Get existing GDB watchpoints
722740
let existingGDBWatchpointsList = await this.getWatchpointList();
@@ -799,6 +817,19 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
799817
response: DebugProtocol.SetInstructionBreakpointsResponse,
800818
args: DebugProtocol.SetInstructionBreakpointsArguments
801819
): Promise<void> {
820+
// If this is the first time sending this breakpoint and there are no breakpoints to set,
821+
// do not change state of the target by avoiding an unnecessary pause
822+
if (!this.isInstructionBreakpointSent) {
823+
if (args.breakpoints.length === 0) {
824+
response.body = {
825+
breakpoints: [],
826+
};
827+
this.sendResponse(response);
828+
return;
829+
}
830+
this.isInstructionBreakpointSent = true;
831+
}
832+
802833
await this.pauseIfNeeded();
803834
// Get a list of existing instruction breakpoints
804835
const existingInstBreakpointsList =
@@ -894,6 +925,22 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
894925
response: DebugProtocol.SetBreakpointsResponse,
895926
args: DebugProtocol.SetBreakpointsArguments
896927
): Promise<void> {
928+
// If this is the first time sending this breakpoint and there are no breakpoints to set,
929+
// do not change state of the target by avoiding an unnecessary pause
930+
if (!this.isBreakpointSent) {
931+
if (
932+
args.breakpoints !== undefined &&
933+
args.breakpoints.length === 0
934+
) {
935+
response.body = {
936+
breakpoints: [],
937+
};
938+
this.sendResponse(response);
939+
return;
940+
}
941+
this.isBreakpointSent = true;
942+
}
943+
897944
await this.pauseIfNeeded();
898945

899946
try {
@@ -1115,6 +1162,19 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
11151162
response: DebugProtocol.SetFunctionBreakpointsResponse,
11161163
args: DebugProtocol.SetFunctionBreakpointsArguments
11171164
) {
1165+
// If this is the first time sending this breakpoint and there are no breakpoints to set,
1166+
// do not change state of the target by avoiding an unnecessary pause
1167+
if (!this.isFunctionBreakpointSent) {
1168+
if (args.breakpoints.length === 0) {
1169+
response.body = {
1170+
breakpoints: [],
1171+
};
1172+
this.sendResponse(response);
1173+
return;
1174+
}
1175+
this.isFunctionBreakpointSent = true;
1176+
}
1177+
11181178
await this.pauseIfNeeded();
11191179

11201180
try {

src/integration-tests/breakpoints.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,4 +795,38 @@ describe('breakpoints', async function () {
795795
});
796796
expect(response.body.breakpoints.length).to.eq(1);
797797
});
798+
799+
it('empty breakpoint request if no breakpoint exists', async () => {
800+
const response = await dc.setBreakpointsRequest({
801+
source: {
802+
name: 'count.c',
803+
path: path.join(testProgramsDir, 'count.c'),
804+
},
805+
breakpoints: [],
806+
});
807+
expect(response.body.breakpoints.length).eq(0);
808+
});
809+
810+
it('empty breakpoint request if a breakpoint exists', async () => {
811+
await dc.setBreakpointsRequest({
812+
source: {
813+
name: 'count.c',
814+
path: path.join(testProgramsDir, 'count.c'),
815+
},
816+
breakpoints: [
817+
{
818+
column: 1,
819+
line: 4,
820+
},
821+
],
822+
});
823+
const response = await dc.setBreakpointsRequest({
824+
source: {
825+
name: 'count.c',
826+
path: path.join(testProgramsDir, 'count.c'),
827+
},
828+
breakpoints: [],
829+
});
830+
expect(response.body.breakpoints.length).eq(0);
831+
});
798832
});

src/integration-tests/functionBreakpoints.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,25 @@ describe('function breakpoints', async function () {
291291
await dc.configurationDoneRequest();
292292
await dc.assertStoppedLocation('function breakpoint', { line: 10 });
293293
});
294+
295+
it('empty function breakpoint request if no breakpoint exists', async () => {
296+
const bpResp = await dc.setFunctionBreakpointsRequest({
297+
breakpoints: [],
298+
});
299+
expect(bpResp.body.breakpoints.length).eq(0);
300+
});
301+
302+
it('empty function breakpoint request if a breakpoint exists', async () => {
303+
await dc.setFunctionBreakpointsRequest({
304+
breakpoints: [
305+
{
306+
name: 'main',
307+
},
308+
],
309+
});
310+
const bpResp = await dc.setFunctionBreakpointsRequest({
311+
breakpoints: [],
312+
});
313+
expect(bpResp.body.breakpoints.length).eq(0);
314+
});
294315
});

0 commit comments

Comments
 (0)