Badel2 / slime_seed_finder

https://badel2.github.io/slime_seed_finder
GNU General Public License v3.0
49 stars 4 forks source link

Gracefully handle out of memory errors in webassembly #34

Open Badel2 opened 2 years ago

Badel2 commented 2 years ago

There are some strange bugs when using large zipped worlds in the web demo. Instead of a user friendly "out of memory" error, we get "TextDecoder" errors:

Uncaught (in promise) TypeError: TextDecoder.decode: Decoding failed.
    getStringFromWasm0 https://badel2.github.io/slime_seed_finder/slime_seed_finder_web.js:19
    __wbindgen_string_new https://badel2.github.io/slime_seed_finder/slime_seed_finder_web.js:770
    find_spawners_in_world https://badel2.github.io/slime_seed_finder/slime_seed_finder_web.js:597
    findBlock https://badel2.github.io/slime_seed_finder/multi_spawner.js:41
    promise callback*findBlock https://badel2.github.io/slime_seed_finder/multi_spawner.js:19
    onclick https://badel2.github.io/slime_seed_finder/multi_spawner.html:1

Presumably this happens because the webassembly code runs into undefined behavior when trying to call console.log with uninitialized memory, but more investigation is needed.

Badel2 commented 2 years ago

So that issue was caused by https://github.com/rustwasm/wasm-bindgen/issues/2957 which caused errors when the memory usage of the WebAssembly code is greater than 2GB. I fixed that in my fork of wasm-bindgen which will be used from now on in this repository.

But even after fixing that, the error message when running out of memory at the 4GB limit is "unreachable executed".

That can be fixed by changing the compile command to use the oom=panic compiler flag, which unfortunately is only available in the nightly channel:

RUSTFLAGS='-Z oom=panic' cargo +nightly build --target wasm32-unknown-unknown --release -p slime_seed_finder_web

This is the output with that flag:

ERROR slime_seed_finder_web/src/lib.rs:13 PANIC: panicked at 'memory allocation of 1 bytes failed', library/std/src/alloc.rs:338:9

Another alternative that needs nightly rust but no extra flags is to use the set_alloc_error_hook function:

std::alloc::set_alloc_error_hook(|_layout| {
    panic!("Out of memory");
});

This results in this output:

ERROR slime_seed_finder_web/src/lib.rs:14 PANIC: panicked at 'Out of memory', slime_seed_finder_web/src/lib.rs:19:9

I guess it could be possible to implement set_alloc_error_hook in stable with a bit of unsafe, but for now I'll mark this issue as blocked.