Как правильно обрабатывать SIGINT с помощью Express.js? - программирование
Подтвердить что ты не робот

Как правильно обрабатывать SIGINT с помощью Express.js?

Мне нужно сделать некоторые полезные вещи, когда моя служба Express.js остановлена ​​на SIGINT. Используя Express.js версии 3.0.6, я понимаю, что это должно работать:

var express = require('express');

var app = express();
var server = app.listen(3000);

process.on('SIGINT', function() {
  console.log('Do something useful here.');
  server.close();
});

Но процесс не возвращает мне приглашение Bash, если я не выпущу SIGINT (Control - C) дважды:

$ node problem.js 
^CDo something useful here.
^CDo something useful here.

net.js:1046
    throw new Error('Not running');
          ^
Error: Not running
    at Server.close (net.js:1046:11)
    at process.<anonymous> (/path/to/problem.js:8:10)
    at process.EventEmitter.emit (events.js:93:17)
    at SignalWatcher.startup.processSignalHandlers.process.on.process.addListener.w.callback (node.js:486:45)
$

Еще одно предостережение. Если я запустил эту службу Express.js и не отправлял никаких запросов, то SIGINT завершается правильно.

Очевидно, есть что-то фундаментальное, что я здесь отсутствует?

4b9b3361

Ответ 1

Улавливая обработчик SIGINT, вы предотвращаете поведение по умолчанию, которое заключается в выходе из процесса. Когда вы используете Ctrl+C второй раз, процесс умирает, потому что server.close генерирует неперехваченное исключение.

Просто добавьте process.exit() в конец вашего обработчика SIGINT, чтобы закончить процесс.

Ответ 2

Я использую этот вариант:

server.close(() => {
  process.exit(0)
})

Ответ 3

Воскрешение старика, поскольку вопрос не полностью (или правильно) ответил, и люди все еще могут найти этот ответ.

Важная часть вашего вопроса:

Еще одно предостережение. Если я запустил эту службу Express.js и не отправлял никаких запросов, тогда SIGINT прекратит работу. Ясно, что есть что-то фундаментальное, что я здесь отсутствует?

Что вам не хватает, так это то, что по умолчанию express продолжает открывать соединения (HTTP keep-alive) для повторного использования. Итак, когда был (недавний) запрос, все еще есть что-то в цикле событий и причина, по которой ваше приложение не закрывается.

Использование process.exit() будет работать, но похоже на отправку другого ^ C и может скрывать тот факт, что еще есть что-то еще (например, соединения с базой данных). Ваше приложение должно просто закрыть, когда в цикле событий ничего не осталось.

Итак, я изменил ваш пример, установив 5-минутную поддержку в соединении, поэтому он будет изящным завершением в разумные сроки.

var express = require('express');

var serverPort = 3000;
var app = express();
var server = app.listen(serverPort);


// HTTP Keep-Alive to a short time to allow graceful shutdown
server.on('connection', function (socket) {
  socket.setTimeout(5 * 1000);
});

// Handle ^C
process.on('SIGINT', shutdown);

// Do graceful shutdown
function shutdown() {
  console.log('graceful shutdown express');
  server.close(function () {
    console.log('closed express');
  });
}

console.log('running server: http://localhost:' + serverPort);