@@ -871,6 +871,27 @@ function afterWrite(status, handle, req, err) {
871871}
872872
873873
874+ function checkBindError ( err , port , handle ) {
875+ // EADDRINUSE may not be reported until we call listen() or connect().
876+ // To complicate matters, a failed bind() followed by listen() or connect()
877+ // will implicitly bind to a random port. Ergo, check that the socket is
878+ // bound to the expected port before calling listen() or connect().
879+ //
880+ // FIXME(bnoordhuis) Doesn't work for pipe handles, they don't have a
881+ // getsockname() method. Non-issue for now, the cluster module doesn't
882+ // really support pipes anyway.
883+ if ( err === 0 && port > 0 && handle . getsockname ) {
884+ var out = { } ;
885+ err = handle . getsockname ( out ) ;
886+ if ( err === 0 && port !== out . port ) {
887+ debug ( `checkBindError, bound to ${ out . port } instead of ${ port } ` ) ;
888+ err = uv . UV_EADDRINUSE ;
889+ }
890+ }
891+ return err ;
892+ }
893+
894+
874895function internalConnect (
875896 self , address , port , addressType , localAddress , localPort ) {
876897 // TODO return promise from Socket.prototype.connect which
@@ -894,6 +915,7 @@ function internalConnect(
894915 debug ( 'binding to localAddress: %s and localPort: %d (addressType: %d)' ,
895916 localAddress , localPort , addressType ) ;
896917
918+ err = checkBindError ( err , localPort , self . _handle ) ;
897919 if ( err ) {
898920 const ex = exceptionWithHostPort ( err , 'bind' , localAddress , localPort ) ;
899921 self . destroy ( ex ) ;
@@ -1382,20 +1404,7 @@ function listenInCluster(server, address, port, addressType,
13821404 cluster . _getServer ( server , serverQuery , listenOnMasterHandle ) ;
13831405
13841406 function listenOnMasterHandle ( err , handle ) {
1385- // EADDRINUSE may not be reported until we call listen(). To complicate
1386- // matters, a failed bind() followed by listen() will implicitly bind to
1387- // a random port. Ergo, check that the socket is bound to the expected
1388- // port before calling listen().
1389- //
1390- // FIXME(bnoordhuis) Doesn't work for pipe handles, they don't have a
1391- // getsockname() method. Non-issue for now, the cluster module doesn't
1392- // really support pipes anyway.
1393- if ( err === 0 && port > 0 && handle . getsockname ) {
1394- var out = { } ;
1395- err = handle . getsockname ( out ) ;
1396- if ( err === 0 && port !== out . port )
1397- err = uv . UV_EADDRINUSE ;
1398- }
1407+ err = checkBindError ( err , port , handle ) ;
13991408
14001409 if ( err ) {
14011410 var ex = exceptionWithHostPort ( err , 'bind' , address , port ) ;
0 commit comments