-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Inject hop_to_executor
after self
is fully initialized in unrestricted actor inits
#38215
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
@swift-ci please smoke test |
@swift-ci please smoke test |
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.
Some quick structural comments.
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.
Some more things.
969a70a
to
2368cb6
Compare
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.
Some initial comments. Need to go through again for the algorithm.
580ff03
to
0678583
Compare
@swift-ci please smoke test |
caba62f
to
cfac663
Compare
There's a complication right now: a For now, trying something hacky to see what breaks: blindly inject at the beginning of every async init. |
@swift-ci please smoke test |
21f6ce0
to
2645e9d
Compare
5d3d04a
to
4ec1d69
Compare
4ec1d69
to
ba2b0ee
Compare
@swift-ci please test |
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 looks good to me (as a way to hide the problem for now). Is there value in adding the minimal reproducer as a runtime test?
Build failed |
ba2b0ee
to
4f64054
Compare
@swift-ci please smoke test |
aecd101
to
6b56d60
Compare
@swift-ci please smoke test and merge |
I ran into this while implementing async actor inits; where I was emitting an actor hop in the middle of an access region, which caused the access set to be unexpectedly empty.
Because `self` can be used unrestricted after it is fully-initialized in an async actor init, we perform a hop_to_executor(self) immediately after `self` is fully-initialized on all paths within the initializer. If we did not, then code could race with the initializer if it, e.g., spawns a task from the initializer and mutates actor state that the initializer then reads. By hopping to the executor, we prevent that task from running until _after_ the initializer completes.
6b56d60
to
ddf041f
Compare
@swift-ci please smoke test and merge |
Since
async
actor initializers (designated ones) are allowed to make unrestricted use ofself
after the point where it is fully-initialized, we need to hop to theself
executor after those points in order to prevent races in the init.The design of initializer declarations in Swift means that there are multiple such fully-initialized points. To find them, you need to use a flow-sensitive analysis of stores to properties, etc.
We already do this analysis in DefiniteInitialization for classes, etc. So, this PR takes advantage of the information DI already computes to find these points and insert the hop instructions, thus plugging the data-race.
Resolves rdar://78790683