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

"Cannot execute LocalPool executor from within another executor" panic! on master #826

Closed
mitchmindtree opened this issue Dec 21, 2021 · 12 comments · Fixed by #833
Closed

Comments

@mitchmindtree
Copy link
Member

A user on matrix mentioned they're running into the following panic! on Windows 10:

thread 'main' panicked at 'cannot execute LocalPool executor from within another executor: EnterError'.

Another user confirmed, and mentioned that the recently released 0.18.1 works, so the issue must be in one of the recent unreleased changes. Seeing as we're getting an executor error, I imagine this must be related to either the new async run code or the wgpu async code, or maybe the interaction between the two (which I think we always immediately block on anyway). cc @Woyten any ideas on what might be going on? I'll see if I can get some more detailed backtraces, etc.

@sidwellr
Copy link
Contributor

sidwellr commented Dec 21, 2021

I made sure my local Nannou copy was up-to-date with nannou-org and ran cargo update. I'm running Windows 10 20H2, build 19042.1415. Here's a trace with RUST_BACKTRACE=full:

     Running `target\debug\examples\template_app.exe`
thread 'main' panicked at 'cannot execute `LocalPool` executor from within another executor: EnterError', C:\Users\Rick\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-executor-0.3.19\src\local_pool.rs:81:26
stack backtrace:
   0:     0x7ff73e99b24e - std::backtrace_rs::backtrace::dbghelp::trace
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\..\..\backtrace\src\backtrace\dbghelp.rs:98
   1:     0x7ff73e99b24e - std::backtrace_rs::backtrace::trace_unsynchronized
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\..\..\backtrace\src\backtrace\mod.rs:66
   2:     0x7ff73e99b24e - std::sys_common::backtrace::_print_fmt
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\sys_common\backtrace.rs:67
   3:     0x7ff73e99b24e - std::sys_common::backtrace::_print::impl$0::fmt
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\sys_common\backtrace.rs:46
   4:     0x7ff73e9b2d0a - core::fmt::write
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\core\src\fmt\mod.rs:1150
   5:     0x7ff73e998148 - std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\io\mod.rs:1667
   6:     0x7ff73e99de06 - std::sys_common::backtrace::_print
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\sys_common\backtrace.rs:49
   7:     0x7ff73e99de06 - std::sys_common::backtrace::print
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\sys_common\backtrace.rs:36
   8:     0x7ff73e99de06 - std::panicking::default_hook::closure$1
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:210
   9:     0x7ff73e99d8f4 - std::panicking::default_hook
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:227
  10:     0x7ff73e99e465 - std::panicking::rust_panic_with_hook
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:624
  11:     0x7ff73e99e04b - std::panicking::begin_panic_handler::closure$0
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:521
  12:     0x7ff73e99bb97 - std::sys_common::backtrace::__rust_end_short_backtrace<std::panicking::begin_panic_handler::closure$0,never$>
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\sys_common\backtrace.rs:141
  13:     0x7ff73e99dfa9 - std::panicking::begin_panic_handler
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:517
  14:     0x7ff73e9ba930 - core::panicking::panic_fmt
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\core\src\panicking.rs:101
  15:     0x7ff73e9baa43 - core::result::unwrap_failed
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\core\src\result.rs:1617
  16:     0x7ff73e001d43 - core::result::Result::expect<futures_executor::enter::Enter,futures_executor::enter::EnterError>
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\core\src\result.rs:1259
  17:     0x7ff73df57827 - futures_executor::local_pool::run_executor<enum$<core::result::Result<winit::window::WindowId,enum$<nannou::window::BuildError, 0, 3, WinitOsError> > >,futures_executor::local_pool::block_on::closure$0>
                               at C:\Users\Rick\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-executor-0.3.19\src\local_pool.rs:81
  18:     0x7ff73df57a74 - futures_executor::local_pool::block_on<core::future::from_generator::GenFuture<nannou::window::impl$1::build_async::generator$0> >
                               at C:\Users\Rick\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-executor-0.3.19\src\local_pool.rs:315
  19:     0x7ff73deee8d5 - nannou::window::Builder::build
                               at C:\users\rick\documents\rust\nannou\nannou\src\window.rs:731
  20:     0x7ff73deb4ef7 - template_app::model
                               at C:\users\rick\documents\rust\nannou\examples\templates\template_app.rs:12
  21:     0x7ff73dea783d - nannou::app::impl$0::new::closure$0<template_app::Model>
                               at C:\users\rick\documents\rust\nannou\nannou\src\app.rs:255
  22:     0x7ff73deb249b - core::ops::function::FnOnce::call_once<nannou::app::impl$0::new::closure$0,tuple$<ref$<nannou::app::App> > >
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\core\src\ops\function.rs:227
  23:     0x7ff73dea5413 - alloc::boxed::impl$44::call_once<tuple$<ref$<nannou::app::App> >,dyn$<core::ops::function::FnOnce<tuple$<ref$<nannou::app::App> >,assoc$<Output,alloc::boxed::Box<dyn$<core::future::future::Future,assoc$<Output,template_app::Model> > >,alloc::alloc::Global
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\alloc\src\boxed.rs:1636
  24:     0x7ff73dea8251 - nannou::app::impl$1::run_async::generator$0<template_app::Model,enum$<nannou::event::Event> >
                               at C:\users\rick\documents\rust\nannou\nannou\src\app.rs:498
  25:     0x7ff73deb30f9 - core::future::from_generator::impl$1::poll<nannou::app::impl$1::run_async::generator$0>
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\core\src\future\mod.rs:80
  26:     0x7ff73dea64b0 - futures_executor::local_pool::block_on::closure$0<core::future::from_generator::GenFuture<nannou::app::impl$1::run_async::generator$0> >
                               at C:\Users\Rick\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-executor-0.3.19\src\local_pool.rs:315
  27:     0x7ff73dea630f - futures_executor::local_pool::run_executor::closure$0<tuple$<>,futures_executor::local_pool::block_on::closure$0>
                               at C:\Users\Rick\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-executor-0.3.19\src\local_pool.rs:90
  28:     0x7ff73deb14c3 - std::thread::local::LocalKey<alloc::sync::Arc<futures_executor::local_pool::ThreadNotify> >::try_with<alloc::sync::Arc<futures_executor::local_pool::ThreadNotify>,futures_executor::local_pool::run_executor::closure$0,tuple$<> >
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\std\src\thread\local.rs:399
  29:     0x7ff73deb1403 - std::thread::local::LocalKey<alloc::sync::Arc<futures_executor::local_pool::ThreadNotify> >::with<alloc::sync::Arc<futures_executor::local_pool::ThreadNotify>,futures_executor::local_pool::run_executor::closure$0,tuple$<> >
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\std\src\thread\local.rs:375
  30:     0x7ff73dea6249 - futures_executor::local_pool::run_executor<tuple$<>,futures_executor::local_pool::block_on::closure$0>
                               at C:\Users\Rick\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-executor-0.3.19\src\local_pool.rs:86
  31:     0x7ff73dea641b - futures_executor::local_pool::block_on<core::future::from_generator::GenFuture<nannou::app::impl$1::run_async::generator$0> >
                               at C:\Users\Rick\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-executor-0.3.19\src\local_pool.rs:315
  32:     0x7ff73dea7a49 - nannou::app::Builder<template_app::Model,enum$<nannou::event::Event> >::run<template_app::Model,enum$<nannou::event::Event> >
                               at C:\users\rick\documents\rust\nannou\nannou\src\app.rs:454
  33:     0x7ff73deb4e9e - template_app::main
                               at C:\users\rick\documents\rust\nannou\examples\templates\template_app.rs:4
  34:     0x7ff73deb24cb - core::ops::function::FnOnce::call_once<void (*)(),tuple$<> >
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\core\src\ops\function.rs:227
  35:     0x7ff73deb74fb - std::sys_common::backtrace::__rust_begin_short_backtrace<void (*)(),tuple$<> >
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\std\src\sys_common\backtrace.rs:125
  36:     0x7ff73deb3251 - std::rt::lang_start::closure$0<tuple$<> >
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\std\src\rt.rs:63
  37:     0x7ff73e99e9f6 - core::ops::function::impls::impl$2::call_once
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\core\src\ops\function.rs:259
  38:     0x7ff73e99e9f6 - std::panicking::try::do_call
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:403
  39:     0x7ff73e99e9f6 - std::panicking::try
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:367
  40:     0x7ff73e99e9f6 - std::panic::catch_unwind
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panic.rs:129
  41:     0x7ff73e99e9f6 - std::rt::lang_start_internal::closure$2
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\rt.rs:45
  42:     0x7ff73e99e9f6 - std::panicking::try::do_call
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:403
  43:     0x7ff73e99e9f6 - std::panicking::try
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:367
  44:     0x7ff73e99e9f6 - std::panic::catch_unwind
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panic.rs:129
  45:     0x7ff73e99e9f6 - std::rt::lang_start_internal
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\rt.rs:45
  46:     0x7ff73deb321f - std::rt::lang_start<tuple$<> >
                               at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\std\src\rt.rs:62
  47:     0x7ff73deb5106 - main
  48:     0x7ff73e9b8fc4 - invoke_main
                               at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:78
  49:     0x7ff73e9b8fc4 - __scrt_common_main_seh
                               at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:288
  50:     0x7ff873677034 - BaseThreadInitThunk
  51:     0x7ff874182651 - RtlUserThreadStart
