Node.js process.exit() не завершится с открытым createReadStream

У меня есть программа, которая общается с Asterisk через EAGI. Asterisk открывает мое приложение Node.js и отправляет ему данные через STDIN, а программа отправляет команды Asterisk через STDOUT. Когда пользователь вешает трубку, процессу Node.js отправляется команда SIGHUP. Это перехватывается для более чистого выхода. Этот функционал работает.

Asterisk также отправляет аудиоданные RAW по fd 3 (STDERR+1). Процесс Node.js правильно перехватывает данные и может читать звук, преобразовывать его или делать что-то еще, что необходимо сделать. Однако, когда createReadStream создается на fd 3, процесс Node.js НЕ завершается и быстро становится зомби. Если я закомментирую код createReadStream, Node.js выйдет, как и ожидалось.

Как я могу заставить Node.js выйти с помощью функции process.exit(), как и предполагалось? Я использую Node.js версии v0.10.30.

Код Node.js createReadStream:

// It was success
this.audioInStream = fs.createReadStream( null, { 'fd' : 3 } );

// Pipe the audio stream to a blackhole for now so it doesn't get queued up
this.audioInStream.pipe( blackhole() );

SIGHUP-код:

process
.on( 'SIGHUP', function() {
    log.message.info( "[%s] Asterisk process hung up.", that.callerid );
    that.exitWhenReady();
} );

функция exitWhenReady

Index.prototype.exitWhenReady = function() {
    if( !this.canExit )
        return;

    log.message.info( "[%s] Exiting program successfully.", this.callerid );

    // Get rid of our streams
    this.audioInStream.unpipe();
    this.audioInStream.close();
    this.audioInStream.destroy();

    process.exit( 0 );
};

Модуль черной дыры:

var inherits = require( 'util' ).inherits;
var Writable = require( 'stream' ).Writable;
var process = require( 'process' );

function Blackhole( opts ) {
    if( !(this instanceof Blackhole) )
        return( new Blackhole( opts ) );

    if( !opts )
        opts = {};

    Writable.call( this, opts );
}

inherits( Blackhole, Writable );

Blackhole.prototype._write = function( chunk, encoding, done ) {
    process.nextTick( done );
};

module.exports = Blackhole;

Примечательно, что

Процесс Asterisk завис

А также

Выход из программы успешно.

Никогда не появляйтесь в файле журнала, когда createReadStream читает fd 3, но когда это не так, они это делают.


person Mikey A. Leonetti    schedule 15.06.2015    source источник
comment
Мне кажется, что это основная проблема: github.com/nodejs/ node-v0.x-archive/issues/7101 Несмотря на то, что проблема закрыта, проблема на самом деле не устранена. Все это чтение с tty в узле представляет собой большой беспорядок с блокировкой чтения/записи, хотя они должны быть асинхронными, разными классами потоков/сокетов поверх простых fd....   -  person Johannes Rudolph    schedule 27.10.2015


Ответы (1)


Я обнаружил, что перехват SIGHUP И открытие fd 3 приводит к тому, что программа не закрывается даже при вызове process.exit(). Это было действительно странно.

Что я сделал, чтобы решить эту проблему, так это прослушал событие «выход» процесса. В событии «выход» я вручную убил свой собственный процесс с помощью SIGTERM. Этого было достаточно, чтобы остановить всю программу. Я обнаружил, что это на самом деле хорошо работает даже с регистратором исключений Winston logger. Winston сможет записать исключение в файл журнала, а затем успешно завершить работу.

Код результата:

process
.on( 'SIGHUP', function() {
    log.message.info( "[%s] Asterisk process hung up.", that.callerid );
    that.exitWhenReady( true );
} )
.on( 'exit', function() {
    process.kill( process.pid, 'SIGTERM' );
} );

Вышеупомянутая функция в основном вызывает exitWhenReady() при отправке SIGHUP. Это проверяет, что все задачи завершены, и как только все задачи будут завершены, он вызовет «process.exit ()», который вызывает функцию для вышеуказанного события.

Я надеюсь, что это поможет кому-то.

person Mikey A. Leonetti    schedule 16.06.2015
comment
Спасибо! только что столкнулся с подобным случаем, когда process.exit не работал на SIGINT. SIGTERM сделал свое дело. - person Amiram Korach; 14.07.2017