Skip to content

Commit 76ea8b5

Browse files
IanMatthewHuffIan Huff
andauthored
If we fail to start a raw kernel daemon, fall back on process execution (microsoft#12736)
Co-authored-by: Ian Huff <ianhuff@ravikun-dev2.redmond.corp.microsoft.com>
1 parent 73cbe71 commit 76ea8b5

File tree

4 files changed

+34
-10
lines changed

4 files changed

+34
-10
lines changed

news/2 Fixes/12355.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
If we fail to start a raw kernel daemon then fall back to using process execution.

src/client/datascience/kernel-launcher/kernelLauncherDaemon.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,15 @@ export class PythonKernelLauncherDaemon implements IDisposable {
2727
resource: Resource,
2828
kernelSpec: IJupyterKernelSpec,
2929
interpreter?: PythonInterpreter
30-
): Promise<{ observableOutput: ObservableExecutionResult<string>; daemon: IPythonKernelDaemon }> {
30+
): Promise<{ observableOutput: ObservableExecutionResult<string>; daemon: IPythonKernelDaemon } | undefined> {
3131
const daemon = await this.daemonPool.get(resource, kernelSpec, interpreter);
32+
33+
// The daemon pool can return back a non-IPythonKernelDaemon if daemon service is not supported or for Python 2.
34+
// Use a check for the daemon.start function here before we call it.
35+
if (!daemon.start) {
36+
return undefined;
37+
}
38+
3239
const args = kernelSpec.argv.slice();
3340
const modulePrefixIndex = args.findIndex((item) => item === '-m');
3441
if (modulePrefixIndex === -1) {

src/client/datascience/kernel-launcher/kernelProcess.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,17 +215,23 @@ export class KernelProcess implements IKernelProcess {
215215
}
216216

217217
private async launchAsObservable() {
218-
let exeObs: ObservableExecutionResult<string>;
218+
let exeObs: ObservableExecutionResult<string> | undefined;
219219
if (this.isPythonKernel) {
220220
this.pythonKernelLauncher = new PythonKernelLauncherDaemon(this.daemonPool);
221-
const { observableOutput, daemon } = await this.pythonKernelLauncher.launch(
221+
const kernelDaemonLaunch = await this.pythonKernelLauncher.launch(
222222
this.resource,
223223
this._kernelSpec,
224224
this.interpreter
225225
);
226-
this.kernelDaemon = daemon;
227-
exeObs = observableOutput;
228-
} else {
226+
227+
if (kernelDaemonLaunch) {
228+
this.kernelDaemon = kernelDaemonLaunch.daemon;
229+
exeObs = kernelDaemonLaunch.observableOutput;
230+
}
231+
}
232+
233+
// If we are not python or if we failed with our daemon launch just use the ProcessExecutionFactory
234+
if (!exeObs) {
229235
// First part of argument is always the executable.
230236
const executable = this._kernelSpec.argv[0];
231237
const executionService = await this.processExecutionFactory.create(this.resource);
@@ -234,7 +240,7 @@ export class KernelProcess implements IKernelProcess {
234240
});
235241
}
236242

237-
if (exeObs.proc) {
243+
if (exeObs && exeObs.proc) {
238244
exeObs.proc.on('exit', (exitCode) => {
239245
traceInfo('KernelProcess Exit', `Exit - ${exitCode}`);
240246
if (this.disposed) {

src/test/datascience/kernel-launcher/kernelLauncherDaemon.unit.test.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,19 @@ suite('Data Science - Kernel Launcher Daemon', () => {
5252
await assert.isRejected(promise, /^Unsupported KernelSpec file. args must be/g);
5353
});
5454
test('Creates and returns a daemon', async () => {
55-
const { observableOutput, daemon } = await launcher.launch(undefined, kernelSpec, interpreter);
55+
const daemonCreationOutput = await launcher.launch(undefined, kernelSpec, interpreter);
5656

57-
assert.equal(observableOutput, instance(observableOutputForDaemon));
58-
assert.equal(daemon, instance(kernelDaemon));
57+
assert.isDefined(daemonCreationOutput);
58+
59+
if (daemonCreationOutput) {
60+
assert.equal(daemonCreationOutput.observableOutput, instance(observableOutputForDaemon));
61+
assert.equal(daemonCreationOutput.daemon, instance(kernelDaemon));
62+
}
63+
});
64+
test('If our daemon pool return does not support start, return undefined', async () => {
65+
when(daemonPool.get(anything(), anything(), anything())).thenResolve({} as any);
66+
const daemonCreationOutput = await launcher.launch(undefined, kernelSpec, interpreter);
67+
68+
assert.isUndefined(daemonCreationOutput);
5969
});
6070
});

0 commit comments

Comments
 (0)