-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
bevy_ecs: flush entities after running observers and hooks in despawn #15398
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
bevy_ecs: flush entities after running observers and hooks in despawn #15398
Conversation
5b7eb1e
to
ab440e7
Compare
Let me know when this is ready for review :) |
b32026c
to
5d6968f
Compare
@alice-i-cecile Ready! |
Ooh, a miri failure. That's a new one for me! |
5d6968f
to
ab9bf68
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 clarity nits about the test, but I agree with the fix and the test design is good.
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 flushes need explaining but other than that lgtm.
ab9bf68
to
909f30c
Compare
909f30c
to
0669dd1
Compare
@@ -1323,6 +1323,10 @@ impl<'w> EntityWorldMut<'w> { | |||
world.removed_components.send(component_id, self.entity); | |||
} | |||
|
|||
// Observers and on_remove hooks may reserve new entities, which | |||
// requires a flush before Entities::free may be called. | |||
world.flush_entities(); |
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.
There's also a call to world.flush_entities();
at the top of this method. Do we need both, or did that one just need to get moved down here?
It looks like prior to #10756 the flush()
call was right before the free()
call, and the hooks and observers code got added in between. The calls to deferred_world.trigger_on_foo
in bundle.rs
don't have flush()
calls. That makes me think that we don't need to flush before triggering things, and we only need the single call here, right before the free()
.
It doesn't look like anything bad can happen if we flush twice, though, so it should be fine to leave both even if they're not both needed.
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.
Hmm, so if I remove the first world.flush_entities()
, the tests all pass and everything appears to work fine. As long as observers and hooks are unable to call any methods on Entities
that verify_flushed()
, it's safe to move. Since all of those require mutable access to Entities
and thus exclusive World
access as far as I'm aware, we should be OK to remove the first one.
Merging; thanks for the careful work and clear explanations :) |
Head branch was pushed to by a user without write access
08aa6a1
to
12c5e3e
Compare
Whoops, left an extra line in my test that broke CI. Should be good to go now @alice-i-cecile |
Objective
Fixes #14467
Observers and component lifecycle hooks are allowed to perform operations that subsequently require
Entities
to be flushed, such as reserving a new entity. If this occurs during anon_remove
hook or anOnRemove
event trigger during anEntityWorldMut::despawn
, a panic will occur.Solution
Call
world.flush_entities()
after runningon_remove
hooks/observers duringdespawn
Testing
Added a new test that fails before the fix and succeeds afterward.