-
Notifications
You must be signed in to change notification settings - Fork 299
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix | Fix possible server connection leak if an exception occurs in p…
…ooling layer (#890)
- Loading branch information
1 parent
6a95ad4
commit c34e8a4
Showing
7 changed files
with
241 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
148 changes: 148 additions & 0 deletions
148
src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TransientFaultTDSServer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
// 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; | ||
using System.Net; | ||
using System.Runtime.CompilerServices; | ||
using System.Threading; | ||
using Microsoft.SqlServer.TDS.Done; | ||
using Microsoft.SqlServer.TDS.EndPoint; | ||
using Microsoft.SqlServer.TDS.Error; | ||
using Microsoft.SqlServer.TDS.Login7; | ||
|
||
namespace Microsoft.SqlServer.TDS.Servers | ||
{ | ||
/// <summary> | ||
/// TDS Server that authenticates clients according to the requested parameters | ||
/// </summary> | ||
public class TransientFaultTDSServer : GenericTDSServer, IDisposable | ||
{ | ||
private static int RequestCounter = 0; | ||
|
||
public int Port { get; set; } | ||
|
||
/// <summary> | ||
/// Constructor | ||
/// </summary> | ||
public TransientFaultTDSServer() => new TransientFaultTDSServer(new TransientFaultTDSServerArguments()); | ||
|
||
/// <summary> | ||
/// Constructor | ||
/// </summary> | ||
/// <param name="arguments"></param> | ||
public TransientFaultTDSServer(TransientFaultTDSServerArguments arguments) : | ||
base(arguments) | ||
{ } | ||
|
||
/// <summary> | ||
/// Constructor | ||
/// </summary> | ||
/// <param name="engine"></param> | ||
/// <param name="args"></param> | ||
public TransientFaultTDSServer(QueryEngine engine, TransientFaultTDSServerArguments args) : base(args) | ||
{ | ||
Engine = engine; | ||
} | ||
|
||
private TDSServerEndPoint _endpoint = null; | ||
|
||
private static string GetErrorMessage(uint errorNumber) | ||
{ | ||
switch (errorNumber) | ||
{ | ||
case 40613: | ||
return "Database on server is not currently available. Please retry the connection later. " + | ||
"If the problem persists, contact customer support, and provide them the session tracing ID."; | ||
} | ||
return "Unknown server error occurred"; | ||
} | ||
|
||
/// <summary> | ||
/// Handler for login request | ||
/// </summary> | ||
public override TDSMessageCollection OnLogin7Request(ITDSServerSession session, TDSMessage request) | ||
{ | ||
// Inflate login7 request from the message | ||
TDSLogin7Token loginRequest = request[0] as TDSLogin7Token; | ||
|
||
// Check if arguments are of the transient fault TDS server | ||
if (Arguments is TransientFaultTDSServerArguments) | ||
{ | ||
// Cast to transient fault TDS server arguments | ||
TransientFaultTDSServerArguments ServerArguments = Arguments as TransientFaultTDSServerArguments; | ||
|
||
// Check if we're still going to raise transient error | ||
if (ServerArguments.IsEnabledTransientError && RequestCounter < 1) // Fail first time, then connect | ||
{ | ||
uint errorNumber = ServerArguments.Number; | ||
string errorMessage = ServerArguments.Message; | ||
|
||
// Log request to which we're about to send a failure | ||
TDSUtilities.Log(Arguments.Log, "Request", loginRequest); | ||
|
||
// Prepare ERROR token with the denial details | ||
TDSErrorToken errorToken = new TDSErrorToken(errorNumber, 1, 20, errorMessage); | ||
|
||
// Log response | ||
TDSUtilities.Log(Arguments.Log, "Response", errorToken); | ||
|
||
// Serialize the error token into the response packet | ||
TDSMessage responseMessage = new TDSMessage(TDSMessageType.Response, errorToken); | ||
|
||
// Create DONE token | ||
TDSDoneToken doneToken = new TDSDoneToken(TDSDoneTokenStatusType.Final | TDSDoneTokenStatusType.Error); | ||
|
||
// Log response | ||
TDSUtilities.Log(Arguments.Log, "Response", doneToken); | ||
|
||
// Serialize DONE token into the response packet | ||
responseMessage.Add(doneToken); | ||
|
||
RequestCounter++; | ||
|
||
// Put a single message into the collection and return it | ||
return new TDSMessageCollection(responseMessage); | ||
} | ||
} | ||
|
||
// Return login response from the base class | ||
return base.OnLogin7Request(session, request); | ||
} | ||
|
||
public static TransientFaultTDSServer StartTestServer(bool isEnabledTransientFault, bool enableLog, uint errorNumber, [CallerMemberName] string methodName = "") | ||
=> StartServerWithQueryEngine(null, isEnabledTransientFault, enableLog, errorNumber, methodName); | ||
|
||
public static TransientFaultTDSServer StartServerWithQueryEngine(QueryEngine engine, bool isEnabledTransientFault, bool enableLog, uint errorNumber, [CallerMemberName] string methodName = "") | ||
{ | ||
TransientFaultTDSServerArguments args = new TransientFaultTDSServerArguments() | ||
{ | ||
Log = enableLog ? Console.Out : null, | ||
IsEnabledTransientError = isEnabledTransientFault, | ||
Number = errorNumber, | ||
Message = GetErrorMessage(errorNumber) | ||
}; | ||
|
||
TransientFaultTDSServer server = engine == null ? new TransientFaultTDSServer(args) : new TransientFaultTDSServer(engine, args); | ||
server._endpoint = new TDSServerEndPoint(server) { ServerEndPoint = new IPEndPoint(IPAddress.Any, 0) }; | ||
server._endpoint.EndpointName = methodName; | ||
|
||
// The server EventLog should be enabled as it logs the exceptions. | ||
server._endpoint.EventLog = Console.Out; | ||
server._endpoint.Start(); | ||
|
||
server.Port = server._endpoint.ServerEndPoint.Port; | ||
return server; | ||
} | ||
|
||
public void Dispose() => Dispose(true); | ||
|
||
private void Dispose(bool isDisposing) | ||
{ | ||
if (isDisposing) | ||
{ | ||
_endpoint?.Stop(); | ||
} | ||
} | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TransientFaultTDSServerArguments.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// 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. | ||
|
||
namespace Microsoft.SqlServer.TDS.Servers | ||
{ | ||
public class TransientFaultTDSServerArguments : TDSServerArguments | ||
{ | ||
/// <summary> | ||
/// Transient error number to be raised by server. | ||
/// </summary> | ||
public uint Number { get; set; } | ||
|
||
/// <summary> | ||
/// Transient error message to be raised by server. | ||
/// </summary> | ||
public string Message { get; set; } | ||
|
||
/// <summary> | ||
/// Flag to consider when raising Transient error. | ||
/// </summary> | ||
public bool IsEnabledTransientError { get; set; } | ||
|
||
/// <summary> | ||
/// Constructor to initialize | ||
/// </summary> | ||
public TransientFaultTDSServerArguments() | ||
{ | ||
Number = 0; | ||
Message = string.Empty; | ||
IsEnabledTransientError = false; | ||
} | ||
} | ||
} |