-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Add a missing safety invariant to System::run_unsafe
#7778
Add a missing safety invariant to System::run_unsafe
#7778
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.
Great catch! Though does changing the safety invariants of an unsafe function count as a breaking change? This should probably be documented in the migration guide if possible.
While I wouldn't consider this a breaking change (the safety invariant already existed, it was just undocumented), it probably would be good to put this in the migration guide. |
There is an alternative solution to this issue that I think is cleaner. We could just add the requirement that |
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 suppose this is better than nothing. But why not write another function that validates the world is the correct one and give it its own name rather than using update_archetype_component
?
The name update_archetype_component
doesn't imply that it checks the world at all. And without the comment explaining why you are calling it, this would be a confusing line of code.
I did it in this way because exclusive systems don't actually need to validate the world, and |
Actually, that part isn't as much of an issue since exclusive systems don't even use However, adding a separate method to validate the world is problematic in that it introduces a new dynamic dispatch call every time a system gets run. Performing the world validation in |
Example |
That's been fixed, the bot is just slow. |
I've tried that approach a couple of times since leaving that comment, and I find that it ends up being messier than the approach used in this PR. |
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.
New safety invariants make sense to me. Unfortunate that we need to make some more of the functions unsafe, but this pr is just exposing an existing problem.
Just had the one question about a TODO and then this looks good to me.
@@ -444,7 +456,9 @@ impl MultiThreadedExecutor { | |||
#[cfg(feature = "trace")] | |||
let system_guard = system_span.enter(); | |||
let res = std::panic::catch_unwind(AssertUnwindSafe(|| { | |||
// SAFETY: access is compatible | |||
// SAFETY: | |||
// - Access: TODO. |
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 meant to stay as a TODO?
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.
Yes. The previous "access is compatible" comment is incorrect, since it's not supported by any invariants in this function. I'd rather be explicit that these invariants aren't fully fleshed out yet than pretend that they are. I have a real fix for this in #8292.
It looks like your PR is a breaking change, but you didn't provide a migration guide. Could you add some context on what users should update when this change get released in a new version of Bevy? |
Objective
The implementation of
System::run_unsafe
forFunctionSystem
requires that the world is the same one used to initialize the system. However, theSystem
trait has no requirements that the world actually matches, which makes this implementation unsound.This was previously mentioned in #7605 (comment)
Fixes part of #7833.
Solution
Add the safety invariant that
System::update_archetype_component_access
must be called prior toSystem::run_unsafe
. SinceFunctionSystem::update_archetype_component_access
properly validates the world, this ensures thatrun_unsafe
is not called with a mismatched world.Most exclusive systems are not required to be run on the same world that they are initialized with, so this is not a concern for them. Systems formed by combining an exclusive system with a regular system do require the world to match, however the validation is done inside of
System::run
when needed.