bevy_egui
bevy_egui copied to clipboard
`EguiContexts::ctx_mut` occasionally causes a panic when closing the app.
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
I am also seeing this. It looks like bevy_window
can/will despawn window entities during the default Update
schedule?
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()
}
Can we have EguiContexts::try_ctx_mut()
specifically to work around this issue?
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:
https://github.com/mvlabat/bevy_egui/blob/9dfe7076a96e09fc4d232dd5ddba60472f86ac90/examples/two_windows.rs#L69-L74
@mvlabat this did not make it in 0.28
, right? i ran into this now after upgrading to 0.28
.
@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.
If your system runs during the PostUpdate schedule
but it does not π€ its regular Update
schedule
@extrawurst is it consistent? Do you have a reproducible example?
nope not reliable reproducible, just like in the original posters case :(
its just the first time now that I got it after updating to bevy 0.14
and bevy_egui 0.28
.