From dd48b05151c56fcf92cacc071f80fd39c099cadc Mon Sep 17 00:00:00 2001 From: Gene Lee Date: Thu, 21 Sep 2017 02:25:47 -0700 Subject: [PATCH] Fix for 2nd Connection hangs in Mirroring Environment (#24181) --- .../SqlClient/SqlInternalConnectionTds.cs | 2 +- .../ConnectionOnMirroringTest.cs | 97 +++++++++++++++++++ ....Data.SqlClient.ManualTesting.Tests.csproj | 1 + 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlInternalConnectionTds.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlInternalConnectionTds.cs index 0bc0df2c97ac..f5c03bb81cf8 100644 --- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlInternalConnectionTds.cs @@ -1416,7 +1416,7 @@ TimeoutTimer timeout // Determine unit interval if (timeout.IsInfinite) { - timeoutUnitInterval = checked((long)ADP.FailoverTimeoutStep * ADP.TimerFromSeconds(ADP.DefaultConnectionTimeout)); + timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * ADP.TimerFromSeconds(ADP.DefaultConnectionTimeout))); } else { diff --git a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs new file mode 100644 index 000000000000..ac72f03d1c0d --- /dev/null +++ b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; + +namespace System.Data.SqlClient.ManualTesting.Tests +{ + public static class ConnectionOnMirroringTest + { + private static ManualResetEvent workerCompletedEvent = new ManualResetEvent(false); + + [CheckConnStrSetupFact] + public static void TestMultipleConnectionToMirroredServer() + { + string mirroringStateDesc; + string failoverPartnerName; + bool isMirroring = GetMirroringInfo(DataTestUtility.TcpConnStr, out mirroringStateDesc, out failoverPartnerName); + bool isSynchronized = "SYNCHRONIZED".Equals(mirroringStateDesc, StringComparison.InvariantCultureIgnoreCase); + if (isMirroring && isSynchronized && !string.IsNullOrEmpty(failoverPartnerName)) + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TcpConnStr); + builder.ConnectTimeout = 0; + + TestWorker worker = new TestWorker(builder.ConnectionString); + Thread childThread = new Thread(() => worker.TestMultipleConnection()); + childThread.Start(); + + if (workerCompletedEvent.WaitOne(10000)) + { + childThread.Join(); + } + else + { + // currently Thread.Abort() throws PlatformNotSupportedException in CoreFx. + childThread.Interrupt(); + throw new Exception("SqlConnection could not open and close successfully in timely manner. Possibly connection hangs."); + } + } + } + + private static bool GetMirroringInfo(string connectionString, out string mirroringStateDesc, out string failoverPartnerName) + { + mirroringStateDesc = null; + failoverPartnerName = null; + + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString); + string dbname = builder.InitialCatalog; + + builder.ConnectTimeout = 5; + connectionString = builder.ConnectionString; + + DataTable dt = DataTestUtility.RunQuery(connectionString, $"select mirroring_state_desc from sys.database_mirroring where database_id = DB_ID('{dbname}')"); + mirroringStateDesc = dt.Rows[0][0].ToString(); + + bool isMirroring = !string.IsNullOrEmpty(mirroringStateDesc); + if (isMirroring) + { + dt = DataTestUtility.RunQuery(connectionString, $"select mirroring_partner_name from sys.database_mirroring where database_id = DB_ID('{dbname}')"); + failoverPartnerName = dt.Rows[0][0].ToString(); + } + + return isMirroring; + } + + private class TestWorker + { + private string _connectionString; + + public TestWorker(string connectionString) + { + _connectionString = connectionString; + } + + public void TestMultipleConnection() + { + List list = new List(); + + for (int i = 0; i < 10; ++i) + { + SqlConnection conn = new SqlConnection(_connectionString); + list.Add(conn); + conn.Open(); + } + + foreach (SqlConnection conn in list) + { + conn.Dispose(); + } + + workerCompletedEvent.Set(); + } + } + } +} diff --git a/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj b/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj index 3805a80820b9..7a0e5419151a 100644 --- a/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj @@ -56,6 +56,7 @@ +