[WASM + Winit + Wgpu] Weird error about waiting on the main thread despite not waiting on the main thread

I am writing a minecraft clone using wgpu, winit, egui (with loads of multithreading) with both a native and web version: repo.

The native version runs fine, but the web version spontaneously crashes with the following error message. The program most often crashes (freezes) shortly after loading the webpage, but sometimes, the page loads fine and works only to crash some minutes later. I could not find a connection between interacting with the webpage and it crashing.
Interestingly, the program crashes a lot more often when built in release mode than when build in debug mode. (I tested it on librewolf and firefox)

  • Error without debug info enabled:
Uncaught TypeError: waiting is not allowed on this thread
    __wbg_adapter_48 http://127.0.0.1:5000/pkg/wgpucraft.js:244
    real http://127.0.0.1:5000/pkg/wgpucraft.js:225
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:997
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:294
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:996
    __wbg_adapter_48 http://127.0.0.1:5000/pkg/wgpucraft.js:244
    real http://127.0.0.1:5000/pkg/wgpucraft.js:225
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:997
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:294
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:996
    __wbg_adapter_48 http://127.0.0.1:5000/pkg/wgpucraft.js:244
    real http://127.0.0.1:5000/pkg/wgpucraft.js:225
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:997
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:294
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:996
    __wbg_adapter_48 http://127.0.0.1:5000/pkg/wgpucraft.js:244
    real http://127.0.0.1:5000/pkg/wgpucraft.js:225
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:997
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:294
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:996
    __wbg_adapter_48 http://127.0.0.1:5000/pkg/wgpucraft.js:244
    real http://127.0.0.1:5000/pkg/wgpucraft.js:225
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:997
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:294
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:996
    __wbg_adapter_48 http://127.0.0.1:5000/pkg/wgpucraft.js:244
    real http://127.0.0.1:5000/pkg/wgpucraft.js:225
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:997
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:294
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:996
    __wbg_adapter_48 http://127.0.0.1:5000/pkg/wgpucraft.js:244
    real http://127.0.0.1:5000/pkg/wgpucraft.js:225
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:997
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:294
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:996
  • Error with debug info enabled:
Uncaught TypeError: waiting is not allowed on this thread
wgpucraft_bg.wasm:3700399:1
    h5d1a01bc805a45df http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3700399
    h0bc485d70511a521 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2716375
    h71442e603eebd5cc http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2508509
    hd745d29012b2c27d http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3307628
    hc5beb07ff90edd07 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2794453
    h9903e478ef6302d1 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:1879831
    h550441a6b38d733a http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:776598
    he0ba7029fda31611 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:1360800
    h981b39053466c18a http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2048529
    h0a1171c42f0ead69 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2331062
    h2707ab6c1466db32 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3861998
    <dyn core::ops::function::FnMut<()>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::ha6e29c8103f05cdb http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3900261
    __wbg_adapter_42 http://127.0.0.1:5000/pkg/wgpucraft.js:280
    real http://127.0.0.1:5000/pkg/wgpucraft.js:257
    (Async: FrameRequestCallback)
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1056
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:337
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1055
    hb8fa28778059fbb3 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3838779
    h0d3beec7f0be1f86 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3190665
    h7fad61e02a7dfb61 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2208229
    h0a1171c42f0ead69 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2331146
    h2707ab6c1466db32 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3861998
    <dyn core::ops::function::FnMut<()>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::ha6e29c8103f05cdb http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3900261
    __wbg_adapter_42 http://127.0.0.1:5000/pkg/wgpucraft.js:280
    real http://127.0.0.1:5000/pkg/wgpucraft.js:257
    (Async: FrameRequestCallback)
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1056
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:337
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1055
    hb8fa28778059fbb3 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3838779
    h0d3beec7f0be1f86 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3190665
    h7fad61e02a7dfb61 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2208229
    h0a1171c42f0ead69 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2331146
    h2707ab6c1466db32 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3861998
    <dyn core::ops::function::FnMut<()>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::ha6e29c8103f05cdb http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3900261
    __wbg_adapter_42 http://127.0.0.1:5000/pkg/wgpucraft.js:280
    real http://127.0.0.1:5000/pkg/wgpucraft.js:257
    (Async: FrameRequestCallback)
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1056
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:337
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1055
    hb8fa28778059fbb3 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3838779
    h0d3beec7f0be1f86 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3190665
    h7fad61e02a7dfb61 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2208229
    h0a1171c42f0ead69 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2331146
    h2707ab6c1466db32 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3861998
    <dyn core::ops::function::FnMut<()>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::ha6e29c8103f05cdb http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3900261
    __wbg_adapter_42 http://127.0.0.1:5000/pkg/wgpucraft.js:280
    real http://127.0.0.1:5000/pkg/wgpucraft.js:257
    (Async: FrameRequestCallback)
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1056
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:337
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1055
    hb8fa28778059fbb3 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3838779
    h0d3beec7f0be1f86 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3190665
    h7fad61e02a7dfb61 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2208229
    h0a1171c42f0ead69 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2331146
    h2707ab6c1466db32 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3861998
    <dyn core::ops::function::FnMut<()>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::ha6e29c8103f05cdb http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3900261
    __wbg_adapter_42 http://127.0.0.1:5000/pkg/wgpucraft.js:280
    real http://127.0.0.1:5000/pkg/wgpucraft.js:257
    (Async: FrameRequestCallback)
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1056
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:337
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1055
    hb8fa28778059fbb3 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3838779
    h0d3beec7f0be1f86 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3190665
    h7fad61e02a7dfb61 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2208229
    h0a1171c42f0ead69 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2331146
    h2707ab6c1466db32 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3861998
    <dyn core::ops::function::FnMut<()>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::ha6e29c8103f05cdb http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3900261
    __wbg_adapter_42 http://127.0.0.1:5000/pkg/wgpucraft.js:280
    real http://127.0.0.1:5000/pkg/wgpucraft.js:257
    (Async: FrameRequestCallback)
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1056
    handleError http://127.0.0.1:5000/pkg/wgpucraft.js:337
    __wbg_requestAnimationFrame_d082200514b6674d http://127.0.0.1:5000/pkg/wgpucraft.js:1055
    hb8fa28778059fbb3 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3838779
    h0d3beec7f0be1f86 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3190665
    h7fad61e02a7dfb61 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2208229
    h0a1171c42f0ead69 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:2331146
    h2707ab6c1466db32 http://127.0.0.1:5000/pkg/wgpucraft_bg.wasm:3861998

