-
Notifications
You must be signed in to change notification settings - Fork 317
Fix Cancel #234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Cancel #234
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -598,41 +598,41 @@ internal void Cancel(object caller) | |
| // Keep looping until we either grabbed the lock (and therefore sent attention) or the connection closes\breaks | ||
| while ((!hasLock) && (_parser.State != TdsParserState.Closed) && (_parser.State != TdsParserState.Broken)) | ||
| { | ||
| // try to take the lock so that if another command is attempted it will queue on the lock | ||
| // but don't require that the lock be taken because otherwise attention cannot be sent | ||
| // during command execution causing cancellation to wait | ||
| // This lock is also protecting against concurrent close and async continuations | ||
| Monitor.TryEnter(this, _waitForCancellationLockPollTimeout, ref hasLock); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the point of taking a lock at all here? If we actually need to prevent new commands being started while sending attention, then we can't allow this lock to be optional, and if we don't, then why have it at all. |
||
| if (hasLock) | ||
| { // Lock for the time being - since we need to synchronize the attention send. | ||
| // This lock is also protecting against concurrent close and async continuations | ||
|
|
||
| // Ensure that, once we have the lock, that we are still the owner | ||
| if ((!_cancelled) && (_cancellationOwner.Target == caller)) | ||
| { | ||
| _cancelled = true; | ||
| // Ensure that that we are still the owner | ||
| if ((!_cancelled) && (_cancellationOwner.Target == caller)) | ||
| { | ||
| _cancelled = true; | ||
|
|
||
| if (_pendingData && !_attentionSent) | ||
| if (_pendingData && !_attentionSent) | ||
| { | ||
| bool hasParserLock = false; | ||
| // Keep looping until we have the parser lock (and so are allowed to write), or the connection closes\breaks | ||
| while ((!hasParserLock) && (_parser.State != TdsParserState.Closed) && (_parser.State != TdsParserState.Broken)) | ||
| { | ||
| bool hasParserLock = false; | ||
| // Keep looping until we have the parser lock (and so are allowed to write), or the connection closes\breaks | ||
| while ((!hasParserLock) && (_parser.State != TdsParserState.Closed) && (_parser.State != TdsParserState.Broken)) | ||
| try | ||
| { | ||
| try | ||
| _parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false, timeout: _waitForCancellationLockPollTimeout, lockTaken: ref hasParserLock); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feels like there should be an async version of this function. If the locks were async, wouldn't that also fix the cancellation hang? |
||
| if (hasParserLock) | ||
| { | ||
| _parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false, timeout: _waitForCancellationLockPollTimeout, lockTaken: ref hasParserLock); | ||
| if (hasParserLock) | ||
| { | ||
| _parser.Connection.ThreadHasParserLockForClose = true; | ||
| SendAttention(); | ||
| } | ||
| _parser.Connection.ThreadHasParserLockForClose = true; | ||
| SendAttention(); | ||
| } | ||
| finally | ||
| } | ||
| finally | ||
| { | ||
| if (hasParserLock) | ||
| { | ||
| if (hasParserLock) | ||
| if (_parser.Connection.ThreadHasParserLockForClose) | ||
| { | ||
| if (_parser.Connection.ThreadHasParserLockForClose) | ||
| { | ||
| _parser.Connection.ThreadHasParserLockForClose = false; | ||
| } | ||
| _parser.Connection._parserLock.Release(); | ||
| _parser.Connection.ThreadHasParserLockForClose = false; | ||
| } | ||
| _parser.Connection._parserLock.Release(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't get the lock, won't this loop / send attention multiple times? Is that intended?