Skip to content

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

Merged

Conversation

jrobsonchase
Copy link
Contributor

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 an on_remove hook or an OnRemove event trigger during an EntityWorldMut::despawn, a panic will occur.

Solution

Call world.flush_entities() after running on_remove hooks/observers during despawn

Testing

Added a new test that fails before the fix and succeeds afterward.

@jrobsonchase jrobsonchase force-pushed the no_observer_despawn_panic branch 2 times, most recently from 5b7eb1e to ab440e7 Compare September 23, 2024 20:31
@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-ECS Entities, components, systems, and events S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Sep 23, 2024
@alice-i-cecile
Copy link
Member

Let me know when this is ready for review :)

@jrobsonchase jrobsonchase force-pushed the no_observer_despawn_panic branch 2 times, most recently from b32026c to 5d6968f Compare September 23, 2024 20:44
@jrobsonchase jrobsonchase marked this pull request as ready for review September 23, 2024 20:44
@jrobsonchase
Copy link
Contributor Author

@alice-i-cecile Ready!

@jrobsonchase
Copy link
Contributor Author

jrobsonchase commented Sep 23, 2024

Ooh, a miri failure. That's a new one for me!

Copy link
Member

@alice-i-cecile alice-i-cecile left a 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.

@alice-i-cecile alice-i-cecile added this to the 0.15 milestone Sep 23, 2024
@alice-i-cecile alice-i-cecile added S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Sep 23, 2024
Copy link
Contributor

@iiYese iiYese left a 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.

@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Sep 23, 2024
@jrobsonchase jrobsonchase force-pushed the no_observer_despawn_panic branch from ab9bf68 to 909f30c Compare September 23, 2024 22:54
@jrobsonchase jrobsonchase requested a review from iiYese September 23, 2024 22:56
@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Sep 23, 2024
@@ -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();
Copy link
Contributor

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.

Copy link
Contributor Author

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.

@alice-i-cecile
Copy link
Member

Merging; thanks for the careful work and clear explanations :)

auto-merge was automatically disabled September 24, 2024 00:52

Head branch was pushed to by a user without write access

@jrobsonchase jrobsonchase force-pushed the no_observer_despawn_panic branch from 08aa6a1 to 12c5e3e Compare September 24, 2024 00:52
@jrobsonchase
Copy link
Contributor Author

Whoops, left an extra line in my test that broke CI. Should be good to go now @alice-i-cecile

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Sep 24, 2024
Merged via the queue into bevyengine:main with commit 3d0f240 Sep 24, 2024
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Bug An unexpected or incorrect behavior S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Panic when a despawning Entity's observer spawns an Entity
4 participants