I don't use Mutexes or RwLocks anywhere in the code, nor do I thread::sleep anywhere (I sleep in a spawned thread when only in the native version, but that shouldn't have anything to do with this)... I do use atmoics and channels, but those, as far as I know, shouldn't be causing this.

Sadly, I wasn't able to get any useful information out of these error messages, but "requestAnimationFrame" appears often, so maybe it has something to do with winit or something? I spent way too much time trying to find the cause of this and have no clue. If any of you has encountered something similar, please let me know.

Sorry for dumping the whole repo here, but I can't tell what part of the program might be causing it. All interaction with winit happes in lib.rs. If you want to try and run the program, install sfz and run this script.

Thanks for any possible insight

You cannot use pollster::block_on in WASM (it blocks the main thread). You can use wasm_bindgen_futures::spawn_local instead.

edit: This might be the wrong answer. You are using wasm_bindgen attributes to override the entrypoint. (It's mildly surprising that this even exists.)

2 Likes

This looks like at least one legitimate problem: You are using std::sync::mpsc in terrain.rs. You might want a non-blocking channel like futures_channel::mpsc.


Ok, I did some digging and I'm more convinced that this is the issue. The "waiting is not allowed on this thread" exception is caused by Atomics.wait() (emphasis added):

Note: This operation only works with a shared Int32Array or BigInt64Array and may not be allowed on the main thread. For a non-blocking, asynchronous version of this method, see Atomics.waitAsync().

The std::sync::mpsc::sync_channel's Receiver implementation on WASM32 uses a Mutex under the hood for notifying senders that a message has been received (even when using try_recv, which is called by try_iter in your case).

This mutex is itself implemented by calling core::arch::wasm32::memory_atomic_wait32 when under contention. This method corresponds to the JavaScript Atomics.wait(), namely (emphasis added):

This function, when called, will block the current thread if the memory pointed to by ptr is equal to expression (performing this action atomically).

2 Likes

Thanks a lot for your reply

  • I overwrite the wasm entrypoint, because apparently wasm_thread needs to overwrite it to work
  • I had no idea std::sync::mpsc blocked. I will try your suggestion tomorrow
  • Do I understand this correctly: ?
    • Rusts std::sync::atomic types are safe to use on the main thread on wasm
    • They do not block when reading / writing
    • (I assume) They don't use JavaScript Atomics.wait() under the hood, but do something different that doesn't block?

This might be a bug introduced by the crossbeam-channel change that happened in 1.67.0 [1]. The docs for try_recv claims that it "will never block". But it does sometimes:

That is my understanding, yes. The types in std::sync::atomics use compiler intrinsics, and there is no "atomic wait" intrinsic.


  1. There is an open issue on the upstream crossbeam repo: crossbeam::channel::Receiver::try_recv can block forever if sending thread is blocked · Issue #997 · crossbeam-rs/crossbeam (github.com) I added a link back here to that thread. ↩︎

2 Likes

As you suggested, I have replaced std::sync::mpsc channels with channels from futures_channel::mpsc and the issue seems to have been resolved.
Not only that, but terrain loading also feels (I have not done any rigorous testing) a lot faster than before. (I guess std::sync::mpsc was causing some unnecessary waiting)

Thanks!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.