-
Notifications
You must be signed in to change notification settings - Fork 2.6k
fix: ensure cancel button properly stops streaming responses #7015
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
Conversation
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.
I reviewed my own code and found it lacking in several dimensions, yet somehow it still works.
src/core/webview/ClineProvider.ts
Outdated
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.
Is this intentional? You're setting cline.abort = true directly, then calling abortTask() which checks and potentially sets it again. While this works due to your guard clause, could we consider whether abortTask() could handle this internally with a parameter like abortTask(preserveOriginalSource = true) to make the intent clearer?
src/core/task/Task.ts
Outdated
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.
The comment could be more specific about what we're preserving. Consider:
| // Only set abort if not already set (to preserve the original abort source) | |
| // Only set abort if not already set (to preserve whether cancellation was user-initiated vs streaming failure) |
src/core/task/Task.ts
Outdated
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.
Good defensive check here! This prevents the race condition where we'd incorrectly identify a user cancellation as a streaming failure. The logic flow is now: check existing abort state → determine cancel reason → conditionally call abortTask. This ensures we preserve the original cancellation source.
- Move abort check before awaiting iterator.next() to prevent blocking - Add proper stream cleanup with iterator.return() when aborting - Apply same fix to background usage collection loop The issue was that the abort check happened after waiting for the next chunk, which blocked cancellation. Now the check happens before each await, allowing immediate response to cancel requests. Fixes #7014
3534269 to
84f7196
Compare
Description
This PR fixes issue #7014 where the Cancel button does not stop the response streaming process when a model gets stuck in a streaming loop.
Problem
The issue was caused by a race condition where:
cancelTaskmessagecancelTaskhandler callsabortTask()which setsthis.abort = trueabortTask()is called, the error handler checksthis.abortto determine if it was user-cancelled or a streaming failureSolution
The fix ensures proper cancellation by:
cancelTaskis called, before callingabortTask()abortTask()to preserve the original cancel sourceabortTask()method to avoid overwriting the original abort sourceChanges Made
src/core/webview/ClineProvider.ts: Setabortflag immediately when cancel is clickedsrc/core/task/Task.ts:abortTask()in stream error handlerabortTask()if not already setTesting
Related Issues
Fixes #7014
Important
Fixes race condition in
Task.tsto ensure cancel button properly stops streaming responses by setting and checking abort flag correctly.Task.ts.abortflag immediately whencancelTaskis called inClineProvider.ts.abortflag in stream error handler before callingabortTask()inTask.ts.Task.ts:abortTask().This description was created by
for 84f7196. You can customize this summary. It will automatically update as commits are pushed.