изящно завершить дочерний элемент при выполнении Ctrl-C в NodeJS

У меня есть архитектура с одним родителем, которая порождает дочерний элемент следующим образом:

this.process = child.spawn(this.cmd, this.args);

this.process.on('exit', (code: number, signal: string) => {
    this.exitCode = code;
    console.log(`exit code: ${code}`);
});

особого варианта нет, потому что я хочу сохранить связь с ребенком. Итак, когда я нажимаю Ctr-C, чтобы убить родителя, он ловит SIGINT, чтобы (1) завершить дочерний элемент, (2) правильно выйти. Но SIGINT также распространяется на потомка, поэтому родитель не может завершить его корректно. Итак, есть ли способ сделать это? может быть, предотвратив распространение SIGINT на ребенка? или говорить ребенку игнорировать сигнал?

я знаю, что что-то возможно, добавив опции detached: true и stdio: 'ignore' при нересте, но я не хочу этого делать, потому что, если родитель умрет, я закончу процесс зомби. В то время как сохранение ссылок гарантирует, что ребенок будет убит, если родитель неожиданно умрет. Наконец, я хочу не поймать SIGINT в дочернем элементе, так как я хочу, чтобы он был немым.

EDIT: у родителя уже есть process.on('SIGINT', () => { ... }, а дочерний — на python.


person Hattori    schedule 27.05.2020    source источник


Ответы (1)


Вы можете поймать код выхода следующим образом:

process.on('SIGINT', () => {
  // handle it yourself
})

Вы можете передать его детям следующим образом:

process.on('SIGINT', () => {
  this.child.kill('SIGINT')
})

Конечно, дочерний процесс также может выбрать обработку сигнала, разумно не предполагать, что дочерний процесс завершится только потому, что вы отправили один сигнал. Возможно, вам придется установить тайм-аут и отправить повторные или разные сигналы, чтобы полностью убить процесс. Вы также захотите прослушать сообщение 'exit' дочернего процесса, чтобы узнать, когда он действительно убит, прежде чем продолжить.

Документация

person justin.m.chase    schedule 27.05.2020
comment
дело в том, что SIGINT отправляется на всю группу. Что значит и для ребенка. У меня на самом деле уже есть process.on('SIGINT', () => { //end child } но это не мешает ребенку получать SIGINT самостоятельно. Более того, функция spawn возвращает дочерний процесс. Итак, в коде, который я дал, если я добавлю this.process.on('SIGINT', () => { //do something }, я ожидаю, что SIGINT будет пойман также для ребенка. но это не так. И кажется (через что читал), что ребенка нужно отрывать от родителей для работы. Чего я не хочу. - person Hattori; 27.05.2020
comment
Как вы сами предложили, похоже, вам нужно поймать сигнал от ребенка и обработать его/игнорировать его там. Я буду делать это в моем случае, когда и родительский, и дочерний процессы являются процессами Node. - person jorisw; 02.01.2021