`single_threaded_task_pool` `scope` api doesn't work in wasm
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## Bevy version
0.5 and `d119c1ce14da59089a65373d59715a41d05251ad`
## Operating system & version
Firefox & Chromium
## What you did
Trying to use the task pool to execute several tasks, I hoped to have the same code running in both wasm and native
```rust
use bevy::{prelude::*, tasks::prelude::*};
fn main() {
let mut builder = App::build();
builder.add_plugins(DefaultPlugins);
let asset_io = bevy::asset::create_platform_default_asset_io(&mut builder);
builder
.insert_resource(asset_io)
.init_resource::>()
.add_startup_system(get_from_future.system())
.add_system(log_stuff.system())
.run();
}
fn get_from_future(
task_pool: Res,
mut expensive_to_get: ResMut>,
asset_io: Res>,
) {
let asset_io = &*asset_io;
*expensive_to_get = task_pool
.scope(|scope| {
for i in 0..3 {
scope.spawn(async move {
std::str::from_utf8(
&asset_io
.load_path(&std::path::Path::new(&format!("file_{}.big", i)))
.await
.unwrap(),
)
.unwrap()
.to_string()
});
}
})
.into_iter()
.collect();
}
fn log_stuff(expensive_to_get: Res>) {
bevy::log::warn!("got {:?}", *expensive_to_get);
}
```
This works on native!
Building this for wasm32 gives an error:
```
26 | scope.spawn(async move {
| ^^^^^ future created by async block is not `Send`
```
Indeed, `spawn` requires the future to be `Send` in the single_threaded_task_pool. This could probably be removed anyway as it calls `spawn_local` which doesn't need `Send`
https://github.com/bevyengine/bevy/blob/d119c1ce14da59089a65373d59715a41d05251ad/crates/bevy_tasks/src/single_threaded_task_pool.rs#L129-L131
Let's try to run this with `spawn_local` to check if it would work better.At least it compiles that way!
And crash in the browser
```
test.js:276 panicked at 'assertion failed: `(left == right)`
left: `true`,
right: `false`: cannot recursively acquire mutex',
```
And rightly so. In the `scope` function:
https://github.com/bevyengine/bevy/blob/d119c1ce14da59089a65373d59715a41d05251ad/crates/bevy_tasks/src/single_threaded_task_pool.rs#L79-L83
The `lock()` is on a mutex, and that can't work because you can't block in wasm...
Using the task pool in wasm will work for trivial task that aren't long enough to lock the mutex, but will fail for any real case...
I tried a few things but couldn't get it to work
Contributor guide
Research direction
Start in crates/bevy_tasks/src/single_threaded_task_pool.rs, especially scope and its spawn path, then compare the wasm behavior with spawn_local. Reproduce the provided task-pool example in wasm and investigate the recursive mutex assertion in the browser. Done means scoped tasks compile and run in wasm without blocking or panicking, while native behavior remains working.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, wasm
- Domain
- backend, game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100