From 3d44ec314e3f1a758cdbac0d630139e42afcccc1 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Thu, 25 Mar 2021 00:48:44 +0000 Subject: [PATCH] fix inverted timeout reset --- .../src/Microsoft/Data/SqlClient/TdsParserStateObject.cs | 6 ++---- .../src/Microsoft/Data/SqlClient/TdsParserStateObject.cs | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index c2e41d4cb3..fb449e2dca 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -2434,7 +2434,6 @@ private bool OnTimeoutCore(int expectedState, int targetState) internal void ReadSni(TaskCompletionSource completion) { - Debug.Assert(_networkPacketTaskSource == null || ((_asyncReadWithoutSnapshot) && (_networkPacketTaskSource.Task.IsCompleted)), "Pending async call or failed to replay snapshot when calling ReadSni"); _networkPacketTaskSource = completion; @@ -2468,6 +2467,7 @@ internal void ReadSni(TaskCompletionSource completion) // the identity source. The identity value is used to correlate timer callback events to the currently // running timeout and prevents a late timer callback affecting a result it does not relate to int previousTimeoutState = Interlocked.CompareExchange(ref _timeoutState, TimeoutState.Running, TimeoutState.Stopped); + Debug.Assert(previousTimeoutState == TimeoutState.Stopped, "previous timeout state was not Stopped"); if (previousTimeoutState == TimeoutState.Stopped) { Debug.Assert(_timeoutIdentityValue == 0, "timer was previously stopped without resetting the _identityValue"); @@ -2488,8 +2488,6 @@ internal void ReadSni(TaskCompletionSource completion) // 0 == Already timed out (NOTE: To simulate the same behavior as sync we will only timeout on 0 if we receive an IO Pending from SNI) // >0 == Actual timeout remaining int msecsRemaining = GetTimeoutRemaining(); - - Debug.Assert(previousTimeoutState == TimeoutState.Stopped, "previous timeout state was not Stopped"); if (msecsRemaining > 0) { ChangeNetworkPacketTimeout(msecsRemaining, Timeout.Infinite); @@ -2902,7 +2900,7 @@ public void ReadAsyncCallback(IntPtr key, PacketHandle packet, uint error) // try to change to the stopped state but only do so if currently in the running state // and use cmpexch so that all changes out of the running state are atomic - int previousState = Interlocked.CompareExchange(ref _timeoutState, TimeoutState.Running, TimeoutState.Stopped); + int previousState = Interlocked.CompareExchange(ref _timeoutState, TimeoutState.Stopped, TimeoutState.Running); // if the state is anything other than running then this query has reached an end so // set the correlation _timeoutIdentityValue to 0 to prevent late callbacks executing diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index c91b3285e2..ebd75aaefa 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -2546,6 +2546,7 @@ internal void ReadSni(TaskCompletionSource completion) // the identity source. The identity value is used to correlate timer callback events to the currently // running timeout and prevents a late timer callback affecting a result it does not relate to int previousTimeoutState = Interlocked.CompareExchange(ref _timeoutState, TimeoutState.Running, TimeoutState.Stopped); + Debug.Assert(previousTimeoutState == TimeoutState.Stopped, "previous timeout state was not Stopped"); if (previousTimeoutState == TimeoutState.Stopped) { Debug.Assert(_timeoutIdentityValue == 0, "timer was previously stopped without resetting the _identityValue"); @@ -2565,8 +2566,6 @@ internal void ReadSni(TaskCompletionSource completion) // 0 == Already timed out (NOTE: To simulate the same behavior as sync we will only timeout on 0 if we receive an IO Pending from SNI) // >0 == Actual timeout remaining int msecsRemaining = GetTimeoutRemaining(); - - Debug.Assert(previousTimeoutState == TimeoutState.Stopped, "previous timeout state was not Stopped"); if (msecsRemaining > 0) { ChangeNetworkPacketTimeout(msecsRemaining, Timeout.Infinite); @@ -2983,7 +2982,7 @@ public void ReadAsyncCallback(IntPtr key, IntPtr packet, UInt32 error) // try to change to the stopped state but only do so if currently in the running state // and use cmpexch so that all changes out of the running state are atomic - int previousState = Interlocked.CompareExchange(ref _timeoutState, TimeoutState.Running, TimeoutState.Stopped); + int previousState = Interlocked.CompareExchange(ref _timeoutState, TimeoutState.Stopped, TimeoutState.Running); // if the state is anything other than running then this query has reached an end so // set the correlation _timeoutIdentityValue to 0 to prevent late callbacks executing