Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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