error: process didn't exit successfully: `target\debug\examples\template_app.exe` (exit code: 101)

@wehnsdaefflae
Copy link

i got the same issue under windows 11 with half of the examples.

@SuperSimon81
Copy link

Same for me on macosx big sur

@m0rphtail
Copy link

same on archlinux

@maurimura
Copy link

maurimura commented Dec 29, 2021

Hey, I had the same problem with the examples. As a workaround, I added async_std library to nannou dependencies, then changed the implementation of this function:

nannou/nannou/src/window.rs

Lines 730 to 732 in c7c9932

pub fn build(self) -> Result<Id, BuildError> {
futures::executor::block_on(self.build_async())
}
for this:

    /// Builds the window, inserts it into the `App`'s display map and returns the unique ID.
    pub fn build(self) -> Result<Id, BuildError> {
        async_std::task::block_on(self.build_async())
    }

All wgpu examples are running now.

I'm happy to send a pull request, but since the change adds a new library, maybe you want to think about that.

I'm on Windows 11.

@mitchmindtree
Copy link
Member Author

Thanks all for reporting!

It seems as though the issue is caused by attempted nesting of calls to futures::executor::block_on, likely due to the thread-local global state associated with the default executor.

https://docs.rs/futures-executor/0.3.19/src/futures_executor/local_pool.rs.html#82

