From 6c8258897268687da35979fbd26fa615947b2248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Wawrzyniec=20Urba=C5=84czyk?= Date: Tue, 16 Aug 2022 14:56:08 +0200 Subject: [PATCH] Handling exceptions in IDE main to avoid entering "zombie process" state. (#3648) This is meant to address https://www.pivotaltracker.com/story/show/182691027. --- CHANGELOG.md | 4 ++ app/ide-desktop/lib/client/src/index.js | 55 +++++++++++++++++-------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76bae824949..3f1318173b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,9 @@ methods, atoms and functions are presented in nice, categorized view. The most popular tools are available at hand. The The panel is unstable, and thus is available under the `--enable-new-component-browser` flag. +- [Fixed error handling during startup.][3648] This prevents entering IDE into a + "zombie" state, where processes were started but not visible to user. They + could cause issues with starting further IDE instances. #### EnsoGL (rendering engine) @@ -273,6 +276,7 @@ [3601]: https://github.com/enso-org/enso/pull/3601 [3617]: https://github.com/enso-org/enso/pull/3617 [3629]: https://github.com/enso-org/enso/pull/3629 +[3648]: https://github.com/enso-org/enso/pull/3648 #### Enso Compiler diff --git a/app/ide-desktop/lib/client/src/index.js b/app/ide-desktop/lib/client/src/index.js index df35c743af0..640dce6260e 100644 --- a/app/ide-desktop/lib/client/src/index.js +++ b/app/ide-desktop/lib/client/src/index.js @@ -476,27 +476,46 @@ let mainWindow = null let origin = null async function main(args) { - runBackend() - console.log('Starting the IDE service.') - if (args.server !== false) { - let serverCfg = Object.assign({}, args) - serverCfg.dir = root - serverCfg.fallback = '/assets/index.html' - server = await Server.create(serverCfg) - origin = `http://localhost:${server.port}` - } - if (args.window !== false) { - console.log('Starting the IDE client.') - mainWindow = createWindow() - mainWindow.on('close', evt => { - if (hideInsteadOfQuit) { - evt.preventDefault() - mainWindow.hide() - } - }) + // Note [Main error handling] + try { + runBackend() + + console.log('Starting the IDE service.') + if (args.server !== false) { + let serverCfg = Object.assign({}, args) + serverCfg.dir = root + serverCfg.fallback = '/assets/index.html' + server = await Server.create(serverCfg) + origin = `http://localhost:${server.port}` + } + if (args.window !== false) { + console.log('Starting the IDE client.') + mainWindow = createWindow() + mainWindow.on('close', evt => { + if (hideInsteadOfQuit) { + evt.preventDefault() + mainWindow.hide() + } + }) + } + } catch (err) { + // Note [Main error handling] + console.error('Failed to setup IDE. Error:', err) + Electron.app.quit() } } +// Note [Main error handling] +// ========================== +// It is critical that the main function runs in its entirety. Otherwise, IDE enters a "zombie +// process" state, where Electron processes have been spawned, but there is no window and user can't +// observe anything. Usually they will try to spawn another instance of the IDE, but this can fail +// because of these zombie process presence. +// +// The solution is to catch all errors and exit the process if any part of the initial setup fails. +// If it succeeds, at least the Window will be shown, allowing the user to observe the error and +// close it. + function urlParamsFromObject(obj) { let params = [] for (let key in obj) {