22
22
'use strict' ;
23
23
const { spawn } = require ( 'child_process' ) ;
24
24
const { EventEmitter } = require ( 'events' ) ;
25
+ const net = require ( 'net' ) ;
25
26
const util = require ( 'util' ) ;
26
27
27
28
const runAsStandalone = typeof __dirname !== 'undefined' ;
@@ -90,6 +91,45 @@ function createAgentProxy(domain, client) {
90
91
} ) ;
91
92
}
92
93
94
+ function portIsFree ( host , port , timeout = 2000 ) {
95
+ const retryDelay = 150 ;
96
+ let didTimeOut = false ;
97
+
98
+ return new Promise ( ( resolve , reject ) => {
99
+ setTimeout ( ( ) => {
100
+ didTimeOut = true ;
101
+ reject ( new Error (
102
+ `Timeout (${ timeout } ) waiting for ${ host } :${ port } to be free` ) ) ;
103
+ } , timeout ) ;
104
+
105
+ function pingPort ( ) {
106
+ if ( didTimeOut ) return ;
107
+
108
+ const socket = net . connect ( port , host ) ;
109
+ let didRetry = false ;
110
+ function retry ( ) {
111
+ if ( ! didRetry && ! didTimeOut ) {
112
+ didRetry = true ;
113
+ setTimeout ( pingPort , retryDelay ) ;
114
+ }
115
+ }
116
+
117
+ socket . on ( 'error' , ( error ) => {
118
+ if ( error . code === 'ECONNREFUSED' ) {
119
+ resolve ( ) ;
120
+ } else {
121
+ retry ( ) ;
122
+ }
123
+ } ) ;
124
+ socket . on ( 'connect' , ( ) => {
125
+ socket . destroy ( ) ;
126
+ retry ( ) ;
127
+ } ) ;
128
+ }
129
+ pingPort ( ) ;
130
+ } ) ;
131
+ }
132
+
93
133
class NodeInspector {
94
134
constructor ( options , stdin , stdout ) {
95
135
this . options = options ;
@@ -169,7 +209,14 @@ class NodeInspector {
169
209
170
210
run ( ) {
171
211
this . killChild ( ) ;
172
- return this . _runScript ( ) . then ( ( child ) => {
212
+ const { host, port } = this . options ;
213
+
214
+ const runOncePortIsFree = ( ) => {
215
+ return portIsFree ( host , port )
216
+ . then ( ( ) => this . _runScript ( ) ) ;
217
+ } ;
218
+
219
+ return runOncePortIsFree ( ) . then ( ( child ) => {
173
220
this . child = child ;
174
221
175
222
let connectionAttempts = 0 ;
@@ -194,7 +241,6 @@ class NodeInspector {
194
241
} ) ;
195
242
} ;
196
243
197
- const { host, port } = this . options ;
198
244
this . print ( `connecting to ${ host } :${ port } ..` , true ) ;
199
245
return attemptConnect ( ) ;
200
246
} ) ;
0 commit comments