Skip to content
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

Panic when despawning entity with child scene just after creation #2406

Closed
benoitryder opened this issue Jun 27, 2021 · 4 comments
Closed

Panic when despawning entity with child scene just after creation #2406

benoitryder opened this issue Jun 27, 2021 · 4 comments
Labels
A-Scenes Serialized ECS data stored on the disk P-Crash A sudden unexpected crash

Comments

@benoitryder
Copy link

Bevy version

main branch (71bf07f)

Operating system & version

OS: Windows 10
Rust toolchain: stable-x86_64-pc-windows-gnu 1.52.1

What you did

Despawning an entity with a GLTF scene child one update after its creation leads to a panic.
Here is minimal code reproducing the issue.

use bevy::{
    prelude::*,
};

#[derive(Default)]
struct State {
  entity: Option<Entity>,
  delay: usize,
}


fn update(
    mut commands: Commands,
    assets: Res<AssetServer>,
    mut state: Local<State>,
) {
    if let Some(id) = state.entity {
        if state.delay == 0 {
            commands.entity(id).despawn_recursive();
            state.entity = None;
        } else {
            state.delay -= 1;
        }
    } else {
        let id = commands
            .spawn()
            .with_children(|parent| {
                let handle: Handle<Scene> = assets.load("alien.glb#Scene0");  // no panic with "alien.glb"
                parent.spawn_scene(handle);
            }).id();
        state.entity = Some(id);
        state.delay = 0;  // no panic when set to 1
    }
}

fn main() {
    App::build()
        .add_plugins(DefaultPlugins)
        .add_system(update.system())
        .run();
}

What you expected to happen

Entity is despawned, no panic.
Sample program above will spawn/despawn entities indefinitely.

What actually happened

After the first despawn, program panics with an Entity does not exist error and the following backtrace (truncated):

thread 'main' panicked at 'Entity does not exist', C:\Users\user\bevy\crates\bevy_ecs\src\world\mod.rs:215:37
stack backtrace:
   0: rust_begin_unwind
             at /rustc/9bc8c42bb2f19e745a63f3445f1ac248fb015e53\/library\std\src/panicking.rs:493:5
   1: core::panicking::panic_fmt
             at /rustc/9bc8c42bb2f19e745a63f3445f1ac248fb015e53\/library\core\src/panicking.rs:92:14
   2: core::option::expect_failed
             at /rustc/9bc8c42bb2f19e745a63f3445f1ac248fb015e53\/library\core\src/option.rs:1321:5
   3: core::option::Option<T>::expect
             at /rustc/9bc8c42bb2f19e745a63f3445f1ac248fb015e53\library\core\src/option.rs:349:21
   4: bevy_ecs::world::World::entity_mut
             at C:\Users\user\bevy\crates\bevy_transform/C:\Users\user\bevy\crates\bevy_ecs\src\world/mod.rs:215:9
   5: <bevy_ecs::system::commands::Insert<T> as bevy_ecs::system::commands::Command>::write
             at C:\Users\user\bevy\crates\bevy_transform/C:\Users\user\bevy\crates\bevy_ecs\src\system/commands.rs:356:9
   6: bevy_ecs::system::commands::CommandQueue::apply
             at C:\Users\user\bevy\crates\bevy_ecs/C:\Users\user\bevy\crates\bevy_ecs\src\system/commands.rs:27:13
   7: <bevy_ecs::system::commands::CommandQueue as bevy_ecs::system::system_param::SystemParamState>::apply
             at C:\Users\user\bevy\crates\bevy_ecs/C:\Users\user\bevy\crates\bevy_ecs\src\system/system_param.rs:489:9
   8: <(P0,P1,P2,P3) as bevy_ecs::system::system_param::SystemParamState>::apply
             at C:\Users\user\bevy\crates\bevy_transform/C:\Users\user\bevy\crates\bevy_ecs\src\system/system_param.rs:1107:19
   9: <bevy_ecs::system::function_system::FunctionSystem<In,Out,Param,Marker,F> as bevy_ecs::system::system::System>::apply_buffers
             at C:\Users\user\bevy\crates\bevy_transform/C:\Users\user\bevy\crates\bevy_ecs\src\system/function_system.rs:338:9
  10: <bevy_ecs::schedule::stage::SystemStage as bevy_ecs::schedule::stage::Stage>::run
             at C:\Users\user\bevy\crates\bevy_ecs/C:\Users\user\bevy\crates\bevy_ecs\src\schedule/stage.rs:830:25
  11: bevy_ecs::schedule::Schedule::run_once
             at C:\Users\user\bevy\crates\bevy_ecs/C:\Users\user\bevy\crates\bevy_ecs\src\schedule/mod.rs:208:13
  12: <bevy_ecs::schedule::Schedule as bevy_ecs::schedule::stage::Stage>::run
             at C:\Users\user\bevy\crates\bevy_ecs/C:\Users\user\bevy\crates\bevy_ecs\src\schedule/mod.rs:226:21
  13: bevy_app::app::App::update
             at C:\Users\user\bevy\crates\bevy_app/C:\Users\user\bevy\crates\bevy_app\src/app.rs:62:9
<snipped>