The reason the nannou::sketch examples don't panic (e.g. draw.rs, template_sketch.rs) is that the default window creation awaits within the block_on context in App::run. On the other hand, in most nannou::app examples the user generally creates the window manually within their model function which is a regular, non-async function, which means that window creation must attempt to spawn another executor and block, resulting in our issue with nested calls to futures::executor::block_on.

@maurimura thanks for diving into finding a solution! I think the reason using the async_std executor within Window::build works is because async_std spawns its own separate executor altogether. While this might work for this case, I think the more sustainable approach might be to offer an async alternative to model to let the existing single executor manage all tasks.

I think that if building windows in an async context is a necessity for providing a good wasm+wgpu experience by default, then we should consider making the breaking change to require that the model function is async in general. I'll open an issue for this.

In the meantime, folks running the examples can use the publish-nannou-0.18.1 branch, or if using nannou downstream use version 0.18.1 directly rather than the master github branch.

@Woyten curious to grab your thoughts on all this, but I know it's holiday season - no rush at all :)

@mitchmindtree
Copy link
Member Author

then we should consider making the breaking change to require that the model function is async in general

Thinking on this a little more, while it's common to create all necessary windows during model, we also want to support the case where windows can be created at runtime. I've opened #831 with some thoughts on supporting async more generally.

In the meantime, it might be worth reverting #815 until we can come up with a more complete approach to supporting async.

@maurimura
Copy link

@mitchmindtree thanks for your feedback! I found the hints for making it work here: rust-lang/futures-rs#2090, which is exactly what you described in your comment.

I'm glad you're up to find a proper solution for this, async tradeoff could be hard for API design. I just discovered nannou and it looks great, I'll be playing a bit more with it, maybe I'll find some opinions on the use of async code.

@Woyten
Copy link
Contributor

Woyten commented Dec 31, 2021

@maurimura What happens if you remove the futures dependency completely and use async_std::task::spawn for the thread pools? My hope is that async_std::task::spawn will do the trick and is even more WASM friendly.

@maurimura
Copy link

Hey @Woyten. Yes, I think that will do the trick, but it involves adding a new dependency to nannou. I'm fine with that, but I'm not a maintainer on this repo to make that call.

Looking at some comments on the previous linked issue, rust-lang/futures-rs#2090 (comment) suggest it will work as well.

@Woyten
Copy link
Contributor

Woyten commented Dec 31, 2021

@maurimura Thanks for checking! I was talking about removing the dependency futures entirely. I am no maintainer either but if I was I would ne happy about a PR replacing futures with async_std.

@Woyten
Copy link
Contributor

Woyten commented Jan 2, 2022

@maurimura @mitchmindtree I prepared something which I would require some feedback about. Will prepare the draft PR soon.

mitchmindtree added a commit that referenced this issue Jan 25, 2022
Fix #826 / Use async-std instead of futures
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants