Node и NPM Запуск скрипта и Ctrl-C запускают SIGINT дважды

Я столкнулся с проблемой в одном из моих приложений Nodejs, работающих с npm start (который просто делает node app.js).

Мое приложение содержит обработчик сигинта следующим образом:

process.on('SIGINT', () => {
    db.disconnect().then({
        process.exit(0);
    }).catch(e => process.exit(1));
});

С соответствующими журналами. После некоторого тестирования других файлов, я заметил, что Ctrl-C, когда на npm Процесс вызывает SIGINT дважды, если первый из них занимает слишком много времени для выхода. (попробуйте добавить таймаут в пример приложения).

На данный момент я добавил счетчик, чтобы проверить, выполняется ли вызов более одного раза, но я не уверен, что это "путь" в отношении этой проблемы. Я предполагаю, что SIGINT для процесса npm, как ожидается, завершится через определенный промежуток времени, поэтому npm передает его еще раз (всегда только дважды).

Кто-нибудь сталкивался с этой проблемой и нашел жизнеспособное решение?

Спасибо!

3 ответа

Возможно, вы захотите запустить свою команду напрямую через узел, а не через npm start. NPM может быть причиной странного перехвата сигналов, см. https://lisk.io/blog/tutorial/why-we-stopped-using-npm-start-child-processes.

Ваш обработчик SIGINT может вызываться несколько раз, вы должны написать свой код для защиты от этого.

Также, если вы используете родительские / дочерние процессы, см. https://github.com/jtlapp/node-cleanup.

Когда вы нажимаете Ctrl-C, вы отправляете сигнал SIGINT каждому процессу в текущей группе процессов. Группа процессов - это набор процессов, которые должны завершиться вместе как группа, а не существовать независимо. Однако некоторые программы, такие как Emacs, перехватывают и изменяют назначение SIGINT, так что это не завершает процесс. В таких случаях SIGINT не должен завершать какие-либо процессы группы.

Кроме того, в большинстве случаев вызов process.exit не требуется, см. https://nodejs.org/api/process.html

Вместо этого установите process.exitCode, удалите обработчики сигналов, а затем повторно поднимите сигнал с помощью process.kill(process.pid, signal)

Я знаю, что этот пост существует уже некоторое время, но, к сожалению, у меня такая же проблема. При беге простоnode <app.js>выдает только один сигнал. Этот сигнал приходит дважды, если работаетnpm start. Вместо счетчика я предлагаю проверить, продолжает ли сервер слушать, если да, продолжайте свою логику и внутреннее завершение (например, подключения к базе данных и т. Д.):

process.on('SIGINT', function(){
 if (server.listening) {
    server.close(function (err) {
      if (err) {
        console.error(err);
        process.exit(1)
      }
      process.exit(0);
    })
 }
})

Более чистым решением было бы обернуть обработчик отключения в обещание, и из-за внутренней реализации обещания разрешение будет вызываться только один раз.

      new Promise((resolve) => process.on('SIGINT', resolve))
   .then(() => db.disconnect())
   .then(() => process.exit(0))
   .catch(() => process.exit(1));

Примечание. Я бы посоветовал избегать явного вызова process.exit() и позволить узлу выйти самостоятельно. Если по каким-то причинам процесс не завершился, это означает, что есть что-то, что его блокирует (например, прослушивание портов, открытые/ожидающие TCP-соединения, очищенные setIntervalили же setTimeoutиспользованная литература)

Другие вопросы по тегам