Skip to content

Commit

Permalink
Merge pull request #1 from cheenamalhotra/659
Browse files Browse the repository at this point in the history
Add tests
  • Loading branch information
David Engel authored Feb 13, 2021
2 parents bf72dd1 + 7834cbc commit 7882171
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ internal enum SnapshottedStateFlags : byte

private readonly LastIOTimer _lastSuccessfulIOTimer;

// Below 2 properties are used to enforce timeout delays in code to
// reproduce issues related to theadpool starvation and timeout delay.
// It should always be set to false by default, and only be enabled during testing.
internal bool _enforceTimeoutDelay = false;
internal int _enforcedTimeoutDelayInMilliSeconds = 5000;

// secure password information to be stored
// At maximum number of secure string that need to be stored is two; one for login password and the other for new change password
private SecureString[] _securePasswords = new SecureString[2] { null, null };
Expand Down Expand Up @@ -1453,7 +1459,7 @@ internal bool TryReadInt16(out short value)
{
// The entire int16 is in the packet and in the buffer, so just return it
// and take care of the counters.
buffer = _inBuff.AsSpan(_inBytesUsed,2);
buffer = _inBuff.AsSpan(_inBytesUsed, 2);
_inBytesUsed += 2;
_inBytesPacket -= 2;
}
Expand Down Expand Up @@ -1487,7 +1493,7 @@ internal bool TryReadInt32(out int value)
}

AssertValidState();
value = (buffer[3] << 24) + (buffer[2] <<16) + (buffer[1] << 8) + buffer[0];
value = (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0];
return true;

}
Expand Down Expand Up @@ -2255,6 +2261,10 @@ internal void OnConnectionClosed()

private void OnTimeout(object state)
{
if (_enforceTimeoutDelay)
{
Thread.Sleep(_enforcedTimeoutDelayInMilliSeconds);
}
WeakReference timerOwner = (WeakReference)state;
if (_owner.Target == null ||
timerOwner.Target == null ||
Expand Down Expand Up @@ -3467,35 +3477,35 @@ internal void SendAttention(bool mustTakeWriteLock = false)
if (!_skipSendAttention)
{
#endif
// Take lock and send attention
bool releaseLock = false;
if ((mustTakeWriteLock) && (!_parser.Connection.ThreadHasParserLockForClose))
// Take lock and send attention
bool releaseLock = false;
if ((mustTakeWriteLock) && (!_parser.Connection.ThreadHasParserLockForClose))
{
releaseLock = true;
_parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false);
_parser.Connection.ThreadHasParserLockForClose = true;
}
try
{
// Check again (just in case the connection was closed while we were waiting)
if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken)
{
releaseLock = true;
_parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false);
_parser.Connection.ThreadHasParserLockForClose = true;
return;
}
try
{
// Check again (just in case the connection was closed while we were waiting)
if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken)
{
return;
}

uint sniError;
_parser._asyncWrite = false; // stop async write
SNIWritePacket(attnPacket, out sniError, canAccumulate: false, callerHasConnectionLock: false);
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.SendAttention|INFO> Send Attention ASync.");
}
finally
uint sniError;
_parser._asyncWrite = false; // stop async write
SNIWritePacket(attnPacket, out sniError, canAccumulate: false, callerHasConnectionLock: false);
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.SendAttention|INFO> Send Attention ASync.");
}
finally
{
if (releaseLock)
{
if (releaseLock)
{
_parser.Connection.ThreadHasParserLockForClose = false;
_parser.Connection._parserLock.Release();
}
_parser.Connection.ThreadHasParserLockForClose = false;
_parser.Connection._parserLock.Release();
}
}
#if DEBUG
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ internal int ObjectID
internal int _inBytesUsed = 0; // number of bytes used in internal read buffer
internal int _inBytesRead = 0; // number of bytes read into internal read buffer
internal int _inBytesPacket = 0; // number of bytes left in packet

internal int _spid; // SPID of the current connection

// Packet state variables
Expand Down Expand Up @@ -109,6 +109,12 @@ internal int ObjectID
internal bool _internalTimeout = false; // an internal timeout occurred
private readonly LastIOTimer _lastSuccessfulIOTimer;

