Skip to content

Don’t cancel in-progress diagnostic generation when calling DiagnosticReportManager.removeItemsFromCache #1414

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

Merged

Conversation

ahoppen
Copy link
Member

@ahoppen ahoppen commented Jun 4, 2024

This was causing a non-deterministic test failure: When target preparation finishes while a diagnostic request is in progress, it will re-open the document, which calls DiagnosticReportManager.removeItemsFromCache for that document’s URI. With the old implementation, we would thus cancel the diagnostics sourcekitd request and return a cancelled error to the diagnostics LSP request.

While doing this, I also realized that there was a race condition: Document re-opening would happen outside of the SourceKit-LSP message handling queue and could thus run concurrently to any other request. This means that a sourcekitd request could run after reopenDocument had closed the document but before it was opened again. Introduce an internal reopen request that can be handled on the main message handling queue and thus doesn’t have this problem

…icReportManager.removeItemsFromCache`

This was causing a non-deterministic test failure: When target preparation finishes while a diagnostic request is in progress, it will re-open the document, which calls `DiagnosticReportManager.removeItemsFromCache` for that document’s URI. With the old implementation, we would thus cancel the diagnostics sourcekitd request and return a cancelled error to the diagnostics LSP request.

While doing this, I also realized that there was a race condition: Document re-opening would happen outside of the SourceKit-LSP message handling queue and could thus run concurrently to any other request. This means that a sourcekitd request could run after `reopenDocument` had closed the document but before it was opened again. Introduce an internal reopen request that can be handled on the main message handling queue and thus doesn’t have this problem
@ahoppen ahoppen requested review from bnbarham and hamishknight June 4, 2024 00:52
@ahoppen ahoppen requested a review from benlangmuir as a code owner June 4, 2024 00:52
@ahoppen
Copy link
Member Author

ahoppen commented Jun 4, 2024

@swift-ci Please test

Comment on lines -89 to -93
let tasksToCancel = reportTaskCache.filter { $0.snapshotID.uri == uri }
reportTaskCache.removeAll(where: { $0.snapshotID.uri == uri })
for task in tasksToCancel {
await task.reportTask.cancel()
}
Copy link
Contributor

@hamishknight hamishknight Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we could still do the cancellation on close/open (just not re-open), would that be beneficial?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There wouldn’t be any point. The close and open are classified as MessageHandlingDependencyTracker.documentUpdate, so they will only execute after the diagnostic requests have finished.

Also, I don’t like implicit cancellation and think that the client should explicitly cancel a request if they no longer need it.

@ahoppen ahoppen merged commit 560d3e9 into swiftlang:main Jun 4, 2024
3 checks passed
@ahoppen ahoppen deleted the no-cancel-if-removing-diag-from-cache branch June 4, 2024 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants