Skip to content

[6.2][Concurrency] Fix races/overflows in TaskGroup implementation. #81815

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
merged 1 commit into from
May 29, 2025

Conversation

mikeash
Copy link
Contributor

@mikeash mikeash commented May 28, 2025

Cherry-pick #81814 to release/6.2.

Explanation: This fixes several bugs in the implementation of task groups involving race conditions and overflows. We add loops around compare-and-swap operations and use the correct return type for discarding task groups.
Scope: Affects Swift Concurrency code that creates and cancels task groups.
Issue: rdar://151663730
Risk: Medium, this this makes quite a few changes to delicate concurrent code in the task group implementation. I'm confident the risk is worth the reward but there is more room for error here than usual.
Testing: Added tests that make the un-fixed code crash and verify that the new code does not crash. Other existing tests cover TaskGroup functionality to ensure we didn't regress anything.
Reviewer: @ktoso

statusCompletePendingReadyWaiting(), offer(), and poll() did a one-off compare_exchange_strong which could fail if the group was concurrently cancelled. Put these into loops so that they are retried when needed.

DiscardingTaskGroup creation passed the group result type as the task result type. waitAll() would then use the group result type when collecting task results. Since the task result type is always Void in this case, this would overflow the result buffer if the group result type was larger. This often works as it writes into the free space of the task allocator, but can crash if it happens to be at the end of a page or the group result type is particularly large.

rdar://151663730

@mikeash mikeash requested a review from a team as a code owner May 28, 2025 19:35
@mikeash
Copy link
Contributor Author

mikeash commented May 28, 2025

@swift-ci please test

statusCompletePendingReadyWaiting(), offer(), and poll() did a one-off compare_exchange_strong which could fail if the group was concurrently cancelled. Put these into loops so that they are retried when needed.

DiscardingTaskGroup creation passed the group result type as the task result type. waitAll() would then use the group result type when collecting task results. Since the task result type is always Void in this case, this would overflow the result buffer if the group result type was larger. This often works as it writes into the free space of the task allocator, but can crash if it happens to be at the end of a page or the group result type is particularly large.

rdar://151663730
(cherry picked from commit 5be22fa)
@mikeash mikeash force-pushed the taskgroup-fixes-6.2 branch from 440363d to b42c7fa Compare May 29, 2025 00:59
@mikeash
Copy link
Contributor Author

mikeash commented May 29, 2025

@swift-ci please test

@mikeash mikeash enabled auto-merge May 29, 2025 01:44
@mikeash mikeash merged commit 90b232c into swiftlang:release/6.2 May 29, 2025
5 checks passed
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