From 6cdf53df3892c7c550bf9f875c5d2e1036897fc9 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 10 Apr 2025 13:38:25 -0700 Subject: [PATCH 1/3] Handle null socket when receiving packets of data --- .../Data/SqlClient/SNI/SNITcpHandle.cs | 24 +++++++++++++++---- .../src/Resources/Strings.Designer.cs | 2 +- .../src/Resources/Strings.resx | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs index ca68cec63c..8bca937e6f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs @@ -809,17 +809,29 @@ public override uint Send(SNIPacket packet) } /// - /// Receive a packet synchronously + /// Receives a packet synchronously. /// - /// SNI packet - /// Timeout in Milliseconds - /// SNI error code + /// The received SNI packet. + /// + /// Timeout in milliseconds: + /// - If greater than 0, sets the socket's receive timeout to the specified value. + /// - If equal to -1, represents an infinite timeout (socket timeout is set to 0). + /// - If less than -1 or equal to 0, results in a timeout error. + /// + /// SNI error code indicating the result of the operation. public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds) { SNIPacket errorPacket; lock (this) { packet = null; + + if (_socket == null) + { + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.ERR, "Connection Id {0}, Socket is null.", args0: _connectionId); + return ReportTcpSNIError(0, SNICommon.ConnOpenFailedError, Strings.SNI_ERROR_10); + } + try { if (timeoutInMilliseconds > 0) @@ -884,7 +896,9 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds) } finally { - _socket.ReceiveTimeout = 0; + // Reset the socket timeout to 0 (infinite) after the receive operation is done + // to avoid blocking the thread in case of a timeout error. + _socket.ReceiveTimeout = Timeout.Infinite; } } } diff --git a/src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs index e5f2e9db93..48cbfee2e6 100644 --- a/src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs +++ b/src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs @@ -8326,7 +8326,7 @@ internal static string SNI_ERROR_1 { } /// - /// Looks up a localized string similar to . + /// Looks up a localized string similar to Socket is null. /// internal static string SNI_ERROR_10 { get { diff --git a/src/Microsoft.Data.SqlClient/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/src/Resources/Strings.resx index 6220147015..675e2e55fb 100644 --- a/src/Microsoft.Data.SqlClient/src/Resources/Strings.resx +++ b/src/Microsoft.Data.SqlClient/src/Resources/Strings.resx @@ -3805,7 +3805,7 @@ Associating port with I/O completion mechanism failed - + Socket is null Timeout error From 1a825d01c73f769f47e6c5afaac7d1470a467e4e Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 10 Apr 2025 13:41:54 -0700 Subject: [PATCH 2/3] Use Timeout.Infinite --- .../netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs index 8bca937e6f..ce4c9cac70 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs @@ -841,7 +841,7 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds) else if (timeoutInMilliseconds == -1) { // SqlClient internally represents infinite timeout by -1, and for TcpClient this is translated to a timeout of 0 - _socket.ReceiveTimeout = 0; + _socket.ReceiveTimeout = Timeout.Infinite; } else { @@ -896,7 +896,7 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds) } finally { - // Reset the socket timeout to 0 (infinite) after the receive operation is done + // Reset the socket timeout to -1 (Timeout.Infinite) after the receive operation is done // to avoid blocking the thread in case of a timeout error. _socket.ReceiveTimeout = Timeout.Infinite; } From 1f8b3e7efd30419e113b1d6c5280f1be5c198453 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Fri, 11 Apr 2025 07:41:26 -0700 Subject: [PATCH 3/3] Apply suggestions from code review --- .../netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs index ce4c9cac70..b3ecfb156a 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs @@ -840,7 +840,6 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds) } else if (timeoutInMilliseconds == -1) { - // SqlClient internally represents infinite timeout by -1, and for TcpClient this is translated to a timeout of 0 _socket.ReceiveTimeout = Timeout.Infinite; } else @@ -896,7 +895,7 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds) } finally { - // Reset the socket timeout to -1 (Timeout.Infinite) after the receive operation is done + // Reset the socket timeout to Timeout.Infinite after the receive operation is done // to avoid blocking the thread in case of a timeout error. _socket.ReceiveTimeout = Timeout.Infinite; }