@@ -66,6 +66,7 @@ let freeParser;
6666let HTTPParser ;
6767
6868const MAX_HANDLE_RETRANSMISSIONS = 3 ;
69+ const kChannelHandle = Symbol ( 'kChannelHandle' ) ;
6970const kIsUsedAsStdio = Symbol ( 'kIsUsedAsStdio' ) ;
7071
7172// This object contain function to convert TCP objects to native handle objects
@@ -108,7 +109,7 @@ const handleConversion = {
108109 // The worker should keep track of the socket
109110 message . key = socket . server . _connectionKey ;
110111
111- const firstTime = ! this . channel . sockets . send [ message . key ] ;
112+ const firstTime = ! this [ kChannelHandle ] . sockets . send [ message . key ] ;
112113 const socketList = getSocketList ( 'send' , this , message . key ) ;
113114
114115 // The server should no longer expose a .connection property
@@ -508,30 +509,55 @@ ChildProcess.prototype.unref = function() {
508509} ;
509510
510511class Control extends EventEmitter {
512+ #channel = null ;
513+ #refs = 0 ;
514+ #refExplicitlySet = false ;
515+
511516 constructor ( channel ) {
512517 super ( ) ;
513- this . channel = channel ;
514- this . refs = 0 ;
518+ this . #channel = channel ;
515519 }
516- ref ( ) {
517- if ( ++ this . refs === 1 ) {
518- this . channel . ref ( ) ;
520+
521+ // The methods keeping track of the counter are being used to track the
522+ // listener count on the child process object as well as when writes are
523+ // in progress. Once the user has explicitly requested a certain state, these
524+ // methods become no-ops in order to not interfere with the user's intentions.
525+ refCounted ( ) {
526+ if ( ++ this . #refs === 1 && ! this . #refExplicitlySet) {
527+ this . #channel. ref ( ) ;
519528 }
520529 }
521- unref ( ) {
522- if ( -- this . refs === 0 ) {
523- this . channel . unref ( ) ;
530+
531+ unrefCounted ( ) {
532+ if ( -- this . #refs === 0 && ! this . #refExplicitlySet) {
533+ this . #channel. unref ( ) ;
524534 this . emit ( 'unref' ) ;
525535 }
526536 }
537+
538+ ref ( ) {
539+ this . #refExplicitlySet = true ;
540+ this . #channel. ref ( ) ;
541+ }
542+
543+ unref ( ) {
544+ this . #refExplicitlySet = true ;
545+ this . #channel. unref ( ) ;
546+ }
547+
548+ get fd ( ) {
549+ return this . #channel ? this . #channel. fd : undefined ;
550+ }
527551}
528552
529553const channelDeprecationMsg = '_channel is deprecated. ' +
530554 'Use ChildProcess.channel instead.' ;
531555
532556let serialization ;
533557function setupChannel ( target , channel , serializationMode ) {
534- target . channel = channel ;
558+ const control = new Control ( channel ) ;
559+ target . channel = control ;
560+ target [ kChannelHandle ] = channel ;
535561
536562 ObjectDefineProperty ( target , '_channel' , {
537563 get : deprecate ( ( ) => {
@@ -547,8 +573,6 @@ function setupChannel(target, channel, serializationMode) {
547573 target . _handleQueue = null ;
548574 target . _pendingMessage = null ;
549575
550- const control = new Control ( channel ) ;
551-
552576 if ( serialization === undefined )
553577 serialization = require ( 'internal/child_process/serialization' ) ;
554578 const {
@@ -796,11 +820,11 @@ function setupChannel(target, channel, serializationMode) {
796820
797821 if ( wasAsyncWrite ) {
798822 req . oncomplete = ( ) => {
799- control . unref ( ) ;
823+ control . unrefCounted ( ) ;
800824 if ( typeof callback === 'function' )
801825 callback ( null ) ;
802826 } ;
803- control . ref ( ) ;
827+ control . refCounted ( ) ;
804828 } else if ( typeof callback === 'function' ) {
805829 process . nextTick ( callback , null ) ;
806830 }
@@ -855,6 +879,7 @@ function setupChannel(target, channel, serializationMode) {
855879
856880 // This marks the fact that the channel is actually disconnected.
857881 this . channel = null ;
882+ this [ kChannelHandle ] = null ;
858883
859884 if ( this . _pendingMessage )
860885 closePendingHandle ( this ) ;
@@ -1011,7 +1036,7 @@ function getValidStdio(stdio, sync) {
10111036
10121037
10131038function getSocketList ( type , worker , key ) {
1014- const sockets = worker . channel . sockets [ type ] ;
1039+ const sockets = worker [ kChannelHandle ] . sockets [ type ] ;
10151040 let socketList = sockets [ key ] ;
10161041 if ( ! socketList ) {
10171042 const Construct = type === 'send' ? SocketListSend : SocketListReceive ;
@@ -1054,6 +1079,7 @@ function spawnSync(options) {
10541079
10551080module . exports = {
10561081 ChildProcess,
1082+ kChannelHandle,
10571083 setupChannel,
10581084 getValidStdio,
10591085 stdioStringToArray,
0 commit comments