Поймать SIGINT в родительском, но все равно убивает ребенка - PullRequest
1 голос
/ 10 марта 2020

У меня есть архитектура с одним родителем, который порождает два дочерних элемента (один в c ++, другой в python). Родитель порождает следующий класс:

export class subProcess {
    protected cmd: string;
    protected args: string[];
    protected process: child.ChildProcess;

    constructor(cmd: string, args: string[]) {
        this.cmd     = cmd;
        this.args    = args;
        this.process = null;
    }

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

        const rlout = readline.createInterface({
            input: this.process.stdout,
        });
        rlout.on('line', line => this.logger.info(line));

        const rlerr = readline.createInterface({
            input: this.process.stderr,
        });
        rlerr.on('line', line => this.logger.error(line));

        this.process.on('exit', (code: number) => {
            this.logger.info(`exit code: ${code}`);
        });
    }

Когда я прерываю родителя с помощью Ctrl- C, сигнал SIGINT настаивает в родительском процессе, чтобы иметь возможность сначала отключить и убить потомков изящно:

process.on('SIGINT', () => {
    this.bus.disconnect();
});

disconnect - это функция, которая отправляет команду "exit_process" дочерним элементам через ZeroMQ. Эта команда прекрасно работает при нормальном поведении. Но проблема в том, что когда я нажимаю Ctrl- C, родительский элемент SIGINT осторожен и выполняет функцию disconnect (как и ожидалось), но кажется, что он также распространяется SIGINT на дочерние элементы. Действительно, команда "exit_process", отправленная через ZeroMQ, достигает своего тайм-аута (что означает, что дочерние элементы никогда не получали / не отвечали), тогда как дочерние элементы выдают возвращенный код через событие exit.

Дело в том, что не может отсоединять и / или разыменовать дочерние элементы или управлять сигналами в дочерних элементах по проектным причинам. И я ожидал, что родитель поймает SIGINT, не распространяя его на childs.

Еще один момент, я попытался добавить следующее в subProcess класс, но это не сработало:

this.process.on('SIGINT', () => {
    console.log('SIGINT received. Do nothing');
});

1 Ответ

1 голос
/ 11 марта 2020

Ваш SIGINT передается всей группе процессов - см. этот раздел в Википедии . Однако вы, вероятно, не видите никаких выходных данных из-за того, как установлены дочерние каналы процесса.

При порождении нового дочернего процесса вы можете предоставить stdio options :

this.process = child.spawn(this.cmd, this.args, {stdio: 'inherit'});

Из-за вышесказанного дочерний процесс наследует родительские process.stdin, process.stdout, process.stderr. Если вы воспользуетесь этим подходом, вы увидите, что ваш ребенок получает SIGINT.

Поведение по умолчанию - создание отдельных потоков , поэтому вы не видите свой console.log. Вы также можете прослушать поток stdout ребенка:

this.process.stdout.on('data', data => console.log(data.toString()));
...