@ -369,16 +369,25 @@ function setupChannel(target, channel) {
assert ( util . isArray ( target . _ handleQueue ) ) ;
var queue = target . _ handleQueue ;
target . _ handleQueue = null ;
queue . forEach ( function ( args ) {
target . send ( args . message , args . handle ) ;
target . _ send ( args . message , args . handle , fals e ) ;
} ) ;
// Process a pending disconnect (if any).
if ( ! target . connected && target . _ channel && ! target . _ handleQueue )
target . _ disconnect ( ) ;
return ;
}
if ( message . cmd !== 'NODE_HANDLE' ) return ;
// Acknowledge handle receival.
target . send ( { cmd : 'NODE_HANDLE_ACK' } ) ;
// Acknowledge handle receival. Don't emit error events (for example if
// the other side has disconnected) because this call to send() is not
// initiated by the user and it shouldn't be fatal to be unable to ACK
// a message.
target . _ send ( { cmd : 'NODE_HANDLE_ACK' } , null , true ) ;
var obj = handleConversion [ message . type ] ;
@ -395,14 +404,17 @@ function setupChannel(target, channel) {
} ) ;
target . send = function ( message , handle ) {
if ( util . isUndefined ( message ) ) {
throw new TypeError ( 'message cannot be undefined' ) ;
}
if ( ! this . connected ) {
if ( ! this . connected )
this . emit ( 'error' , new Error ( 'channel closed' ) ) ;
return ;
}
else
this . _ send ( message , handle , false ) ;
} ;
target . _ send = function ( message , handle , swallowErrors ) {
assert ( this . connected || this . _ channel ) ;
if ( util . isUndefined ( message ) )
throw new TypeError ( 'message cannot be undefined' ) ;
// package messages with a handle object
if ( handle ) {
@ -454,7 +466,8 @@ function setupChannel(target, channel) {
var err = channel . writeUtf8String ( req , string , handle ) ;
if ( err ) {
this . emit ( 'error' , errnoException ( err , 'write' ) ) ;
if ( ! swallowErrors )
this . emit ( 'error' , errnoException ( err , 'write' ) ) ;
} else if ( handle && ! this . _ handleQueue ) {
this . _ handleQueue = [ ] ;
}
@ -467,15 +480,37 @@ function setupChannel(target, channel) {
return channel . writeQueueSize < ( 65536 * 2 ) ;
} ;
// connected will be set to false immediately when a disconnect() is
// requested, even though the channel might still be alive internally to
// process queued messages. The three states are distinguished as follows:
// - disconnect() never requested: _channel is not null and connected
// is true
// - disconnect() requested, messages in the queue: _channel is not null
// and connected is false
// - disconnect() requested, channel actually disconnected: _channel is
// null and connected is false
target . connected = true ;
target . disconnect = function ( ) {
if ( ! this . connected ) {
this . emit ( 'error' , new Error ( 'IPC channel is already disconnected' ) ) ;
return ;
}
// do not allow messages to be written
// Do not allow any new messages to be written.
this . connected = false ;
// If there are no queued messages, disconnect immediately. Otherwise,
// postpone the disconnect so that it happens internally after the
// queue is flushed.
if ( ! this . _ handleQueue )
this . _ disconnect ( ) ;
}
target . _ disconnect = function ( ) {
assert ( this . _ channel ) ;
// This marks the fact that the channel is actually disconnected.
this . _ channel = null ;
var fired = false ;