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

Senders and receivers are both unusable in browser main thread in WASM #137

Closed
white-axe opened this issue Nov 30, 2023 · 0 comments · Fixed by #138
Closed

Senders and receivers are both unusable in browser main thread in WASM #137

white-axe opened this issue Nov 30, 2023 · 0 comments · Fixed by #138

Comments

@white-axe
Copy link
Contributor

I made a WebAssembly example at https://github.com/white-axe/flume-wasm-atomics-test that uses flume to send data between the main thread of a web browser and a web worker.

However, it crashes sporadically with errors like this:

Uncaught (in promise) RuntimeError: Atomics.wait cannot be called in this context
    at core::core_arch::wasm32::atomic::memory_atomic_wait32::h96376a6414a86a87 (flume-wasm-atomics-test_bg.wasm:0xe12d2)
    at std::sys::wasm::futex::futex_wait::h292a0a973fc726d3 (flume-wasm-atomics-test_bg.wasm:0xa5924)
    at std::sys::wasm::locks::futex_mutex::Mutex::lock_contended::hd45bb12cab0c22e6 (flume-wasm-atomics-test_bg.wasm:0x702c4)
    at std::sys::wasm::locks::futex_mutex::Mutex::lock::h73cff9beb960ea5f (flume-wasm-atomics-test_bg.wasm:0x98dd2)
    at std::sync::mutex::Mutex<T>::lock::h1b6b582f0a571882 (flume-wasm-atomics-test_bg.wasm:0xdc6de)
    at flume::wait_lock::h1c6a6297de59474f (flume-wasm-atomics-test_bg.wasm:0xaa943)
    at flume::Shared<T>::recv::h41d724fcd222a605 (flume-wasm-atomics-test_bg.wasm:0x457ca)
    at flume::Shared<T>::recv_sync::h75768094a9f2c6b2 (flume-wasm-atomics-test_bg.wasm:0x9caf9)
    at flume::async::RecvFut<T>::poll_inner::hbd655e3c0d43e014 (flume-wasm-atomics-test_bg.wasm:0x328d0)
    at <flume::async::RecvFut<T> as core::future::future::Future>::poll::hbd3ea43ef3f7793f (flume-wasm-atomics-test_bg.wasm:0xca7d9)

This is happening because the wait_lock function is using a mutex or spinlock:

flume/src/lib.rs

Lines 395 to 416 in fcf3849

#[cfg(feature = "spin")]
#[inline]
fn wait_lock<T>(lock: &Spinlock<T>) -> SpinlockGuard<T> {
let mut i = 4;
loop {
for _ in 0..10 {
if let Some(guard) = lock.try_lock() {
return guard;
}
thread::yield_now();
}
// Sleep for at most ~1 ms
thread::sleep(Duration::from_nanos(1 << i.min(20)));
i += 1;
}
}
#[cfg(not(feature = "spin"))]
#[inline]
fn wait_lock<'a, T>(lock: &'a Mutex<T>) -> MutexGuard<'a, T> {
lock.lock().unwrap()
}

In my example, it's using the mutex implementation of wait_lock and the mutex is causing the error because it's blocking in the main thread of a web browser, and this is not allowed. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/wait:

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

My example itself doesn't block the main thread, it's just the wait_lock function that's blocking. If you look at my example, you'll notice I only used non-blocking code on the main thread.

However, using the spinlock implementation by enabling the spin feature doesn't work either because that uses thread::sleep which also blocks and therefore cannot be used in the main thread. This basically makes it impossible to use senders or receivers at all in a reliable way in multithreaded WebAssembly projects if either the sender or the receiver is on the main thread.

I propose to add a plain spinlock implementation of wait_lock without thread::sleep for WebAssembly like I did here: Astrabit-ST@d323799. Of course, this should be opt-in if it's implemented because not every WebAssembly project using flume is going to run into this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant