@@ -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,7 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
426428 {
427429 if ( timeout . IsExpired )
428430 {
429- return null ;
431+ throw new Win32Exception ( 258 , "The operation has timed out." ) ;
430432 }
431433
432434 int socketSelectTimeout =
@@ -442,10 +444,24 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
442444
443445 Socket . Select ( checkReadLst , checkWriteLst , checkErrorLst , socketSelectTimeout ) ;
444446 // nothing selected means timeout
447+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO ,
448+ "Socket.Select results: checkReadLst.Count: {0}, checkWriteLst.Count: {1}, checkErrorLst.Count: {2}" ,
449+ checkReadLst . Count , checkWriteLst . Count , checkErrorLst . Count ) ;
445450 } while ( checkReadLst . Count == 0 && checkWriteLst . Count == 0 && checkErrorLst . Count == 0 ) ;
446451
447452 // workaround: false positive socket.Connected on linux: https://github.com/dotnet/runtime/issues/55538
448453 isConnected = socket . Connected && checkErrorLst . Count == 0 ;
454+ if ( ! isConnected )
455+ {
456+ // Retrieve the socket error code
457+ int socketErrorCode = ( int ) socket . GetSocketOption ( SocketOptionLevel . Socket , SocketOptionName . Error ) ;
458+ SocketError socketError = ( SocketError ) socketErrorCode ;
459+
460+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . ERR ,
461+ "Socket connection failed. SocketError: {0} ({1})" , socketError , socketErrorCode ) ;
462+
463+ lastSocketException = new SocketException ( socketErrorCode ) ;
464+ }
449465 }
450466
451467 if ( isConnected )
@@ -463,6 +479,8 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
463479 }
464480 pendingDNSInfo = new SQLDNSInfo ( cachedFQDN , iPv4String , iPv6String , port . ToString ( ) ) ;
465481 isSocketSelected = true ;
482+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO ,
483+ "Connected to socket: {0}" , socket . RemoteEndPoint ) ;
466484 return socket ;
467485 }
468486 }
@@ -471,6 +489,7 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
471489 SqlClientEventSource . Log . TryAdvancedTraceEvent (
472490 "{0}.{1}{2}THIS EXCEPTION IS BEING SWALLOWED: {3}" ,
473491 nameof ( SniTcpHandle ) , nameof ( Connect ) , EventType . ERR , e ) ;
492+ lastSocketException = e ;
474493 }
475494 finally
476495 {
@@ -479,6 +498,14 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
479498 }
480499 }
481500
501+ if ( lastSocketException != null )
502+ {
503+ SqlClientEventSource . Log . TryAdvancedTraceEvent (
504+ "{0}.{1}{2}Last Socket Exception: {3}" ,
505+ nameof ( SniTcpHandle ) , nameof ( Connect ) , EventType . ERR , lastSocketException ) ;
506+ throw lastSocketException ;
507+ }
508+
482509 return null ;
483510 }
484511 }
@@ -574,6 +601,20 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
574601 Socket . Select ( checkReadLst , checkWriteLst , checkErrorLst , socketSelectTimeout ) ;
575602 // nothing selected means select timed out
576603 } while ( checkReadLst . Count == 0 && checkWriteLst . Count == 0 && checkErrorLst . Count == 0 && ! timeout . IsExpired ) ;
604+ foreach ( Socket socket in checkErrorLst )
605+ {
606+ // Retrieve the socket error code
607+ int socketErrorCode = ( int ) socket . GetSocketOption ( SocketOptionLevel . Socket , SocketOptionName . Error ) ;
608+ SocketError socketError = ( SocketError ) socketErrorCode ;
609+
610+ // Log any failed sockets
611+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO ,
612+ "Socket connection failed for {0}. SocketError: {1} ({2})" ,
613+ sockets [ socket ] , socketError , socketErrorCode ) ;
614+
615+ lastError = new SocketException ( socketErrorCode ) ;
616+ }
617+
577618 }
578619 catch ( SocketException e )
579620 {
@@ -588,6 +629,7 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
588629 {
589630 SqlClientEventSource . Log . TryAdvancedTraceEvent (
590631 "{0}.{1}{2}ParallelConnect timeout expired." , nameof ( SniTcpHandle ) , nameof ( ParallelConnect ) , EventType . INFO ) ;
632+ // We will throw below after cleanup
591633 break ;
592634 }
593635
@@ -654,9 +696,19 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
654696
655697 if ( connectedSocket == null )
656698 {
699+ if ( timeout . IsExpired )
700+ {
701+ throw new Win32Exception ( 258 , "The operation has timed out." ) ;
702+ }
703+
657704 SqlClientEventSource . Log . TryAdvancedTraceEvent (
658- "{0}.{1}{2}No socket connections succeeded. Last error: {3}" ,
705+ "{0}.{1}{2} No socket connections succeeded. Last error: {3}" ,
659706 nameof ( SniTcpHandle ) , nameof ( ParallelConnect ) , EventType . ERR , lastError ) ;
707+
708+ if ( lastError != null )
709+ {
710+ throw lastError ;
711+ }
660712 }
661713
662714 return connectedSocket ;
@@ -861,7 +913,7 @@ public override uint Receive(out SniPacket packet, int timeoutInMilliseconds)
861913 packet = null ;
862914 var e = new Win32Exception ( ) ;
863915 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 ) ;
916+ return ReportErrorAndReleasePacket ( errorPacket , e . NativeErrorCode , 0 , e . Message ) ;
865917 }
866918
867919 SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO , "Connection Id {0}, Data read from stream synchronously" , args0 : _connectionId ) ;
@@ -992,13 +1044,13 @@ public override uint CheckConnection()
9921044 return TdsEnums . SNI_SUCCESS ;
9931045 }
9941046
995- private uint ReportTcpSNIError ( Exception sniException , uint nativeErrorCode = 0 )
1047+ private uint ReportTcpSNIError ( Exception sniException , int nativeErrorCode = 0 )
9961048 {
9971049 _status = TdsEnums . SNI_ERROR ;
9981050 return SniCommon . ReportSNIError ( SniProviders . TCP_PROV , SniCommon . InternalExceptionError , sniException , nativeErrorCode ) ;
9991051 }
10001052
1001- private uint ReportTcpSNIError ( uint nativeError , uint sniError , string errorMessage )
1053+ private uint ReportTcpSNIError ( int nativeError , uint sniError , string errorMessage )
10021054 {
10031055 _status = TdsEnums . SNI_ERROR ;
10041056 return SniCommon . ReportSNIError ( SniProviders . TCP_PROV , nativeError , sniError , errorMessage ) ;
@@ -1013,7 +1065,7 @@ private uint ReportErrorAndReleasePacket(SniPacket packet, Exception sniExceptio
10131065 return ReportTcpSNIError ( sniException ) ;
10141066 }
10151067
1016- private uint ReportErrorAndReleasePacket ( SniPacket packet , uint nativeError , uint sniError , string errorMessage )
1068+ private uint ReportErrorAndReleasePacket ( SniPacket packet , int nativeError , uint sniError , string errorMessage )
10171069 {
10181070 if ( packet != null )
10191071 {
0 commit comments