-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Concurrency] Fix too optimistic TaskGroup bail-out-when-empty, #63016
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
This resolves a flaky test (and an actual bug) that @shahmishal and @beccadax reported today. |
@swift-ci please smoke test |
I'll have another look and add more tests about the retain/release correctness of the errors... I have a suspicion it might be wrong and over-retain the error a bit... 🤔 |
Had another bug hiding, we must offerError WHILE holding the group locks ofc, otherwise we get interleaving between the offer and completions of other tasks and may end up returning a success while we intended to throw the body error. Fix: 95628b1 |
642dc77
to
13de654
Compare
@swift-ci please smoke test |
47b76c1
to
b34b67c
Compare
@swift-ci please smoke test |
@swift-ci please smoke test linux |
332c1bd
to
c49bd0a
Compare
@swift-ci please smoke test |
1 similar comment
@swift-ci please smoke test |
7286220
to
c87ebdc
Compare
@@ -1641,8 +1652,9 @@ static void swift_taskGroup_waitAllImpl( | |||
ThrowingTaskFutureWaitContinuationFunction *resumeFunction, | |||
AsyncContext *rawContext) { | |||
auto waitingTask = swift_task_getCurrent(); | |||
waitingTask->ResumeTask = task_group_wait_resume_adapter; | |||
waitingTask->ResumeContext = rawContext; |
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.
this was incorrect, we cannot do this without holding the lock, as otherwise an offer
may pull the waiting task off the queue; but only one of the paths shall update and run the task.
@@ -1739,21 +1739,52 @@ PollResult TaskGroupBase::tryEnqueueWaitingTask(AsyncTask *waitingTask) { | |||
bool haveRunOneChildTaskInline = false; | |||
|
|||
reevaluate_if_TaskGroup_has_results:; | |||
auto assumed = statusMarkWaitingAssumeAcquire(); |
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 change here is that we don't mark and undo, but only mark when we indeed decide that we'll be waiting.
This is all still done with a lock, but the dance is more correct anyway.
|
||
@main struct Main { | ||
static func main() async { | ||
for i in 0...1_000 { |
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.
this is quick enough tbh, let's leave it like this
@swift-ci please smoke test |
All passed but I want to make double-sure here, run again. |
@swift-ci please smoke test |
may need to emit an error out of such waitAll attempt, if a previous error was already stored.
@swift-ci please smoke test |
@swift-ci please smoke test linux |
Heh, only remaining thing is a Only on our Ubuntu 20.04 CI this happens:
Unable to reproduce this issue on a linux host 👎 Haven been trying all day to find some reason for this. |
@swift-ci please smoke test |
Managed to reproduce the other occasional issue, with debug output:
but I can't understand how that's possible; we never hit any "store the result" codepath in the first offer, so how does the 12 end up in the result... |
preset=asan |
@swift-ci Please smoke test linux |
945cd59
to
8525a45
Compare
@swift-ci Please smoke test |
@swift-ci Please smoke test macOS |
Seems linux is passing with the latest rework of waitAll body -- avoiding a race on Yeah all those issues can be tracked back to an use-after-free I found and finally fixed now. |
@swift-ci Please smoke test linux |
8525a45
to
2c7038b
Compare
2c7038b
to
e75ef10
Compare
@swift-ci Please smoke test |
Unlocking one more test @swift-ci Please smoke test |
Also picked over the overflow protection we did way back then in #62271 I believe we're finally golden here, let's give it another test run and I'll pick forward. |
@swift-ci please test |
ARM_ARCH_7K compilation fun™, fixed now. |
ead2375
to
23699b0
Compare
@swift-ci please test |
@swift-ci please smoke test windows |
discarding group may need to emit an error out of such waitAll attempt, if a previous error was already stored.
The exact dance is:
Instead, it should:
This also is now able to easily handle the "first error always wins" but we choose to implement the "error thrown by body wins" after discussions within the team.
Resolves rdar://104198700
Resolves #63147
Resolves rdar://104507347
Resolves rdar://104332560
Resolves rdar://104212282