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

EguiContexts::ctx_mut occasionally causes a panic when closing the app. #212

Open
JoJoJet opened this issue Sep 28, 2023 · 12 comments
Open

Comments

@JoJoJet
Copy link

JoJoJet commented Sep 28, 2023

thread 'Compute Task Pool (2)' panicked at '`EguiContexts::ctx_mut` was called for an uninitialized context (primary window), make sure your system is run after [`EguiSet::InitContexts`] (or [`EguiStartupSet::InitContexts`] for startup systems)', /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_egui-0.21.0/src/lib.rs:337:14

This panic occurs intermittently when closing my app. Based on the panic message, I'm assuming that the EguiContext for the primary window is being deinitialized before the app fully closes, after which my system is allowed to run, which fails since it's trying to access an uninitialized context.

Backtrace:

stack backtrace:
   0: rust_begin_unwind
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panicking.rs:593:5
   1: core::panicking::panic_fmt
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panicking.rs:67:14
   2: core::panicking::panic_display
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panicking.rs:150:5
   3: core::panicking::panic_str
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panicking.rs:134:5
   4: core::option::expect_failed
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/option.rs:1952:5
   5: core::option::Option<T>::expect
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/option.rs:898:21
   6: bevy_egui::EguiContexts::ctx_mut
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_egui-0.21.0/src/lib.rs:333:47
   7: creator::home::show_loading_screen
             at ./src/home.rs:38:15
   8: core::ops::function::FnMut::call_mut
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/ops/function.rs:166:5
   9: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/ops/function.rs:294:13
  10: <Func as bevy_ecs::system::function_system::SystemParamFunction<fn(F0,F1,F2,F3) .> Out>>::run::call_inner
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.11.2/src/system/function_system.rs:622:21
  11: <Func as bevy_ecs::system::function_system::SystemParamFunction<fn(F0,F1,F2,F3) .> Out>>::run
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.11.2/src/system/function_system.rs:625:17
  12: <bevy_ecs::system::function_system::FunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run_unsafe
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.11.2/src/system/function_system.rs:460:19
  13: bevy_ecs::schedule::executor::multi_threaded::MultiThreadedExecutor::spawn_system_task::{{closure}}::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.11.2/src/schedule/executor/multi_threaded.rs:505:26
  14: core::ops::function::FnOnce::call_once
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/ops/function.rs:250:5
  15: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panic/unwind_safe.rs:271:9
  16: std::panicking::try::do_call
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panicking.rs:500:40
  17: __rust_try
  18: std::panicking::try
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panicking.rs:464:19
  19: std::panic::catch_unwind
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panic.rs:142:14
  20: bevy_ecs::schedule::executor::multi_threaded::MultiThreadedExecutor::spawn_system_task::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.11.2/src/schedule/executor/multi_threaded.rs:500:23
  21: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::future::future::Future>::poll
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panic/unwind_safe.rs:296:9
  22: <futures_lite::future::CatchUnwind<F> as core::future::future::Future>::poll::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-1.13.0/src/future.rs:626:42
  23: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panic/unwind_safe.rs:271:9
  24: std::panicking::try::do_call
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panicking.rs:500:40
  25: __rust_try
  26: std::panicking::try
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panicking.rs:464:19
  27: std::panic::catch_unwind
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panic.rs:142:14
  28: <futures_lite::future::CatchUnwind<F> as core::future::future::Future>::poll
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-1.13.0/src/future.rs:626:9
  29: async_executor::Executor::spawn::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.5.1/src/lib.rs:145:20
  30: async_task::raw::RawTask<F,T,S,M>::run
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-task-4.4.0/src/raw.rs:563:17
  31: async_task::runnable::Runnable<M>::run
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-task-4.4.0/src/runnable.rs:782:18
  32: async_executor::Executor::run::{{closure}}::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.5.1/src/lib.rs:236:21
  33: <futures_lite::future::Or<F1,F2> as core::future::future::Future>::poll
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-1.13.0/src/future.rs:529:33
  34: async_executor::Executor::run::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.5.1/src/lib.rs:243:32
  35: futures_lite::future::block_on::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-1.13.0/src/future.rs:89:27
  36: std::thread::local::LocalKey<T>::try_with
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/thread/local.rs:270:16
  37: std::thread::local::LocalKey<T>::with
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/thread/local.rs:246:9
  38: futures_lite::future::block_on
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-1.13.0/src/future.rs:79:5
  39: bevy_tasks::task_pool::TaskPool::new_internal::{{closure}}::{{closure}}::{{closure}}::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_tasks-0.11.2/src/task_pool.rs:171:37
  40: std::panicking::try::do_call
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panicking.rs:500:40
  41: __rust_try
  42: std::panicking::try
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panicking.rs:464:19
  43: std::panic::catch_unwind
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panic.rs:142:14
  44: bevy_tasks::task_pool::TaskPool::new_internal::{{closure}}::{{closure}}::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_tasks-0.11.2/src/task_pool.rs:165:43
  45: std::thread::local::LocalKey<T>::try_with
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/thread/local.rs:270:16
  46: std::thread::local::LocalKey<T>::with
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/thread/local.rs:246:9
  47: bevy_tasks::task_pool::TaskPool::new_internal::{{closure}}::{{closure}}
             at /home/joseph/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_tasks-0.11.2/src/task_pool.rs:158:25
