Skip to content

Special-case emscripten without atomics to take no-threads path#156366

Open
juntyr wants to merge 1 commit into
rust-lang:mainfrom
juntyr:emscripten-no-threads-sync
Open

Special-case emscripten without atomics to take no-threads path#156366
juntyr wants to merge 1 commit into
rust-lang:mainfrom
juntyr:emscripten-no-threads-sync

Conversation

@juntyr

@juntyr juntyr commented May 9, 2026

Copy link
Copy Markdown
Contributor

Fixes #156350

Emscripten's pthread stub, which is used when compiling Emscripten without pthreads/atomics, has an unsound mutex implementation. As a quick fix, explicitly make Emscripten without atomics take the no-threads path.

@hoodmane Do we support Emscripten tests in CI here? How should we test this?

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels May 9, 2026
@rustbot

rustbot commented May 9, 2026

Copy link
Copy Markdown
Collaborator

r? @Mark-Simulacrum

rustbot has assigned @Mark-Simulacrum.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ChrisDenton, libs
  • @ChrisDenton, libs expanded to 8 candidates
  • Random selection from Mark-Simulacrum, nia-e

@juntyr juntyr force-pushed the emscripten-no-threads-sync branch from 3eabd84 to aeabcda Compare May 9, 2026 15:50
@Mark-Simulacrum

Copy link
Copy Markdown
Member

As a quick fix, explicitly make Emscripten without atomics take the no-threads path

Does Emscripten without atomics mean Emscripten without threads? It's not obvious to me that is true.

@curiousdannii

curiousdannii commented May 10, 2026

Copy link
Copy Markdown

Or the reverse - atomics could be enabled but pthreads disabled.

If Emscripten pthreads needs RUSTFLAGS="-Clink-arg=-pthread" then is it even something that could be tested with cfg_select!?

Also for a Rust staticlib there might not be any link args?

@juntyr

juntyr commented May 11, 2026

Copy link
Copy Markdown
Contributor Author

As a quick fix, explicitly make Emscripten without atomics take the no-threads path

Does Emscripten without atomics mean Emscripten without threads? It's not obvious to me that is true.

@sbc100 Could you answer this one?

@Mark-Simulacrum

Copy link
Copy Markdown
Member

It's not obvious to me what the right behavior here is. I'm not very happy that we have no-threads targets as an implicit catch-all in std's implementation, that seems very dangerous since the implementation is unsound if someone forgets to note that a target does in fact have threads. It seems like that ought to condition on something like cfg(not(target_has_threads)) from the singlethread target option...

Based on rustc --print target-spec-json --target wasm32-unknown-emscripten -Zunstable-options, it looks like wasm32-unknown-emscripten does currently set singlethread to true, so I think from that perspective this is reasonable. But it also seems like we declare that target to have atomics:

$ rustc --print cfg --target wasm32-unknown-emscripten -Zunstable-options
target_has_atomic
target_has_atomic="16"
target_has_atomic="32"
target_has_atomic="64"
target_has_atomic="8"
...

