Improve Cleanup of Jupyter processes on Notebook and/or ADS Close (#5142)

* Close jupyter and python

* Ensure we stop jupyter correctly on process end

* dont stopServer from clientSession shutdown

* PR comments

* close notebook after each test
This commit is contained in:
Chris LaFreniere
2019-04-26 15:28:26 -07:00
committed by GitHub
parent 91b946bf3d
commit bb9c85cd8f
6 changed files with 21 additions and 16 deletions

View File

@@ -76,19 +76,20 @@ export class ServerInstanceUtils {
return spawn(command, args, options);
}
public checkProcessDied(childProcess: ChildProcess): void {
public ensureProcessEnded(childProcess: ChildProcess): void {
if (!childProcess) {
return;
}
// Wait 10 seconds and then force kill. Jupyter stop is slow so this seems a reasonable time limit
// Wait 5 seconds and then force kill. Jupyter stop is slow so this seems a reasonable time limit
setTimeout(() => {
// Test if the process is still alive. Throws an exception if not
try {
process.kill(childProcess.pid, <any>0);
process.kill(childProcess.pid, 'SIGKILL');
} catch (error) {
console.log(error);
// All is fine.
}
}, 10000);
}, 5000);
}
}
@@ -156,13 +157,14 @@ export class PerNotebookServerInstance implements IServerInstance {
let install = this.options.install;
let stopCommand = `"${install.pythonExecutable}" -m jupyter notebook stop ${this._port}`;
await this.utils.executeBufferedCommand(stopCommand, install.execOptions, install.outputChannel);
this._isStarted = false;
this.utils.checkProcessDied(this.childProcess);
this.handleConnectionClosed();
}
} catch (error) {
// For now, we don't care as this is non-critical
this.notify(this.options.install, localize('serverStopError', 'Error stopping Notebook Server: {0}', utils.getErrorMessage(error)));
} finally {
this._isStarted = false;
this.utils.ensureProcessEnded(this.childProcess);
this.handleConnectionClosed();
}
}
@@ -290,6 +292,8 @@ export class PerNotebookServerInstance implements IServerInstance {
this.childProcess.addListener('error', this.handleConnectionError);
this.childProcess.addListener('exit', this.handleConnectionClosed);
process.addListener('exit', this.stop);
// TODO #897 covers serializing stdout and stderr to a location where we can read from so that user can see if they run into trouble
}
@@ -363,9 +367,10 @@ export class PerNotebookServerInstance implements IServerInstance {
env['MSHOST_ENVIRONMENT'] = 'ADSClient-' + vscode.version;
// Start the notebook process
let options = {
let options: SpawnOptions = {
shell: true,
env: env
env: env,
detached: false
};
let childProcess = this.utils.spawn(startCommand, [], options);
return childProcess;

View File

@@ -38,7 +38,7 @@ describe('Jupyter server instance', function (): void {
mockInstall.setup(i => i.outputChannel).returns(() => mockOutputChannel.object);
mockInstall.setup(i => i.pythonExecutable).returns(() => 'python3');
mockUtils = TypeMoq.Mock.ofType(ServerInstanceUtils);
mockUtils.setup(u => u.checkProcessDied(TypeMoq.It.isAny())).returns(() => undefined);
mockUtils.setup(u => u.ensureProcessEnded(TypeMoq.It.isAny())).returns(() => undefined);
serverInstance = new PerNotebookServerInstance({
documentPath: expectedPath,
install: mockInstall.object