@hammypants
Copy link

I am also seeing this. It looks like bevy_window can/will despawn window entities during the default Update schedule?

@AntiBlueQuirk
Copy link

My guess is that the Entity with the PrimaryWindow gets despawned when the window closes, taking the context with it. For me at least, the panic only happens for systems in the PostUpdate schedule. So you can probably fix this by moving your system to the Update schedule.

I think this is kind of a flaw in EguiContexts. Calling EguiContexts::ctx_mut implies that your system can only run if there is a context on the PrimaryWindow, but using EguiContexts as system parameter does not encode this condition to Bevy, since it uses Option<PrimaryWindow> internally. I think there should be a separate PrimaryEguiContext struct for running systems only when the primary contexts exists. Then, EguiContexts::try_ctx_mut() could be added that returns an Option, so that EguiContexts represents "contexts that may or may not exist, including the primary context".

An alternative temporary fix is to add a run condition to your system. This is a little silly, since you're running the same query twice, but it's a one line change until this gets resolved.

// In setup:
app.add_systems(PostUpdate, (
  some_system.run_if(egui_has_primary_context),
))

// Elsewhere:
pub fn egui_has_primary_context(
    query: Query<(With<bevy_egui::EguiContext>, With<bevy_window::PrimaryWindow>)>,
) -> bool {
    !query.is_empty()
}

@rlidwka
Copy link
Contributor

rlidwka commented Apr 3, 2024

Can we have EguiContexts::try_ctx_mut() specifically to work around this issue?

@mvlabat
Copy link
Owner

mvlabat commented Apr 4, 2024

Sounds good, I'll add it in the next release. Meanwhile, you can use the workaround suggested by @AntiBlueQuirk or use the following query, as in the two_windows example:

mut egui_ctx: Query<&mut EguiContext, With<PrimaryWindow>>,
) {
let bevy_texture_id = egui_user_textures.add_image(images.bevy_icon.clone_weak());
let Ok(mut ctx) = egui_ctx.get_single_mut() else {
return;
};

@extrawurst
Copy link

@mvlabat this did not make it in 0.28, right? i ran into this now after upgrading to 0.28.

@mvlabat
Copy link
Owner

mvlabat commented Jul 7, 2024

@extrawurst the try_ctx_mut method is available since 0.27. If your system runs during the PostUpdate schedule, you should use it instead of ctx_mut to avoid the panic.

@mvlabat mvlabat closed this as completed Jul 7, 2024
@extrawurst
Copy link

If your system runs during the PostUpdate schedule

but it does not 🤔 its regular Update schedule

@mvlabat mvlabat reopened this Jul 7, 2024
@mvlabat
Copy link
Owner

mvlabat commented Jul 7, 2024

@extrawurst is it consistent? Do you have a reproducible example?

@extrawurst
Copy link

nope not reliable reproducible, just like in the original posters case :(

@extrawurst
Copy link

its just the first time now that I got it after updating to bevy 0.14 and bevy_egui 0.28.

@nixpulvis
Copy link

I also have calls to ctx_mut panicking in an Update system. I replaced all the calls with if let Some(ctx) = ...try_ctx_mut() { ... } and now things aren't panicking, but IIUC once this issue is resolved, I won't need to?

@meanbeanmachine
Copy link

This might be a redneck workaround but I noticed that when I quit my app manually via a Quit button, I no longer received the panic messages. The panic messages only occur when I 'X' out the window. So I made this system to intercept the window close event, and close it the same way I do with the Quit button. Now the app never panics on window close.

fn window_exit_fix( close_requested: EventReader<WindowCloseRequested>, mut exit: EventWriter<AppExit>, ) { if !close_requested.is_empty() { exit.send(AppExit::Success); } }

I'm not smart enough to know why this works, but it does. On Ubtunu 22.04 at least. It doesn't fix whatever the issue is but I found it to be a better workaround vs using try_ctx_mut() in all of my egui systems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants