Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

## Unreleased

- Fixes [`463`](https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/issues/463): Cannot use custom reset while CPU is running.

## 1.4.1

- Fixes [`400`](https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/issues/400): Evaluation of variables to support RTOS Views extension.
Expand Down
23 changes: 17 additions & 6 deletions src/gdb/GDBDebugSessionBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,16 +277,27 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
*/
protected customResetRequest(response: DebugProtocol.Response) {
if (this.customResetCommands) {
this.gdb
.sendCommands(this.customResetCommands)
.then(() => this.sendResponse(response))
.catch(() =>
this.pauseIfNeeded()
.then(() => {
// Behavior after reset very much depends on the commands used.
// So, hard to make assumptions when expected state is reached.
// Hence, implement stop-after-reset behavior unless commands
// set running. Achieved by decrementing pause count (no recursion
// expected, this reset is not called as part of connection).
if (this.pauseCount > 0) {
this.pauseCount--;
}
this.gdb.sendCommands(this.customResetCommands).then(() => {
this.sendResponse(response);
});
})
.catch(() => {
this.sendErrorResponse(
response,
1,
'The custom reset command failed'
)
);
);
});
}
}

Expand Down
39 changes: 34 additions & 5 deletions src/integration-tests/custom-reset.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,23 @@ import { TargetLaunchRequestArguments } from '../types/session';
import { CdtDebugClient } from './debugClient';
import {
fillDefaults,
gdbAsync,
isRemoteTest,
standardBeforeEach,
testProgramsDir,
} from './utils';

describe('custom reset', function () {
let dc: CdtDebugClient;
const emptyProgram = path.join(testProgramsDir, 'empty');
const loopForeverProgram = path.join(testProgramsDir, 'loopforever');
const commands = ['print 42'];
const expectedResult = '$1 = 42\n';

beforeEach(async function () {
dc = await standardBeforeEach('debugTargetAdapter.js');
await dc.launchRequest(
fillDefaults(this.currentTest, {
program: emptyProgram,
program: loopForeverProgram,
customResetCommands: commands,
} as TargetLaunchRequestArguments)
);
Expand All @@ -45,8 +46,36 @@ describe('custom reset', function () {
this.skip();
}

const event = dc.waitForOutputEvent('stdout', expectedResult);
await dc.customRequest('cdt-gdb-adapter/customReset');
await event;
await Promise.all([
dc.waitForOutputEvent('stdout', expectedResult),
dc.customRequest('cdt-gdb-adapter/customReset'),
]);
});

it('stops the target if necessary before sending custom reset commands', async function () {
if (!isRemoteTest || !gdbAsync) {
// This test is pointless if async mode is off. It stops anyway.
this.skip();
}

await dc.setFunctionBreakpointsRequest({
breakpoints: [{ name: 'main' }],
});
const [stoppedEvent] = await Promise.all([
dc.waitForEvent('stopped'),
dc.configurationDoneRequest(),
]);
await dc.setFunctionBreakpointsRequest({ breakpoints: [] }); // remove function breakpoints

// Let the program run
await dc.continueRequest({ threadId: stoppedEvent.body.threadId });

await Promise.all([
dc.waitForOutputEvent('stdout', expectedResult), // wait stdout event
dc.customRequest('cdt-gdb-adapter/customReset'),
]);

// Would throw if it wasn't stopped
await dc.stepInRequest({ threadId: stoppedEvent.body.threadId });
});
});