-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Description
Summary
PR #151016 introduced a blanket cfg!(target_os = "wasi") guard in Thread::new() that immediately returns UNSUPPORTED_PLATFORM for all WASI targets, without ever calling pthread_create. This breaks projects targeting wasm32-wasip1-threads that link against emnapi, which provides a fully working pthread_create implementation backed by Web Workers.
Affected Code
library/std/src/sys/thread/unix.rs, lines 46-54:
impl Thread {
pub unsafe fn new(stack: usize, init: Box<ThreadInit>) -> io::Result<Thread> {
// FIXME: remove this block once wasi-sdk is updated with the fix from
// https://github.com/WebAssembly/wasi-libc/pull/716
// WASI does not support threading via pthreads. While wasi-libc provides
// pthread stubs, pthread_create returns EAGAIN, which causes confusing
// errors. We return UNSUPPORTED_PLATFORM directly instead.
if cfg!(target_os = "wasi") {
return Err(io::Error::UNSUPPORTED_PLATFORM);
}
// ... pthread_create call never reached for WASI ...Background
PR #151016 was merged to fix a regression where wasi-libc's stub pthread_create returned EAGAIN, causing libraries like rayon to panic. The fix was correct for that specific scenario.
However, the wasm32-wasip1-threads target exists precisely for WASI programs that do support threading. Projects in the WebAssembly/Node.js ecosystem use emnapi (an implementation of Node-API for WebAssembly) which provides a real, working pthread_create that spawns Web Workers. This has been working reliably across the ecosystem until Rust 1.94.0.
The cfg!(target_os = "wasi") check is evaluated at compile time and cannot distinguish between:
- wasi-libc's stub
pthread_create(returnsEAGAIN— broken) - emnapi's
pthread_create(creates Web Workers — working)
Impact
napi-rs is a widely-used framework for building Node.js native addons in Rust, with support for compiling to wasm32-wasip1-threads for platform-independent WebAssembly distribution. It uses tokio's multi-thread runtime, which calls std::thread::spawn to create worker threads.
- https://github.com/rolldown/rolldown
- https://github.com/web-infra-dev/rspack
- https://github.com/oxc-project/oxc
These projects are impacted.
Since Rust 1.94.0, all async functionality in napi-rs WASI builds is broken:
thread '<unnamed>' (2) panicked at
tokio-1.50.0/src/runtime/scheduler/multi_thread/worker.rs:489:13:
OS can't spawn worker thread: operation not supported on this platform
This affects every napi-rs project that publishes a WASI target (used as a universal fallback when no prebuilt native binary is available for the user's platform).
Other projects using emnapi with wasm32-wasip1-threads are likely affected as well.
Reproduction
# Install the target
rustup target add wasm32-wasip1-threads
# Clone napi-rs
git clone https://github.com/napi-rs/napi-rs
cd napi-rs
# Install JS dependencies
yarn install --immutable --mode=skip-build
# Build the WASI example (requires emnapi to be available)
yarn build
RUSTFLAGS='--cfg tokio_unstable' \
yarn workspace @examples/napi build --target wasm32-wasip1-threads --profile wasi
# Run tests with WASI binding forced
NAPI_RS_FORCE_WASI=true WASI_TEST=true SKIP_UNWIND_TEST=1 \
yarn workspace @examples/napi testWith Rust 1.93.0: all tests pass.
With Rust 1.94.0: panics with "operation not supported on this platform" on any async operation.
Minimal analysis
The check if cfg!(target_os = "wasi") on line 52 of unix.rs compiles to a constant true for all WASI targets, including wasm32-wasip1-threads. The function returns Err(io::Error::UNSUPPORTED_PLATFORM) without ever attempting pthread_create. Since emnapi's pthread_create is linked into the final .wasm binary and works correctly, this early return is incorrect for this use case.
Versions
- Rust 1.93.0:
std::thread::spawnworks onwasm32-wasip1-threads(callspthread_create) - Rust 1.94.0:
std::thread::spawnunconditionally returnsUNSUPPORTED_PLATFORMon all WASI targets - Tokio: 1.44+ (any version — the issue is in std, not tokio)
- emnapi: 1.7+
References
- Rust PR that introduced the regression: fix: WASI threading regression by disabling pthread usage #151016
- The earlier PR that moved WASI to unix threading: std: Use more
unix.rscode on WASI targets #147572 - wasi-libc upstream fix referenced in the FIXME: Change
pthread_createstub's error code WebAssembly/wasi-libc#716 - napi-rs CI failure: https://github.com/napi-rs/napi-rs/actions/runs/22751513077/job/65986844078