Skip to content

Commit cba23ce

Browse files
authored
Cancel run multiple session when debugger terminated (#1790)
When the user terminates the debugger using the red Stop icon and we're mid-run of a Debug Multple Times or Debug Until Failure command we should not execute the remaining iterations. Issue: #1747
1 parent 02a9529 commit cba23ce

File tree

3 files changed

+47
-18
lines changed

3 files changed

+47
-18
lines changed

src/TestExplorer/TestRunner.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,8 @@ export class TestRunner {
449449
private testArgs: TestRunArguments;
450450
private xcTestOutputParser: IXCTestOutputParser;
451451
private swiftTestOutputParser: SwiftTestingOutputParser;
452+
private debugSessionTerminatedEmitter = new vscode.EventEmitter<void>();
453+
public onDebugSessionTerminated: vscode.Event<void>;
452454
private static CANCELLATION_ERROR = "Test run cancelled.";
453455

454456
/**
@@ -487,6 +489,7 @@ export class TestRunner {
487489
this.testRun.addParameterizedTestCase,
488490
this.testRun.addAttachment
489491
);
492+
this.onDebugSessionTerminated = this.debugSessionTerminatedEmitter.event;
490493
}
491494

492495
/**
@@ -1158,8 +1161,13 @@ export class TestRunner {
11581161
LoggingDebugAdapterTracker.setDebugSessionCallback(
11591162
session,
11601163
this.workspaceContext.logger,
1161-
output => {
1162-
outputHandler(output);
1164+
output => outputHandler(output),
1165+
exitCode => {
1166+
// Debug session is stopped with exitCode 9 (SIGKILL)
1167+
// when the user terminates it manually.
1168+
if (exitCode === 9) {
1169+
this.debugSessionTerminatedEmitter.fire();
1170+
}
11631171
}
11641172
);
11651173

src/commands/testMultipleTimes.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ export async function runTestMultipleTimes(
5959
token.token
6060
);
6161

62+
// If the user terminates a debugging session we want
63+
// to cancel the remaining iterations.
64+
const terminationListener = runner.onDebugSessionTerminated(() => token.cancel());
65+
6266
testExplorer.onDidCreateTestRunEmitter.fire(runner.testRun);
6367

6468
const testRunState = new TestRunnerTestRunState(runner.testRun);
@@ -91,6 +95,7 @@ export async function runTestMultipleTimes(
9195
}
9296
}
9397
await runner.testRun.end();
98+
terminationListener.dispose();
9499

95100
return runStates;
96101
}

src/debugger/logTracker.ts

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export class LoggingDebugAdapterTrackerFactory implements vscode.DebugAdapterTra
3030
interface OutputEventBody {
3131
category: string;
3232
output: string;
33+
exitCode: number | undefined;
3334
}
3435

3536
interface DebugMessage {
@@ -68,7 +69,9 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
6869
private static debugSessionIdMap: { [id: string]: LoggingDebugAdapterTracker } = {};
6970

7071
private cb?: (output: string) => void;
72+
private exitHandler?: (exitCode: number) => void;
7173
private output: string[] = [];
74+
private exitCode: number | undefined;
7275

7376
constructor(public id: string) {
7477
LoggingDebugAdapterTracker.debugSessionIdMap[id] = this;
@@ -77,49 +80,62 @@ export class LoggingDebugAdapterTracker implements vscode.DebugAdapterTracker {
7780
static setDebugSessionCallback(
7881
session: vscode.DebugSession,
7982
logger: SwiftLogger,
80-
cb: (log: string) => void
83+
cb: (log: string) => void,
84+
exitHandler: (exitCode: number) => void
8185
) {
8286
const loggingDebugAdapter = this.debugSessionIdMap[session.id];
8387
if (loggingDebugAdapter) {
84-
loggingDebugAdapter.cb = cb;
88+
loggingDebugAdapter.setCallbacks(cb, exitHandler);
8589
for (const o of loggingDebugAdapter.output) {
8690
cb(o);
8791
}
92+
if (loggingDebugAdapter.exitCode) {
93+
exitHandler(loggingDebugAdapter.exitCode);
94+
}
8895
loggingDebugAdapter.output = [];
96+
loggingDebugAdapter.exitCode = undefined;
8997
} else {
9098
logger.error("Could not find debug adapter for session: " + session.id);
9199
}
92100
}
93101

102+
setCallbacks(handleOutput: (output: string) => void, handleExit: (exitCode: number) => void) {
103+
this.cb = handleOutput;
104+
this.exitHandler = handleExit;
105+
}
106+
94107
/**
95108
* The debug adapter has sent a Debug Adapter Protocol message to the editor. Check
96109
* it is a output message and is not being sent to the console
97110
*/
98111
onDidSendMessage(message: unknown): void {
99112
const debugMessage = message as DebugMessage;
100-
if (
101-
!(
102-
debugMessage &&
103-
debugMessage.type === "event" &&
104-
debugMessage.event === "output" &&
105-
debugMessage.body.category !== "console"
106-
)
107-
) {
113+
if (!debugMessage) {
108114
return;
109115
}
110-
const output = debugMessage.body.output;
111-
if (this.cb) {
112-
this.cb(output);
113-
} else {
114-
this.output.push(output);
116+
117+
if (debugMessage.event === "exited" && debugMessage.body.exitCode) {
118+
this.exitCode = debugMessage.body.exitCode;
119+
this.exitHandler?.(debugMessage.body.exitCode);
120+
} else if (
121+
debugMessage.type === "event" &&
122+
debugMessage.event === "output" &&
123+
debugMessage.body.category !== "console"
124+
) {
125+
const output = debugMessage.body.output;
126+
if (this.cb) {
127+
this.cb(output);
128+
} else {
129+
this.output.push(output);
130+
}
115131
}
116132
}
117133

118134
/**
119135
* The debug adapter session is about to be stopped. Delete the session from
120136
* the tracker
121137
*/
122-
onWillStopSession?(): void {
138+
onWillStopSession(): void {
123139
delete LoggingDebugAdapterTracker.debugSessionIdMap[this.id];
124140
}
125141
}

0 commit comments

Comments
 (0)