So even without the target feature (which doesn't appear to be present in the list), it seems like gating on atomics is a pretty weird thing to do.

target_feature="bulk-memory"
target_feature="crt-static"
target_feature="exception-handling"
target_feature="multivalue"
target_feature="mutable-globals"
target_feature="nontrapping-fptoint"
target_feature="reference-types"
target_feature="sign-ext"

cc @hoodmane @juntyr (https://doc.rust-lang.org/nightly/rustc/platform-support/wasm32-unknown-emscripten.html#target-maintainers), do you have an opinion here? It seems like that's the only currently present emscripten target, in which case we could adjust the cfg here to just be "emscripten" perhaps?

@Mark-Simulacrum

Copy link
Copy Markdown
Member

Just another poke of the target maintainers: @hoodmane @juntyr, can you take a look at this PR?

@juntyr

juntyr commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@hoodmane you might be more knowledgeable here; I am unfortunately also currently very low on time

@hoodmane

Copy link
Copy Markdown
Contributor

I agree it's not obvious that no threads implies no atomics but no atomics definitely implies no threads. So I think this is an improvement as is, but might not be the best possible improvement.

@Mark-Simulacrum

Copy link
Copy Markdown
Member

@bors r+

OK, I'm going to go ahead and approve this for now. In parallel I've put up #158782 adding a compile-time assertion that no_threads code is only used on single-threaded (according to target spec) targets. It should pass on our current (single) emscripten target.

@rust-bors

rust-bors Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

📌 Commit aeabcda has been approved by Mark-Simulacrum

It is now in the queue for this repository.

🌲 The tree is currently closed for pull requests below priority 1000. This pull request will be tested once the tree is reopened.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 4, 2026
jhpratt added a commit to jhpratt/rust that referenced this pull request Jul 5, 2026
… r=Mark-Simulacrum

Special-case emscripten without atomics to take no-threads path

Fixes rust-lang#156350

Emscripten's pthread stub, which is used when compiling Emscripten without pthreads/atomics, has an unsound mutex implementation. As a quick fix, explicitly make Emscripten without atomics take the no-threads path.

@hoodmane Do we support Emscripten tests in CI here? How should we test this?
@jhpratt

jhpratt commented Jul 5, 2026

Copy link
Copy Markdown
Member

This is the only PR in the rollup that mentions CondVar in any way, so I presume this is the cause.

@bors r- #158790 (comment)

@rust-bors rust-bors Bot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jul 5, 2026
@rust-bors

rust-bors Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

This pull request was unapproved.

This PR was contained in a rollup (#158790), which was unapproved.

View changes since this unapproval

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 5, 2026
… r=Urgau

Add and use cfg(target_has_threads) to enforce no_thread impl usage

The standard library has fallback code for targets without threads (e.g., using a Cell-based Mutex and similar). Today there's no enforcement in std that those targets truly don't have threads which makes that code potentially unsound. This will let us add a static assertion that the target spec agrees that the target is non-threaded. Getting the target spec wrong is already unsound (e.g., LLVM can make use of that) so it's a reasonable source of truth. This pulls in the atomics target feature into the target code and makes the field itself private to encourage going via the method.

For now the cfg is added as unstable but if we have a use case for user code to use this, happy to cut a tracking issue and make it a regular unstable feature.

Setting a compiler reviewer since the std changes are pretty trivial, and I think anyone can review those reasonably.

cc rust-lang#156366 which prompted looking into this

r? compiler
jhpratt added a commit to jhpratt/rust that referenced this pull request Jul 6, 2026
… r=Urgau

Add and use cfg(target_has_threads) to enforce no_thread impl usage

The standard library has fallback code for targets without threads (e.g., using a Cell-based Mutex and similar). Today there's no enforcement in std that those targets truly don't have threads which makes that code potentially unsound. This will let us add a static assertion that the target spec agrees that the target is non-threaded. Getting the target spec wrong is already unsound (e.g., LLVM can make use of that) so it's a reasonable source of truth. This pulls in the atomics target feature into the target code and makes the field itself private to encourage going via the method.

For now the cfg is added as unstable but if we have a use case for user code to use this, happy to cut a tracking issue and make it a regular unstable feature.

Setting a compiler reviewer since the std changes are pretty trivial, and I think anyone can review those reasonably.

cc rust-lang#156366 which prompted looking into this

r? compiler
jhpratt added a commit to jhpratt/rust that referenced this pull request Jul 6, 2026
… r=Urgau

Add and use cfg(target_has_threads) to enforce no_thread impl usage

The standard library has fallback code for targets without threads (e.g., using a Cell-based Mutex and similar). Today there's no enforcement in std that those targets truly don't have threads which makes that code potentially unsound. This will let us add a static assertion that the target spec agrees that the target is non-threaded. Getting the target spec wrong is already unsound (e.g., LLVM can make use of that) so it's a reasonable source of truth. This pulls in the atomics target feature into the target code and makes the field itself private to encourage going via the method.

For now the cfg is added as unstable but if we have a use case for user code to use this, happy to cut a tracking issue and make it a regular unstable feature.

Setting a compiler reviewer since the std changes are pretty trivial, and I think anyone can review those reasonably.

cc rust-lang#156366 which prompted looking into this

r? compiler
rust-timer added a commit that referenced this pull request Jul 6, 2026
Rollup merge of #158782 - Mark-Simulacrum:expose-no-threads, r=Urgau

Add and use cfg(target_has_threads) to enforce no_thread impl usage

The standard library has fallback code for targets without threads (e.g., using a Cell-based Mutex and similar). Today there's no enforcement in std that those targets truly don't have threads which makes that code potentially unsound. This will let us add a static assertion that the target spec agrees that the target is non-threaded. Getting the target spec wrong is already unsound (e.g., LLVM can make use of that) so it's a reasonable source of truth. This pulls in the atomics target feature into the target code and makes the field itself private to encourage going via the method.

For now the cfg is added as unstable but if we have a use case for user code to use this, happy to cut a tracking issue and make it a regular unstable feature.

Setting a compiler reviewer since the std changes are pretty trivial, and I think anyone can review those reasonably.

cc #156366 which prompted looking into this

r? compiler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mutex::try_lock doesn't error in wasm32-emscripten

6 participants