Additional information

  • alien.glb is from bevy's assets, but I reproduced with other .glb files
  • It does not panic when using alien.glb asset path instead of alien.glb#Scene0.
  • It does not panic when delaying the despawn_recursive() to the next system call (initialize state.delay to 1 after spawn in sample code).
  • I'm not familiar with entity parenting, nor if it could be a known limitation of GLTF scenes. May I have misused something?
@benoitryder benoitryder added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Jun 27, 2021
@NathanSWard
Copy link
Contributor

In the error message at this line:

<bevy_ecs::system::commands::Insert as bevy_ecs::system::commands::Command>::write

It appears that it's the Insert command that's panicking.

@benoitryder
Copy link
Author

I added some traces, and there is an extra Insert command for the panic case.

Without delay, two Insert commands are added then written:

  • spawn parent 0v0
  • despawn parent 0v0
  • insert PreviousParent(0v0) to 1v0
  • insert Children([1v0]) to 0v0
  • write Insert<PreviousParent> for 1v0
  • write Insert<Children> for 0v0 (panic)

With delay, there is only one Insert command:

  • spawn parent 0v0
  • insert PreviousParent(0v0) to 1v0
  • write Insert<PreviousParent> for 1v0
  • despawn parent 0v0

Both commands are added by parent_update_system().
The Insert<Children> command is added to re-attach the child (1v0) to its despawned parent (0v0), after detecting a parent change.

@NathanSWard
Copy link
Contributor

NathanSWard commented Jun 28, 2021

The Insert command is added to re-attach the child (1v0) to its despawned parent (0v0), after detecting a parent change.

Ahh interesting haha.
So despawning is triggering the changing filter, which is not what we always want because you can't insert() on a despawned entity haha.

@mockersf
Copy link
Member

it goes like this:

  • stage Update
    • your system spawns entity 0, attach the scene to it
  • frame change
  • stage PreUpdate
    • scene spawner spawn the scene, adding Parent(0) to it's root (which is entity 1)
  • stage Update
    • despawn entity 0
  • stage PostUpdate
    • system parent_update_system kicks in, notice that entity 1 has a Parent(0) component and try to sinc everything. This crashes as you despawned the entity in the previous stage

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events P-Crash A sudden unexpected crash and removed S-Needs-Triage This issue needs to be labelled C-Bug An unexpected or incorrect behavior labels Jul 8, 2021
@alice-i-cecile alice-i-cecile added A-Scenes Serialized ECS data stored on the disk and removed A-ECS Entities, components, systems, and events labels Dec 12, 2021
bors bot pushed a commit that referenced this issue Dec 23, 2021
# Objective

Fix #2406 

Scene parenting was not done completely, leaving the hierarchy maintenance to the standard system. As scene spawning happens in stage `PreUpdate` and hierarchy maintenance in stage `PostUpdate`, this left the scene in an invalid state parent wise for part of a frame

## Solution

Also add/update the `Children` component when spawning the scene.

I kept the `Children` component as a `SmallVec`, it could be moved to an `HashSet` to guarantee uniqueness


Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
bors bot pushed a commit that referenced this issue Dec 23, 2021
# Objective

Fix #2406 

Scene parenting was not done completely, leaving the hierarchy maintenance to the standard system. As scene spawning happens in stage `PreUpdate` and hierarchy maintenance in stage `PostUpdate`, this left the scene in an invalid state parent wise for part of a frame

## Solution

Also add/update the `Children` component when spawning the scene.

I kept the `Children` component as a `SmallVec`, it could be moved to an `HashSet` to guarantee uniqueness


Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
bors bot pushed a commit that referenced this issue Dec 23, 2021
# Objective

Fix #2406 

Scene parenting was not done completely, leaving the hierarchy maintenance to the standard system. As scene spawning happens in stage `PreUpdate` and hierarchy maintenance in stage `PostUpdate`, this left the scene in an invalid state parent wise for part of a frame

## Solution

Also add/update the `Children` component when spawning the scene.

I kept the `Children` component as a `SmallVec`, it could be moved to an `HashSet` to guarantee uniqueness


Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
bors bot pushed a commit that referenced this issue Dec 23, 2021
# Objective

Fix #2406 

Scene parenting was not done completely, leaving the hierarchy maintenance to the standard system. As scene spawning happens in stage `PreUpdate` and hierarchy maintenance in stage `PostUpdate`, this left the scene in an invalid state parent wise for part of a frame

## Solution

Also add/update the `Children` component when spawning the scene.

I kept the `Children` component as a `SmallVec`, it could be moved to an `HashSet` to guarantee uniqueness


Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
bors bot pushed a commit that referenced this issue Dec 23, 2021
# Objective

Fix #2406 

Scene parenting was not done completely, leaving the hierarchy maintenance to the standard system. As scene spawning happens in stage `PreUpdate` and hierarchy maintenance in stage `PostUpdate`, this left the scene in an invalid state parent wise for part of a frame

## Solution

Also add/update the `Children` component when spawning the scene.

I kept the `Children` component as a `SmallVec`, it could be moved to an `HashSet` to guarantee uniqueness


Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
@bors bors bot closed this as completed in 5d5d783 Dec 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Scenes Serialized ECS data stored on the disk P-Crash A sudden unexpected crash
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants