-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
fix: WASI threading regression by disabling pthread usage #151016
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
Conversation
This comment has been minimized.
This comment has been minimized.
2713910 to
7b2a838
Compare
|
please link any relevant issue(s) on this regression if there are any :) |
This comment has been minimized.
This comment has been minimized.
7b2a838 to
769d7d6
Compare
|
Can you share a link to the rayon code that's panicking? Is it testing for a specific I'd ideally prefer to not sprinkle |
This comment has been minimized.
This comment has been minimized.
|
This is the code in lopdf that uses rayon: self.document.objects = self
.document
.reference_table
.entries
.par_iter()
.filter_map(entries_filter_map)
.collect();I could work around this in c2pa-rs, by disabling rayon for lopdf, but that will introduce another WASI specific entry in my Cargo.toml. WASI specific dependencies and code in my SDK make it harder for me to justify supporting the target. Therefore the choice is to either have WASI specific code in this one place in the Rust source, or in every crate that uses it. I realize it's a balancing act, and I will respect your decision here. It won't ruin my day either way. |
|
I agree it'd be best to keep rayon working here, but I'd like to better understand the shape of the problem. For example can you share the location in Rayon that is panicking currently? Do you know the location in Rayon that keeps WASI working today? The crux of the question is why a changing error code for spawning a thread caused Rayon to regress. It would be good to pinpoint that as it'll inform the shape of the solution. |
|
Of course. That makes complete sense. Rayon checks to see if a target is supported here: https://github.com/rayon-rs/rayon/blob/main/rayon-core/src/lib.rs#L745-L747 fn is_unsupported(&self) -> bool {
matches!(&self.kind, ErrorKind::IOError(e) if e.kind() == io::ErrorKind::Unsupported)
}https://github.com/rayon-rs/rayon/blob/main/rayon-core/src/registry.rs#L209-L228 fn default_global_registry() -> Result<Arc<Registry>, ThreadPoolBuildError> {
let result = Registry::new(ThreadPoolBuilder::new());
// If we're running in an environment that doesn't support threads at all, we can fall back to
// using the current thread alone. This is crude, and probably won't work for non-blocking
// calls like `spawn` or `broadcast_spawn`, but a lot of stuff does work fine.
//
// Notably, this allows current WebAssembly targets to work even though their threading support
// is stubbed out, and we won't have to change anything if they do add real threading.
let unsupported = matches!(&result, Err(e) if e.is_unsupported());
if unsupported && WorkerThread::current().is_null() {
let builder = ThreadPoolBuilder::new().num_threads(1).use_current_thread();
let fallback_result = Registry::new(builder);
if fallback_result.is_ok() {
return fallback_result;
}
}
result
}If that check indicates that threading is supported, the thread registry will fail to initialize here: if let Err(e) = builder.get_spawn_handler().spawn(thread) {
return Err(ThreadPoolBuildError::new(ErrorKind::IOError(e)));
} |
This changes from `EAGAIN` to `ENOTSUP` since this operation can't ever succeed, it's entirely unsupported. This is in relation to rust-lang/rust#151016 where in the Rust ecosystem crates were using the "Unsupported" error kind to gracefully handle errors from spawning a thread, such a falling back to single-threaded code. By switching to `EAGAIN` it caused these graceful fallbacks to not get triggered.
|
Ok thanks that makes sense. I think the "real" fix here is WebAssembly/wasi-libc#716 which is to change the source of truth about the error code here. That'll take some time to propagate over here, however, so I don't think it makes sense to block on that. In the meantime, I'd personally prefer a fix such that somewhere on the thread creation path you'd add |
769d7d6 to
417199d
Compare
This comment has been minimized.
This comment has been minimized.
417199d to
1971b75
Compare
This comment has been minimized.
This comment has been minimized.
| #[cfg_attr(target_os = "wasi", allow(dead_code))] | ||
| pub struct Handler; | ||
|
|
||
| impl Handler { | ||
| #[cfg_attr(target_os = "wasi", allow(dead_code))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these two attributes can be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we can. Thanks
This changes from `EAGAIN` to `ENOTSUP` since this operation can't ever succeed, it's entirely unsupported. This is in relation to rust-lang/rust#151016 where in the Rust ecosystem crates were using the "Unsupported" error kind to gracefully handle errors from spawning a thread, such a falling back to single-threaded code. By switching to `EAGAIN` it caused these graceful fallbacks to not get triggered.
Recent changes made WASI targets use the Unix threading implementation, but WASI does not support threading. When the Unix code tries to call pthread_create, it fails with EAGAIN, causing libraries like rayon to panic when trying to initialize their global thread pool. This fix adds an early return in Thread::new() that checks for WASI and returns UNSUPPORTED_PLATFORM. This approach: - Continues using most of the unix.rs code path (less invasive) - Only requires a small cfg check at the start of Thread::new() - Can be easily removed once wasi-sdk is updated with the proper fix The real fix is being tracked in `WebAssembly/wasi-libc#716` which will change the error code returned by pthread_create to properly indicate unsupported operations. Once that propagates to wasi-sdk, this workaround can be removed. Fixes the regression where rayon-based code (e.g., lopdf in PDF handling) panicked on WASI after nightly-2025-12-10. Before fix: pthread_create returns EAGAIN (error code 6) ThreadPoolBuildError { kind: IOError(Os { code: 6, kind: WouldBlock, message: "Resource temporarily unavailable" }) } After fix: Thread::new returns Err(io::Error::UNSUPPORTED_PLATFORM) Libraries can gracefully handle the lack of threading support
1971b75 to
c1bcae0
Compare
|
|
@bors r+ |
fix: WASI threading regression by disabling pthread usage PR rust-lang#147572 changed WASI to use the Unix threading implementation, but WASI does not support threading. When the Unix code tries to call pthread_create, it fails with EAGAIN, causing libraries like rayon to panic when trying to initialize their global thread pool. The old wasip1/wasip2 implementations: - wasip1: Threading conditionally available with atomics (experimental) - wasip2: Threading unconditionally unsupported This fix restores that behavior by disabling pthread-based threading for all WASI targets: 1. Guard the pthread-based Thread implementation with #[cfg(not(target_os = "wasi"))] 2. Provide an unsupported stub (Thread(!)) for WASI 3. Return Err(io::Error::UNSUPPORTED_PLATFORM) when Thread::new is called Fixes the regression where rayon-based code (e.g., lopdf in PDF handling) panicked on WASI after nightly-2025-12-10. Before fix: pthread_create returns EAGAIN (error code 6) ThreadPoolBuildError { kind: IOError(Os { code: 6, kind: WouldBlock, message: "Resource temporarily unavailable" }) } After fix: Thread::new returns Err(io::Error::UNSUPPORTED_PLATFORM) Libraries can gracefully handle the lack of threading support r? @alexcrichton
fix: WASI threading regression by disabling pthread usage PR rust-lang#147572 changed WASI to use the Unix threading implementation, but WASI does not support threading. When the Unix code tries to call pthread_create, it fails with EAGAIN, causing libraries like rayon to panic when trying to initialize their global thread pool. The old wasip1/wasip2 implementations: - wasip1: Threading conditionally available with atomics (experimental) - wasip2: Threading unconditionally unsupported This fix restores that behavior by disabling pthread-based threading for all WASI targets: 1. Guard the pthread-based Thread implementation with #[cfg(not(target_os = "wasi"))] 2. Provide an unsupported stub (Thread(!)) for WASI 3. Return Err(io::Error::UNSUPPORTED_PLATFORM) when Thread::new is called Fixes the regression where rayon-based code (e.g., lopdf in PDF handling) panicked on WASI after nightly-2025-12-10. Before fix: pthread_create returns EAGAIN (error code 6) ThreadPoolBuildError { kind: IOError(Os { code: 6, kind: WouldBlock, message: "Resource temporarily unavailable" }) } After fix: Thread::new returns Err(io::Error::UNSUPPORTED_PLATFORM) Libraries can gracefully handle the lack of threading support r? @alexcrichton
…uwer Rollup of 12 pull requests Successful merges: - #150585 (Add a context-consistency check before emitting redundant generic-argument suggestions) - #150586 (rustdoc: Fix intra-doc link bugs involving type aliases and associated items) - #150590 (Don't try to recover keyword as non-keyword identifier ) - #150817 (cleanup: remove borrowck handling for inline const patterns) - #150939 (resolve: Relax some asserts in glob overwriting and add tests) - #150966 (rustc_target: Remove unused Arch::PowerPC64LE) - #150971 (Disallow eii in statement position) - #151016 (fix: WASI threading regression by disabling pthread usage) - #151046 (compiler: Make Externally Implementable Item (eii) macros "semiopaque") - #151103 (mir_build: Simplify length-determination and indexing for array/slice patterns) - #151117 (Avoid serde dependency in build_helper when not necessary) - #151127 (Delete `MetaItemOrLitParser::Err`) r? @ghost
fix: WASI threading regression by disabling pthread usage PR rust-lang#147572 changed WASI to use the Unix threading implementation, but WASI does not support threading. When the Unix code tries to call pthread_create, it fails with EAGAIN, causing libraries like rayon to panic when trying to initialize their global thread pool. The old wasip1/wasip2 implementations: - wasip1: Threading conditionally available with atomics (experimental) - wasip2: Threading unconditionally unsupported This fix restores that behavior by disabling pthread-based threading for all WASI targets: 1. Guard the pthread-based Thread implementation with #[cfg(not(target_os = "wasi"))] 2. Provide an unsupported stub (Thread(!)) for WASI 3. Return Err(io::Error::UNSUPPORTED_PLATFORM) when Thread::new is called Fixes the regression where rayon-based code (e.g., lopdf in PDF handling) panicked on WASI after nightly-2025-12-10. Before fix: pthread_create returns EAGAIN (error code 6) ThreadPoolBuildError { kind: IOError(Os { code: 6, kind: WouldBlock, message: "Resource temporarily unavailable" }) } After fix: Thread::new returns Err(io::Error::UNSUPPORTED_PLATFORM) Libraries can gracefully handle the lack of threading support r? @alexcrichton
…uwer Rollup of 16 pull requests Successful merges: - #150585 (Add a context-consistency check before emitting redundant generic-argument suggestions) - #150586 (rustdoc: Fix intra-doc link bugs involving type aliases and associated items) - #150590 (Don't try to recover keyword as non-keyword identifier ) - #150817 (cleanup: remove borrowck handling for inline const patterns) - #150939 (resolve: Relax some asserts in glob overwriting and add tests) - #150962 (Remove `FeedConstTy` and provide ty when lowering const arg) - #150966 (rustc_target: Remove unused Arch::PowerPC64LE) - #150971 (Disallow eii in statement position) - #151016 (fix: WASI threading regression by disabling pthread usage) - #151046 (compiler: Make Externally Implementable Item (eii) macros "semiopaque") - #151099 (Recover parse gracefully from `<const N>`) - #151117 (Avoid serde dependency in build_helper when not necessary) - #151127 (Delete `MetaItemOrLitParser::Err`) - #151128 (Add temporary new bors e-mail address to the mailmap) - #151130 (resolve: Downgrade `ambiguous_glob_imports` to warn-by-default) - #151138 (Rename `rust.use-lld` to `rust.bootstrap-override-lld` in INSTALL.md) r? @ghost
…uwer Rollup of 15 pull requests Successful merges: - #150585 (Add a context-consistency check before emitting redundant generic-argument suggestions) - #150586 (rustdoc: Fix intra-doc link bugs involving type aliases and associated items) - #150590 (Don't try to recover keyword as non-keyword identifier ) - #150817 (cleanup: remove borrowck handling for inline const patterns) - #150939 (resolve: Relax some asserts in glob overwriting and add tests) - #150962 (Remove `FeedConstTy` and provide ty when lowering const arg) - #150966 (rustc_target: Remove unused Arch::PowerPC64LE) - #150971 (Disallow eii in statement position) - #151016 (fix: WASI threading regression by disabling pthread usage) - #151046 (compiler: Make Externally Implementable Item (eii) macros "semiopaque") - #151099 (Recover parse gracefully from `<const N>`) - #151117 (Avoid serde dependency in build_helper when not necessary) - #151127 (Delete `MetaItemOrLitParser::Err`) - #151128 (Add temporary new bors e-mail address to the mailmap) - #151138 (Rename `rust.use-lld` to `rust.bootstrap-override-lld` in INSTALL.md) r? @ghost
Rollup merge of #151016 - fix_wasi_threading, r=alexcrichton fix: WASI threading regression by disabling pthread usage PR #147572 changed WASI to use the Unix threading implementation, but WASI does not support threading. When the Unix code tries to call pthread_create, it fails with EAGAIN, causing libraries like rayon to panic when trying to initialize their global thread pool. The old wasip1/wasip2 implementations: - wasip1: Threading conditionally available with atomics (experimental) - wasip2: Threading unconditionally unsupported This fix restores that behavior by disabling pthread-based threading for all WASI targets: 1. Guard the pthread-based Thread implementation with #[cfg(not(target_os = "wasi"))] 2. Provide an unsupported stub (Thread(!)) for WASI 3. Return Err(io::Error::UNSUPPORTED_PLATFORM) when Thread::new is called Fixes the regression where rayon-based code (e.g., lopdf in PDF handling) panicked on WASI after nightly-2025-12-10. Before fix: pthread_create returns EAGAIN (error code 6) ThreadPoolBuildError { kind: IOError(Os { code: 6, kind: WouldBlock, message: "Resource temporarily unavailable" }) } After fix: Thread::new returns Err(io::Error::UNSUPPORTED_PLATFORM) Libraries can gracefully handle the lack of threading support r? @alexcrichton
…uwer Rollup of 15 pull requests Successful merges: - rust-lang/rust#150585 (Add a context-consistency check before emitting redundant generic-argument suggestions) - rust-lang/rust#150586 (rustdoc: Fix intra-doc link bugs involving type aliases and associated items) - rust-lang/rust#150590 (Don't try to recover keyword as non-keyword identifier ) - rust-lang/rust#150817 (cleanup: remove borrowck handling for inline const patterns) - rust-lang/rust#150939 (resolve: Relax some asserts in glob overwriting and add tests) - rust-lang/rust#150962 (Remove `FeedConstTy` and provide ty when lowering const arg) - rust-lang/rust#150966 (rustc_target: Remove unused Arch::PowerPC64LE) - rust-lang/rust#150971 (Disallow eii in statement position) - rust-lang/rust#151016 (fix: WASI threading regression by disabling pthread usage) - rust-lang/rust#151046 (compiler: Make Externally Implementable Item (eii) macros "semiopaque") - rust-lang/rust#151099 (Recover parse gracefully from `<const N>`) - rust-lang/rust#151117 (Avoid serde dependency in build_helper when not necessary) - rust-lang/rust#151127 (Delete `MetaItemOrLitParser::Err`) - rust-lang/rust#151128 (Add temporary new bors e-mail address to the mailmap) - rust-lang/rust#151138 (Rename `rust.use-lld` to `rust.bootstrap-override-lld` in INSTALL.md) r? @ghost
PR #147572 changed WASI to use the Unix threading implementation, but WASI does not support threading. When the Unix code tries to call pthread_create, it fails with EAGAIN, causing libraries like rayon to panic when trying to initialize their global thread pool.
The old wasip1/wasip2 implementations:
This fix restores that behavior by disabling pthread-based threading for all WASI targets:
Fixes the regression where rayon-based code (e.g., lopdf in PDF handling) panicked on WASI after nightly-2025-12-10.
Before fix:
pthread_create returns EAGAIN (error code 6)
ThreadPoolBuildError { kind: IOError(Os { code: 6,
kind: WouldBlock, message: "Resource temporarily unavailable" }) }
After fix:
Thread::new returns Err(io::Error::UNSUPPORTED_PLATFORM)
Libraries can gracefully handle the lack of threading support
r? @alexcrichton