electron / electron

:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS

Home Page:https://electronjs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Quit gracefully when Ctrl-C is pressed in console

elisee opened this issue · comments

  • Electron version: v0.37.7
  • Operating system: Windows 10 (64-bit)

Hi,

In Node.js, listening for the SIGINT event cancels its default behavior of exiting the process.

In Electron, the SIGINT event handler is called but the process still exits ASAP so the event handler will be interrupted randomly while it's doing its thing. For instance, running the following with electron index.js:

setTimeout(() => { /* Just to keep process running */ }, 1000000);

process.on("SIGINT", () => {
  console.log("Caught SIGINT. Exiting in 5 seconds.");

  setTimeout(() => {
    console.log("This should appear in the Electron console but the process will be long killed.");
    process.exit(0);
  }, 5000);
});

Prints for instance Caug or Caught S on my PC right before exiting and the rest of the function doesn't get executed. I believe that's not intended behavior.

commented

For GUI programs it is very unreliable to handle quitting with SIGINT signal, in Electron the SIGINT signal is hijacked to call app.quit instead. So you can use the before-quit or will-quit event to handle quitting.

Neither before-quit nor will-quit are called on my machine (Windows 10 64-bit, Electron v0.37.7) when closing the app with Ctrl+C in a terminal (thus sending SIGINT to it).

setTimeout(() => { /* Just to keep process running */ }, 1000000);

const electron = require("electron");
electron.app.on("before-quit", (event) => {
  // This is never called! Replacing before-quit with will-quit doesn't help.
  console.log("Caught before-quit. Exiting in 5 seconds.");
  event.preventDefault();

  setTimeout(() => { process.exit(0); }, 5000);
});
commented

There is no SIGINT on Windows, pressing Ctrl+C just kills the program, as far as I know there is no way to prevent that unless the program acts like a virus.

Node.js catches Ctrl+C and lets me handle it as SIGINT. It may be emulation, but it's still handled by the SIGINT handler. And Electron sort of does it too, except it terminates the program in the middle of the handler.

Maybe there's a way that Electron can check for a registered process.on("SIGINT", ...) handler and give control to it instead of initiating its shutdown sequence, rather than doing both in parallel.

Relevant section from the Node.js process API documentation:

SIGINT from the terminal is supported on all platforms, and can usually be generated with CTRL+C (though this may be configurable). It is not generated when terminal raw mode is enabled.

commented

Ah I see, so in Node they use SetConsoleCtrlHandler to catch console control events to emulate the SIGINT event, it would probably be harder for us to do in Electron since Electron is a GUI program and SetConsoleCtrlHandler is not supposed to work.

However we should have at least a decent way to handle a situation like this, we can probably follow the behavior on OS X that calls app.quit when Ctrl-C is pressed, so app shuts down gracefully.

http://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js

Can confirm that process.on('SIGINT') is called running as node (6.2.0), not as electron (1.2.3), on Ctrl-C

I'm doing this on command line, there is no UI but as you say the app may be run as GUI

I'd very much Electron to work same way as node.

Run this in Windows cmd prompt and behold the very weird behaviour
Windows 7:

  • app.on('ready') is called as expected
  • When run the app executes, electron.exe processes are loaded, and then app falls back to command line
  • I can see electron.exe in Task Manager.
  • Do some stuff on cmd.
  • Then do a Ctrl-C and see WTF printed from the SIGINT handler, and the electron.exe processes killed.
  • app.on('before-quit') is not called

OS X 10.11 - do Ctrl C

  • SIGINT handler NOT called
  • app.on('before-quit') called
try {
    var {app} = require('electron')
}
catch (e)
{

}

if (app)
{
app.on('before-quit',function()
{
    console.log('smoo')
})
app.on('ready',function()
{
    console.log('smee')
})

}


process.on("SIGINT", function () {
    console.log('WTF')
    process.exit(0) 

});
commented

After looking into this, I'm afraid this is a limitation of Window. Since Electron is an GUI app, there is no way to catch the Ctrl-C event from Windows, even when we setup a handle with SetConsoleCtrlHandler, Windows still kills the process anyway.

So I'm closing this as won't fix.

I've found a weird thing: when I press Ctrl+C, a close event of the focused BrowserWindow is triggered, instead of a app.quit().

How could I distinguish whether the close event is caused by app.quit or user normal close in main process?

Sry for necroposting, but ctrl-c doesn't seem to be caught in ubuntu as well (using xfce terminal to be specific), should I create a new issue?

On a side note - I'm also unable to catch anything and do a graceful shutdown on ubuntu reboot... this exit handling feels like a mess, to be honest.