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

Remove the requirement for nightly on wasmer-wasix when the js feature is activated #4132

Open
Michael-F-Bryan opened this issue Aug 7, 2023 · 0 comments
Labels
📦 lib-wasi About wasmer-wasi lib-wasix Issues related to the WASIX toolchain. priority-low Low priority issue
Milestone

Comments

@Michael-F-Bryan
Copy link
Contributor

Michael-F-Bryan commented Aug 7, 2023

Describe the bug

As of #4119, compiling wasmer-wasix with the js feature requires a nightly compiler in order to do multi-processing correctly. This is a tracking issue for removing that requirement.

Why is nightly required?

TL;DR: We need to enable target_features = "atomics" so compiling to wasm32-unknown-unknown gives us an implementation of std::sync::Condvar (and therefore locks and channels) that works (src).

The wasmer-wasix crate implements multi-threading in the browser by spinning up some web workers and running Rust code (compiled to WebAssembly) on them to implement a basic thread pool. All workers share the same SharedArrayBuffer for their linear memory, which requires the WebAssembly threading proposal. From there, messages get sent to worker threads using a tokio::sync::mpsc channel, which uses Condvar under the hood.

The way you enable atomics in Rust is with the -Ctarget-feature=+atomics,+bulk-memory rustflags.

Unfortunately, std comes pre-compiled for wasm32-unknown-unknown (that's what rustup target add ... downloads), so even if you set $RUSTFLAGS or put the flags in .cargo/config.toml, things like Condvar will use the "unsupported" implementation which always panics.

You can fix this by telling cargo to rebuild the standard library with the correct $RUSTFLAGS. You can set this automatically by modifying your .cargo/config.toml file:

# .cargo/config.toml

[target.'cfg(target_arch = "wasm32")']
# Use "wasmer" for running tests when compiled to WebAssembly
runner = ["wasmer", "run"]
# This is needed so the module is compiled with atomics support (shared memory)
# We add the `-no-check-features` linker args because otherwise one of the modules fails to link
rustflags = '-Ctarget-feature=+atomics,+bulk-memory -Clink-args=--no-check-features'

[unstable]
# We want to make sure std gets built with atomics, too
build-std = ['std', 'panic_abort']

The build-std feature is unstable, and therefore only available on nightly.

You can run wasm-pack tests on nightly using the following

Steps to reproduce

There are a couple ways you can reproduce this.

If you are running a web app that uses the wasmer-wasix crate under the hood, you may see an exception like this from one of the worker threads:

wasm-bindgen-test_bg.wasm:0x14ec439 Uncaught (in promise) RuntimeError: unreachable
    at __rust_start_panic (wasm-bindgen-test_bg.wasm:0x14ec439)
    at rust_panic (wasm-bindgen-test_bg.wasm:0x14d173c)
    at std::panicking::rust_panic_with_hook::h7f7102b82d51338f (wasm-bindgen-test_bg.wasm:0x11d1215)
    at std::panicking::begin_panic_handler::{{closure}}::hfa40135feb109919 (wasm-bindgen-test_bg.wasm:0x12a11e3)
    at std::sys_common::backtrace::__rust_end_short_backtrace::haf21bfec9a028e09 (wasm-bindgen-test_bg.wasm:0x14ec069)
    at rust_begin_unwind (wasm-bindgen-test_bg.wasm:0x13d842a)
    at core::panicking::panic_fmt::he4489d678d6570d5 (wasm-bindgen-test_bg.wasm:0x14989ee)
    at std::sys::wasm::locks::condvar::Condvar::wait::h2cd023b14d678b96 (wasm-bindgen-test_bg.wasm:0x14578f1)
    at std::sync::condvar::Condvar::wait::h3d3df320bb943f6e (wasm-bindgen-test_bg.wasm:0x10164f3)
    at tokio::runtime::park::Inner::park::hb4fb5fafc6db5d36 (wasm-bindgen-test_bg.wasm:0xb889dd)
    at tokio::runtime::park::CachedParkThread::park::{{closure}}::hdf0900dc017d5606 (wasm-bindgen-test_bg.wasm:0x14778f7)
    at tokio::runtime::park::CachedParkThread::with_current::{{closure}}::hf332e1883859450c (wasm-bindgen-test_bg.wasm:0x14573a8)
    at std::thread::local::LocalKey<T>::try_with::hab7631a84070acb6 (wasm-bindgen-test_bg.wasm:0x106c34f)
    at tokio::runtime::park::CachedParkThread::with_current::hefde44dbf608510f (wasm-bindgen-test_bg.wasm:0x1421199)
    at tokio::runtime::park::CachedParkThread::park::h827bcc2f49db8e95 (wasm-bindgen-test_bg.wasm:0x140fd9a)
    at tokio::sync::mpsc::chan::Rx<T,S>::try_recv::{{closure}}::h7c77c7c4726b2128 (wasm-bindgen-test_bg.wasm:0xc6a5b2)
    at tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut::h6f8736a8a89ffe62 (wasm-bindgen-test_bg.wasm:0x13e7084)
    at tokio::sync::mpsc::chan::Rx<T,S>::try_recv::h2ba6aef56be7dc02 (wasm-bindgen-test_bg.wasm:0x13b0a49)
    at tokio::sync::mpsc::unbounded::UnboundedReceiver<T>::try_recv::hac2f62278a7b5734 (wasm-bindgen-test_bg.wasm:0x1488636)
    at wasmer_wasix::runtime::task_manager::web_thread_pool::ThreadStateSync::work::hebed6819631e4e3c (wasm-bindgen-test_bg.wasm:0x24ef65)
    at wasmer_wasix::runtime::task_manager::web_thread_pool::worker_entry_point::h9ae066ccd0ea5cdf (wasm-bindgen-test_bg.wasm:0x8d3968)
    at worker_entry_point (wasm-bindgen-test_bg.wasm:0x1448069)
    at worker_entry_point (wasm-bindgen-test:403:10)
    at globalThis.onmessage (bca07945-deed-4069-aa93-c62e622829dd:15:9)

This happens because creating a wasmer_wasix::runtime::task_manager::WebTaskManager requires setting up a thread pool, and the newly spawned web worker hit that panic!("condvar wait not supported") when it started listening for events. The threadpool has no way of knowing this, so from a WebTaskManager's perspective it's the task just looks like it takes forever to run.

A simpler way to reproduce this is using wasm-pack test and these tests from the wasmer-wasix crate:

// lib/wasix/tests/web.rs

use std::sync::{Condvar, Mutex};

#[wasm_bindgen_test::wasm_bindgen_test]
fn atomics_are_enabled() {
    assert!(cfg!(target_feature = "atomics"));
}

#[wasm_bindgen_test::wasm_bindgen_test]
fn condvar_works() {
    let mutex = Mutex::new("asdf");
    let condvar = Condvar::new();

    let _guard = condvar.wait(mutex.lock().unwrap()).unwrap();
}

Those tests should fail with the following:

$ wasm-pack test --chrome  --features=wasmer/js,wasmer/std,js --no-default-features

---- web::condvar_works output ----
    error output:
        panicked at 'condvar wait not supported', library/std/src/sys/wasm/../unsupported/locks/condvar.rs:20:9
        
        Stack:
        
        Error
            at http://127.0.0.1:8000/wasm-bindgen-test:725:21
            at logError (http://127.0.0.1:8000/wasm-bindgen-test:246:18)
            at imports.wbg.__wbg_new_abda76e883ba8a5f (http://127.0.0.1:8000/wasm-bindgen-test:724:66)
            at console_error_panic_hook::Error::new::h02613b9d5c17cd5c (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[40711]:0x143f1a7)
            at console_error_panic_hook::hook_impl::hcd34ac60637e48a5 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[9972]:0xf98960)
            at console_error_panic_hook::hook::h1b163b7a28e26082 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[44094]:0x146eb4d)
            at core::ops::function::Fn::call::hcea8424ff554cdf9 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[39022]:0x1424698)
            at std::panicking::rust_panic_with_hook::h7f7102b82d51338f (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[17459]:0x11b092c)
            at std::panicking::begin_panic_handler::{{closure}}::hfa40135feb109919 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[21954]:0x127d17e)
            at std::sys_common::backtrace::__rust_end_short_backtrace::haf21bfec9a028e09 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[52494]:0x14beabc)
        
    JS exception that was thrown:
        RuntimeError: unreachable
            at __rust_start_panic (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[52684]:0x14bee88)
            at rust_panic (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[48523]:0x14a474e)
            at std::panicking::rust_panic_with_hook::h7f7102b82d51338f (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[17459]:0x11b0957)
            at std::panicking::begin_panic_handler::{{closure}}::hfa40135feb109919 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[21954]:0x127d17e)
            at std::sys_common::backtrace::__rust_end_short_backtrace::haf21bfec9a028e09 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[52494]:0x14beabc)
            at rust_begin_unwind (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[32883]:0x13b01ae)
            at core::panicking::panic_fmt::he4489d678d6570d5 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[43963]:0x146cfa5)
            at std::sys::wasm::locks::condvar::Condvar::wait::h2cd023b14d678b96 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[39586]:0x142d639)
            at std::sync::condvar::Condvar::wait::h976de1002f01548d (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[10821]:0xfe7d02)
            at web::condvar_works::h039bf24c11969b5f (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[13848]:0x10d8e21)

