@@ -55,7 +55,7 @@ public TimeoutState(int value)
5555
5656 private const int AttentionTimeoutSeconds = 5 ;
5757
58- private static readonly ContextCallback s_readAdyncCallbackComplete = ReadAsyncCallbackComplete ;
58+ private static readonly ContextCallback s_readAsyncCallbackComplete = ReadAsyncCallbackComplete ;
5959
6060 // Ticks to consider a connection "good" after a successful I/O (10,000 ticks = 1 ms)
6161 // The resolution of the timer is typically in the range 10 to 16 milliseconds according to msdn.
@@ -2337,9 +2337,9 @@ private void OnTimeoutAsync(object state)
23372337 }
23382338 }
23392339
2340- private bool OnTimeoutSync ( )
2340+ private bool OnTimeoutSync ( bool asyncClose = false )
23412341 {
2342- return OnTimeoutCore ( TimeoutState . Running , TimeoutState . ExpiredSync ) ;
2342+ return OnTimeoutCore ( TimeoutState . Running , TimeoutState . ExpiredSync , asyncClose ) ;
23432343 }
23442344
23452345 /// <summary>
@@ -2348,8 +2348,9 @@ private bool OnTimeoutSync()
23482348 /// </summary>
23492349 /// <param name="expectedState">the state that is the expected current state, state will change only if this is correct</param>
23502350 /// <param name="targetState">the state that will be changed to if the expected state is correct</param>
2351+ /// <param name="asyncClose">any close action to be taken by an async task to avoid deadlock.</param>
23512352 /// <returns>boolean value indicating whether the call changed the timeout state</returns>
2352- private bool OnTimeoutCore ( int expectedState , int targetState )
2353+ private bool OnTimeoutCore ( int expectedState , int targetState , bool asyncClose = false )
23532354 {
23542355 Debug . Assert ( targetState == TimeoutState . ExpiredAsync || targetState == TimeoutState . ExpiredSync , "OnTimeoutCore must have an expiry state as the targetState" ) ;
23552356
@@ -2382,7 +2383,7 @@ private bool OnTimeoutCore(int expectedState, int targetState)
23822383 {
23832384 try
23842385 {
2385- SendAttention ( mustTakeWriteLock : true ) ;
2386+ SendAttention ( mustTakeWriteLock : true , asyncClose ) ;
23862387 }
23872388 catch ( Exception e )
23882389 {
@@ -2927,7 +2928,7 @@ public void ReadAsyncCallback(IntPtr key, PacketHandle packet, uint error)
29272928 // synchrnously and then call OnTimeoutSync to force an atomic change of state.
29282929 if ( TimeoutHasExpired )
29292930 {
2930- OnTimeoutSync ( ) ;
2931+ OnTimeoutSync ( true ) ;
29312932 }
29322933
29332934 // try to change to the stopped state but only do so if currently in the running state
@@ -2958,7 +2959,7 @@ public void ReadAsyncCallback(IntPtr key, PacketHandle packet, uint error)
29582959 {
29592960 if ( _executionContext != null )
29602961 {
2961- ExecutionContext . Run ( _executionContext , s_readAdyncCallbackComplete , source ) ;
2962+ ExecutionContext . Run ( _executionContext , s_readAsyncCallbackComplete , source ) ;
29622963 }
29632964 else
29642965 {
@@ -3441,7 +3442,7 @@ private void CancelWritePacket()
34413442
34423443#pragma warning disable 0420 // a reference to a volatile field will not be treated as volatile
34433444
3444- private Task SNIWritePacket( PacketHandle packet , out uint sniError , bool canAccumulate , bool callerHasConnectionLock )
3445+ private Task SNIWritePacket( PacketHandle packet , out uint sniError , bool canAccumulate , bool callerHasConnectionLock , bool asyncClose = false )
34453446 {
34463447 // Check for a stored exception
34473448 var delayedException = Interlocked. Exchange ( ref _delayedWriteAsyncCallbackException , null ) ;
@@ -3534,7 +3535,7 @@ private Task SNIWritePacket(PacketHandle packet, out uint sniError, bool canAccu
35343535 {
35353536 SqlClientEventSource . Log . TryTraceEvent ( "TdsParserStateObject.SNIWritePacket | Info | State Object Id {0}, Write async returned error code {1}" , _objectID , ( int ) error ) ;
35363537 AddError ( _parser . ProcessSNIError ( this ) ) ;
3537- ThrowExceptionAndWarning ( ) ;
3538+ ThrowExceptionAndWarning ( false , asyncClose ) ;
35383539 }
35393540 AssertValidState ( ) ;
35403541 completion . SetResult ( null ) ;
@@ -3569,7 +3570,7 @@ private Task SNIWritePacket(PacketHandle packet, out uint sniError, bool canAccu
35693570 {
35703571 SqlClientEventSource . Log . TryTraceEvent ( "TdsParserStateObject.SNIWritePacket | Info | State Object Id {0}, Write async returned error code {1}" , _objectID , ( int ) sniError ) ;
35713572 AddError( _parser . ProcessSNIError ( this ) ) ;
3572- ThrowExceptionAndWarning( callerHasConnectionLock ) ;
3573+ ThrowExceptionAndWarning( callerHasConnectionLock , asyncClose ) ;
35733574 }
35743575 AssertValidState( ) ;
35753576 }
@@ -3581,7 +3582,7 @@ private Task SNIWritePacket(PacketHandle packet, out uint sniError, bool canAccu
35813582 internal abstract uint WritePacket( PacketHandle packet , bool sync ) ;
35823583
35833584 // Sends an attention signal - executing thread will consume attn.
3584- internal void SendAttention( bool mustTakeWriteLock = false)
3585+ internal void SendAttention( bool mustTakeWriteLock = false, bool asyncClose = false )
35853586 {
35863587 if ( ! _attentionSent )
35873588 {
@@ -3623,7 +3624,7 @@ internal void SendAttention(bool mustTakeWriteLock = false)
36233624
36243625 uint sniError;
36253626 _parser. _asyncWrite = false ; // stop async write
3626- SNIWritePacket ( attnPacket , out sniError , canAccumulate : false , callerHasConnectionLock : false ) ;
3627+ SNIWritePacket ( attnPacket , out sniError , canAccumulate : false , callerHasConnectionLock : false , asyncClose ) ;
36273628 SqlClientEventSource. Log . TryTraceEvent ( "TdsParserStateObject.SendAttention | Info | State Object Id {0}, Sent Attention." , _objectID ) ;
36283629 }
36293630 finally
0 commit comments