@@ -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,9 @@ 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 (
432
+ TdsEnums . SNI_WAIT_TIMEOUT ,
433
+ StringsHelper . GetString ( Strings . SQL_ConnectTimeout ) ) ;
430
434
}
431
435
432
436
int socketSelectTimeout =
@@ -442,10 +446,24 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
442
446
443
447
Socket . Select ( checkReadLst , checkWriteLst , checkErrorLst , socketSelectTimeout ) ;
444
448
// 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 ) ;
445
452
} while ( checkReadLst . Count == 0 && checkWriteLst . Count == 0 && checkErrorLst . Count == 0 ) ;
446
453
447
454
// workaround: false positive socket.Connected on linux: https://github.com/dotnet/runtime/issues/55538
448
455
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
+ }
449
467
}
450
468
451
469
if ( isConnected )
@@ -463,6 +481,8 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
463
481
}
464
482
pendingDNSInfo = new SQLDNSInfo ( cachedFQDN , iPv4String , iPv6String , port . ToString ( ) ) ;
465
483
isSocketSelected = true ;
484
+ SqlClientEventSource . Log . TrySNITraceEvent ( nameof ( SniTcpHandle ) , EventType . INFO ,
485
+ "Connected to socket: {0}" , socket . RemoteEndPoint ) ;
466
486
return socket ;
467
487
}
468
488
}
@@ -471,6 +491,7 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
471
491
SqlClientEventSource . Log . TryAdvancedTraceEvent (
472
492
"{0}.{1}{2}THIS EXCEPTION IS BEING SWALLOWED: {3}" ,
473
493
nameof ( SniTcpHandle ) , nameof ( Connect ) , EventType . ERR , e ) ;
494
+ lastSocketException = e ;
474
495
}
475
496
finally
476
497
{
@@ -479,6 +500,14 @@ private static Socket Connect(string serverName, int port, TimeoutTimer timeout,
479
500
}
480
501
}
481
502
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
+
482
511
return null ;
483
512
}
484
513
}
@@ -574,6 +603,20 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
574
603
Socket . Select ( checkReadLst , checkWriteLst , checkErrorLst , socketSelectTimeout ) ;
575
604
// nothing selected means select timed out
576
605
} 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
+
577
620
}
578
621
catch ( SocketException e )
579
622
{
@@ -588,6 +631,7 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
588
631
{
589
632
SqlClientEventSource . Log . TryAdvancedTraceEvent (
590
633
"{0}.{1}{2}ParallelConnect timeout expired." , nameof ( SniTcpHandle ) , nameof ( ParallelConnect ) , EventType . INFO ) ;
634
+ // We will throw below after cleanup
591
635
break ;
592
636
}
593
637
@@ -654,9 +698,21 @@ private static Socket ParallelConnect(IPAddress[] serverAddresses, int port, Tim
654
698
655
699
if ( connectedSocket == null )
656
700
{
701
+ if ( timeout . IsExpired )
702
+ {
703
+ throw new Win32Exception (
704
+ TdsEnums . SNI_WAIT_TIMEOUT ,
705
+ StringsHelper . GetString ( Strings . SQL_ConnectTimeout ) ) ;
706
+ }
707
+
657
708
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}" ,
659
710
nameof ( SniTcpHandle ) , nameof ( ParallelConnect ) , EventType . ERR , lastError ) ;
711
+
712
+ if ( lastError != null )
713
+ {
714
+ throw lastError ;
715
+ }
660
716
}
661
717
662
718
return connectedSocket ;
@@ -861,7 +917,7 @@ public override uint Receive(out SniPacket packet, int timeoutInMilliseconds)
861
917
packet = null ;
862
918
var e = new Win32Exception ( ) ;
863
919
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 ) ;
865
921
}
866
922
867
923
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()
992
1048
return TdsEnums . SNI_SUCCESS ;
993
1049
}
994
1050
995
- private uint ReportTcpSNIError ( Exception sniException , uint nativeErrorCode = 0 )
1051
+ private uint ReportTcpSNIError ( Exception sniException , int nativeErrorCode = 0 )
996
1052
{
997
1053
_status = TdsEnums . SNI_ERROR ;
998
1054
return SniCommon . ReportSNIError ( SniProviders . TCP_PROV , SniCommon . InternalExceptionError , sniException , nativeErrorCode ) ;
999
1055
}
1000
1056
1001
- private uint ReportTcpSNIError ( uint nativeError , uint sniError , string errorMessage )
1057
+ private uint ReportTcpSNIError ( int nativeError , uint sniError , string errorMessage )
1002
1058
{
1003
1059
_status = TdsEnums . SNI_ERROR ;
1004
1060
return SniCommon . ReportSNIError ( SniProviders . TCP_PROV , nativeError , sniError , errorMessage ) ;
@@ -1013,7 +1069,7 @@ private uint ReportErrorAndReleasePacket(SniPacket packet, Exception sniExceptio
1013
1069
return ReportTcpSNIError ( sniException ) ;
1014
1070
}
1015
1071
1016
- private uint ReportErrorAndReleasePacket ( SniPacket packet , uint nativeError , uint sniError , string errorMessage )
1072
+ private uint ReportErrorAndReleasePacket ( SniPacket packet , int nativeError , uint sniError , string errorMessage )
1017
1073
{
1018
1074
if ( packet != null )
1019
1075
{
0 commit comments