@@ -375,6 +375,8 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
375
375
376
376
IEnumerable < IPAddress > ipAddresses = GetHostAddressesSortedByPreference ( serverName , ipPreference ) ;
377
377
378
+ SocketException lastSocketException = null ;
379
+
378
380
foreach ( IPAddress ipAddress in ipAddresses )
379
381
{
380
382
bool isSocketSelected = false ;
@@ -426,7 +428,7 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
426
428
{
427
429
if ( timeout . IsExpired )
428
430
{
429
- return null ;
431
+ throw new Win32Exception ( 258 , "The operation has timed out." ) ;
430
432
}
431
433
432
434
int socketSelectTimeout =
@@ -442,10 +444,24 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
442
444
443
445
Socket . Select ( checkReadLst , checkWriteLst , checkErrorLst , socketSelectTimeout ) ;
444
446
// 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 ) ;
445
450
} while ( checkReadLst . Count == 0 && checkWriteLst . Count == 0 && checkErrorLst . Count == 0 ) ;
446
451
447
452
// workaround: false positive socket.Connected on linux: https://github.com/dotnet/runtime/issues/55538
448
453
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
+ }
449
465
}
450
466
451
467
if ( isConnected )
@@ -463,6 +479,8 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
463
479
}
464
480
pendingDNSInfo = new SQLDNSInfo ( cachedFQDN , iPv4String , iPv6String , port . ToString ( ) ) ;
465
481
isSocketSelected = true ;
482
+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO ,
483
+ "Connected to socket: {0}" , socket . RemoteEndPoint ) ;
466
484
return socket ;
467
485
}
468
486
}
@@ -471,6 +489,7 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
471
489
SqlClientEventSource . Log . TryAdvancedTraceEvent (
472
490
"{0}.{1}{2}THIS EXCEPTION IS BEING SWALLOWED: {3}" ,
473
491
nameof ( SniTcpHandle ) , nameof ( Connect ) , EventType . ERR , e ) ;
492
+ lastSocketException = e ;
474
493
}
475
494
finally
476
495
{
@@ -479,6 +498,14 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
479
498
}
480
499
}
481
500
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
+
482
509
return null ;
483
510
}
484
511
}
@@ -574,6 +601,20 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
574
601
Socket . Select ( checkReadLst , checkWriteLst , checkErrorLst , socketSelectTimeout ) ;
575
602
// nothing selected means select timed out
576
603
} 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
+
577
618
}
578
619
catch ( SocketException e )
579
620
{
@@ -588,6 +629,7 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
588
629
{
589
630
SqlClientEventSource . Log . TryAdvancedTraceEvent (
590
631
"{0}.{1}{2}ParallelConnect timeout expired." , nameof ( SniTcpHandle ) , nameof ( ParallelConnect ) , EventType . INFO ) ;
632
+ // We will throw below after cleanup
591
633
break ;
592
634
}
593
635
@@ -654,9 +696,19 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
654
696
655
697
if ( connectedSocket == null )
656
698
{
699
+ if ( timeout . IsExpired )
700
+ {
701
+ throw new Win32Exception ( 258 , "The operation has timed out." ) ;
702
+ }
703
+
657
704
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}" ,
659
706
nameof ( SniTcpHandle ) , nameof ( ParallelConnect ) , EventType . ERR , lastError ) ;
707
+
708
+ if ( lastError != null )
709
+ {
710
+ throw lastError ;
711
+ }
660
712
}
661
713
662
714
return connectedSocket ;
@@ -861,7 +913,7 @@ public override uint Receive(out SniPacket packet, int timeoutInMilliseconds)
861
913
packet = null ;
862
914
var e = new Win32Exception ( ) ;
863
915
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 ) ;
865
917
}
866
918
867
919
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()
992
1044
return TdsEnums . SNI_SUCCESS ;
993
1045
}
994
1046
995
- private uint ReportTcpSNIError ( Exception sniException , uint nativeErrorCode = 0 )
1047
+ private uint ReportTcpSNIError ( Exception sniException , int nativeErrorCode = 0 )
996
1048
{
997
1049
_status = TdsEnums . SNI_ERROR ;
998
1050
return SniCommon . ReportSNIError ( SniProviders . TCP_PROV , SniCommon . InternalExceptionError , sniException , nativeErrorCode ) ;
999
1051
}
1000
1052
1001
- private uint ReportTcpSNIError ( uint nativeError , uint sniError , string errorMessage )
1053
+ private uint ReportTcpSNIError ( int nativeError , uint sniError , string errorMessage )
1002
1054
{
1003
1055
_status = TdsEnums . SNI_ERROR ;
1004
1056
return SniCommon . ReportSNIError ( SniProviders . TCP_PROV , nativeError , sniError , errorMessage ) ;
@@ -1013,7 +1065,7 @@ private uint ReportErrorAndReleasePacket(SniPacket packet, Exception sniExceptio
1013
1065
return ReportTcpSNIError ( sniException ) ;
1014
1066
}
1015
1067
1016
- private uint ReportErrorAndReleasePacket ( SniPacket packet , uint nativeError , uint sniError , string errorMessage )
1068
+ private uint ReportErrorAndReleasePacket ( SniPacket packet , int nativeError , uint sniError , string errorMessage )
1017
1069
{
1018
1070
if ( packet != null )
1019
1071
{
0 commit comments