@@ -375,6 +375,8 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
375375
376376 IEnumerable < IPAddress > ipAddresses = GetHostAddressesSortedByPreference ( serverName , ipPreference ) ;
377377
378+ SocketException lastSocketException = null ;
379+
378380 foreach ( IPAddress ipAddress in ipAddresses )
379381 {
380382 bool isSocketSelected = false ;
@@ -426,7 +428,9 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
426428 {
427429 if ( timeout . IsExpired )
428430 {
429- return null ;
431+ throw new Win32Exception (
432+ TdsEnums . SNI_WAIT_TIMEOUT ,
433+ StringsHelper . GetString ( Strings . SQL_ConnectTimeout ) ) ;
430434 }
431435
432436 int socketSelectTimeout =
@@ -442,10 +446,24 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
442446
443447 Socket . Select ( checkReadLst , checkWriteLst , checkErrorLst , socketSelectTimeout ) ;
444448 // nothing selected means timeout
449+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO ,
450+ "Socket.Select results: checkReadLst.Count: {0}, checkWriteLst.Count: {1}, checkErrorLst.Count: {2}" ,
451+ checkReadLst . Count , checkWriteLst . Count , checkErrorLst . Count ) ;
445452 } while ( checkReadLst . Count == 0 && checkWriteLst . Count == 0 && checkErrorLst . Count == 0 ) ;
446453
447454 // workaround: false positive socket.Connected on linux: https://github.com/dotnet/runtime/issues/55538
448455 isConnected = socket . Connected && checkErrorLst . Count == 0 ;
456+ if ( ! isConnected )
457+ {
458+ // Retrieve the socket error code
459+ int socketErrorCode = ( int ) socket . GetSocketOption ( SocketOptionLevel . Socket , SocketOptionName . Error ) ;
460+ SocketError socketError = ( SocketError ) socketErrorCode ;
461+
462+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . ERR ,
463+ "Socket connection failed. SocketError: {0} ({1})" , socketError , socketErrorCode ) ;
464+
465+ lastSocketException = new SocketException ( socketErrorCode ) ;
466+ }
449467 }
450468
451469 if ( isConnected )
@@ -463,6 +481,8 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
463481 }
464482 pendingDNSInfo = new SQLDNSInfo ( cachedFQDN , iPv4String , iPv6String , port . ToString ( ) ) ;
465483 isSocketSelected = true ;
484+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO ,
485+ "Connected to socket: {0}" , socket . RemoteEndPoint ) ;
466486 return socket ;
467487 }
468488 }
@@ -471,6 +491,7 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
471491 SqlClientEventSource . Log . TryAdvancedTraceEvent (
472492 "{0}.{1}{2}THIS EXCEPTION IS BEING SWALLOWED: {3}" ,
473493 nameof ( SniTcpHandle ) , nameof ( Connect ) , EventType . ERR , e ) ;
494+ lastSocketException = e ;
474495 }
475496 finally
476497 {
@@ -479,6 +500,14 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
479500 }
480501 }
481502
503+ if ( lastSocketException != null )
504+ {
505+ SqlClientEventSource . Log . TryAdvancedTraceEvent (
506+ "{0}.{1}{2}Last Socket Exception: {3}" ,
507+ nameof ( SniTcpHandle ) , nameof ( Connect ) , EventType . ERR , lastSocketException ) ;
508+ throw lastSocketException ;
509+ }
510+
482511 return null ;
483512 }
484513 }
@@ -574,6 +603,20 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
574603 Socket . Select ( checkReadLst , checkWriteLst , checkErrorLst , socketSelectTimeout ) ;
575604 // nothing selected means select timed out
576605 } while ( checkReadLst . Count == 0 && checkWriteLst . Count == 0 && checkErrorLst . Count == 0 && ! timeout . IsExpired ) ;
606+ foreach ( Socket socket in checkErrorLst )
607+ {
608+ // Retrieve the socket error code
609+ int socketErrorCode = ( int ) socket . GetSocketOption ( SocketOptionLevel . Socket , SocketOptionName . Error ) ;
610+ SocketError socketError = ( SocketError ) socketErrorCode ;
611+
612+ // Log any failed sockets
613+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO ,
614+ "Socket connection failed for {0}. SocketError: {1} ({2})" ,
615+ sockets [ socket ] , socketError , socketErrorCode ) ;
616+
617+ lastError = new SocketException ( socketErrorCode ) ;
618+ }
619+
577620 }
578621 catch ( SocketException e )
579622 {
@@ -588,6 +631,7 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
588631 {
589632 SqlClientEventSource . Log . TryAdvancedTraceEvent (
590633 "{0}.{1}{2}ParallelConnect timeout expired." , nameof ( SniTcpHandle ) , nameof ( ParallelConnect ) , EventType . INFO ) ;
634+ // We will throw below after cleanup
591635 break ;
592636 }
593637
@@ -654,9 +698,21 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
654698
655699 if ( connectedSocket == null )
656700 {
701+ if ( timeout . IsExpired )
702+ {
703+ throw new Win32Exception (
704+ TdsEnums . SNI_WAIT_TIMEOUT ,
705+ StringsHelper . GetString ( Strings . SQL_ConnectTimeout ) ) ;
706+ }
707+
657708 SqlClientEventSource . Log . TryAdvancedTraceEvent (
658- "{0}.{1}{2}No socket connections succeeded. Last error: {3}" ,
709+ "{0}.{1}{2} No socket connections succeeded. Last error: {3}" ,
659710 nameof ( SniTcpHandle ) , nameof ( ParallelConnect ) , EventType . ERR , lastError ) ;
711+
712+ if ( lastError != null )
713+ {
714+ throw lastError ;
715+ }
660716 }
661717
662718 return connectedSocket ;
@@ -861,7 +917,7 @@ public override uint Receive(out SniPacket packet, int timeoutInMilliseconds)
861917 packet = null ;
862918 var e = new Win32Exception ( ) ;
863919 SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . ERR , "Connection Id {0}, Win32 exception occurred: {1}" , args0 : _connectionId , args1 : e ? . Message ) ;
864- return ReportErrorAndReleasePacket ( errorPacket , ( uint ) e . NativeErrorCode , 0 , e . Message ) ;
920+ return ReportErrorAndReleasePacket ( errorPacket , e . NativeErrorCode , 0 , e . Message ) ;
865921 }
866922
867923 SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO , "Connection Id {0}, Data read from stream synchronously" , args0 : _connectionId ) ;
@@ -992,13 +1048,13 @@ public override uint CheckConnection()
9921048 return TdsEnums . SNI_SUCCESS ;
9931049 }
9941050
995- private uint ReportTcpSNIError ( Exception sniException , uint nativeErrorCode = 0 )
1051+ private uint ReportTcpSNIError ( Exception sniException , int nativeErrorCode = 0 )
9961052 {
9971053 _status = TdsEnums . SNI_ERROR ;
9981054 return SniCommon . ReportSNIError ( SniProviders . TCP_PROV , SniCommon . InternalExceptionError , sniException , nativeErrorCode ) ;
9991055 }
10001056
1001- private uint ReportTcpSNIError ( uint nativeError , uint sniError , string errorMessage )
1057+ private uint ReportTcpSNIError ( int nativeError , uint sniError , string errorMessage )
10021058 {
10031059 _status = TdsEnums . SNI_ERROR ;
10041060 return SniCommon . ReportSNIError ( SniProviders . TCP_PROV , nativeError , sniError , errorMessage ) ;
@@ -1013,7 +1069,7 @@ private uint ReportErrorAndReleasePacket(SniPacket packet, Exception sniExceptio
10131069 return ReportTcpSNIError ( sniException ) ;
10141070 }
10151071
1016- private uint ReportErrorAndReleasePacket ( SniPacket packet , uint nativeError , uint sniError , string errorMessage )
1072+ private uint ReportErrorAndReleasePacket ( SniPacket packet , int nativeError , uint sniError , string errorMessage )
10171073 {
10181074 if ( packet != null )
10191075 {
0 commit comments