---- web::atomics_are_enabled output ----
    error output:
        panicked at 'assertion failed: cfg!(target_feature = \"atomics\")', lib/wasix/tests/web.rs:32:5
        
        Stack:
        
        Error
            at http://127.0.0.1:8000/wasm-bindgen-test:725:21
            at logError (http://127.0.0.1:8000/wasm-bindgen-test:246:18)
            at imports.wbg.__wbg_new_abda76e883ba8a5f (http://127.0.0.1:8000/wasm-bindgen-test:724:66)
            at console_error_panic_hook::Error::new::h02613b9d5c17cd5c (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[40711]:0x143f1a7)
            at console_error_panic_hook::hook_impl::hcd34ac60637e48a5 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[9972]:0xf98960)
            at console_error_panic_hook::hook::h1b163b7a28e26082 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[44094]:0x146eb4d)
            at core::ops::function::Fn::call::hcea8424ff554cdf9 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[39022]:0x1424698)
            at std::panicking::rust_panic_with_hook::h7f7102b82d51338f (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[17459]:0x11b092c)
            at std::panicking::begin_panic_handler::{{closure}}::hfa40135feb109919 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[21954]:0x127d17e)
            at std::sys_common::backtrace::__rust_end_short_backtrace::haf21bfec9a028e09 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[52494]:0x14beabc)
    
    JS exception that was thrown:
        RuntimeError: unreachable
            at std::panicking::rust_panic_with_hook::h7f7102b82d51338f (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[17459]:0x11b0951)
            at std::panicking::begin_panic_handler::{{closure}}::hfa40135feb109919 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[21954]:0x127d17e)
            at std::sys_common::backtrace::__rust_end_short_backtrace::haf21bfec9a028e09 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[52494]:0x14beabc)
            at rust_begin_unwind (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[32883]:0x13b01ae)
            at core::panicking::panic_fmt::he4489d678d6570d5 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[43963]:0x146cfa5)
            at core::panicking::panic::hea78c4e8b318407d (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[35601]:0x13e75db)
            at web::atomics_are_enabled::h8380fe219deaec1c (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[51163]:0x14b920c)
            at core::ops::function::FnOnce::call_once::h8d535a8698ab7927 (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[47227]:0x14968f0)
            at wasm_bindgen_test::__rt::Context::execute_sync::{{closure}}::h9d40de4d3d7aa4aa (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[17462]:0x11b0b63)
            at <wasm_bindgen_test::__rt::TestFuture<F> as core::future::future::Future>::poll::{{closure}}::{{closure}}::h7e923488e6ab9bbd (http://127.0.0.1:8000/wasm-bindgen-test_bg.wasm:wasm-function[19530]:0x1214d28)

failures:

    web::condvar_works
    web::atomics_are_enabled

If you made the above changes to .cargo/config.toml and have a nightly compiler installed, tests using WebTaskManager will now pass if you run wasm-pack test in a nightly environment.

$ rustup run nightly wasm-pack test --chrome  --features=wasmer/js,wasmer/std,js --no-default-features

Additional context

See the original conversation with me and @john-sharratt on Slack.

Michael-F-Bryan pushed a commit that referenced this issue Aug 7, 2023
@Michael-F-Bryan Michael-F-Bryan self-assigned this Aug 8, 2023
@Michael-F-Bryan Michael-F-Bryan added this to the v4.x milestone Aug 8, 2023
@Michael-F-Bryan Michael-F-Bryan added 📦 lib-wasi About wasmer-wasi priority-low Low priority issue lib-wasix Issues related to the WASIX toolchain. labels Aug 8, 2023
@syrusakbary syrusakbary modified the milestones: v4.x, backlog Sep 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📦 lib-wasi About wasmer-wasi lib-wasix Issues related to the WASIX toolchain. priority-low Low priority issue
Projects
None yet
Development

No branches or pull requests

2 participants