// Below 2 properties are used to enforce timeout delays in code to
// reproduce issues related to theadpool starvation and timeout delay.
// It should always be set to false by default, and only be enabled during testing.
internal bool _enforceTimeoutDelay = false;
internal int _enforcedTimeoutDelayInMilliSeconds = 5000;

// secure password information to be stored
// At maximum number of secure string that need to be stored is two; one for login password and the other for new change password
private SecureString[] _securePasswords = new SecureString[2] { null, null };
Expand Down Expand Up @@ -296,7 +302,7 @@ internal TdsParserStateObject(TdsParser parser, SNIHandle physicalConnection, bo
SetPacketSize(_parser._physicalStateObj._outBuff.Length);

SNINativeMethodWrapper.ConsumerInfo myInfo = CreateConsumerInfo(async);

SQLDNSInfo cachedDNSInfo;
bool ret = SQLFallbackDNSCache.Instance.GetDNSInfo(_parser.FQDNforDNSCahce, out cachedDNSInfo);

Expand Down Expand Up @@ -797,7 +803,7 @@ private void ResetCancelAndProcessAttention()
{
tdsReliabilitySection.Start();
#endif //DEBUG
Parser.ProcessPendingAck(this);
Parser.ProcessPendingAck(this);
#if DEBUG
}
finally
Expand Down Expand Up @@ -2332,6 +2338,10 @@ internal void OnConnectionClosed()

private void OnTimeout(object state)
{
if (_enforceTimeoutDelay)
{
Thread.Sleep(_enforcedTimeoutDelayInMilliSeconds);
}
WeakReference timerOwner = (WeakReference)state;
if (_owner.Target == null ||
timerOwner.Target == null ||
Expand Down Expand Up @@ -3523,35 +3533,35 @@ internal void SendAttention(bool mustTakeWriteLock = false)
if (!_skipSendAttention)
{
#endif
// Take lock and send attention
bool releaseLock = false;
if ((mustTakeWriteLock) && (!_parser.Connection.ThreadHasParserLockForClose))
// Take lock and send attention
bool releaseLock = false;
if ((mustTakeWriteLock) && (!_parser.Connection.ThreadHasParserLockForClose))
{
releaseLock = true;
_parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false);
_parser.Connection.ThreadHasParserLockForClose = true;
}
try
{
// Check again (just in case the connection was closed while we were waiting)
if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken)
{
releaseLock = true;
_parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false);
_parser.Connection.ThreadHasParserLockForClose = true;
return;
}
try
{
// Check again (just in case the connection was closed while we were waiting)
if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken)
{
return;
}

UInt32 sniError;
_parser._asyncWrite = false; // stop async write
SNIWritePacket(Handle, attnPacket, out sniError, canAccumulate: false, callerHasConnectionLock: false);
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.SendAttention|{0}> Send Attention ASync.", "Info");
}
finally
UInt32 sniError;
_parser._asyncWrite = false; // stop async write
SNIWritePacket(Handle, attnPacket, out sniError, canAccumulate: false, callerHasConnectionLock: false);
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.SendAttention|{0}> Send Attention ASync.", "Info");
}
finally
{
if (releaseLock)
{
if (releaseLock)
{
_parser.Connection.ThreadHasParserLockForClose = false;
_parser.Connection._parserLock.Release();
}
_parser.Connection.ThreadHasParserLockForClose = false;
_parser.Connection._parserLock.Release();
}
}

#if DEBUG
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<Compile Include="SQL\DataClassificationTest\DataClassificationTest.cs" />
<Compile Include="TracingTests\EventSourceTest.cs" />
<Compile Include="SQL\AdapterTest\AdapterTest.cs" />
<Compile Include="SQL\AsyncTest\AsyncTimeoutTest.cs" />
<Compile Include="SQL\AsyncTest\BeginExecAsyncTest.cs" />
<Compile Include="SQL\AsyncTest\BeginExecReaderAsyncTest.cs" />
<Compile Include="SQL\AsyncTest\XmlReaderAsyncTest.cs" />
Expand Down
Loading

0 comments on commit 7882171

Please sign in to comment.