Skip to content

fix(std): recover thread handle when current() runs before spawn init on Windows - #158579

Open
anshjaiswal12 wants to merge 3 commits into
rust-lang:mainfrom
anshjaiswal12:fix/thread-spawn-dll-attach
Open

fix(std): recover thread handle when current() runs before spawn init on Windows#158579
anshjaiswal12 wants to merge 3 commits into
rust-lang:mainfrom
anshjaiswal12:fix/thread-spawn-dll-attach

Conversation

@anshjaiswal12

@anshjaiswal12 anshjaiswal12 commented Jun 29, 2026

Copy link
Copy Markdown

Fixes #156277

On Windows, thread::spawn can abort if current() is called from a
DLL_THREAD_ATTACH handler before the new thread's TLS is initialized.
Recover the pre-initialized handle instead of aborting.

On Windows, thread::current() during DLL_THREAD_ATTACH can initialize
a temporary handle before thread::spawn sets the real one. Recover
from that pre-init state instead of aborting.
Keep the spawn recovery logic without the env-var test shim in
library/std.
@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 Jun 29, 2026
@rustbot

rustbot commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the pull request, and welcome! The Rust Project is excited to review your changes, and you should hear from @clarfonthey (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue
Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ChrisDenton, libs
  • @ChrisDenton, libs expanded to 13 candidates
  • Random selection from 6 candidates

@anshjaiswal12

Copy link
Copy Markdown
Author

Okay, my bad. I'll keep working on it. Thanks for your feedback. I'll try fixing it again, and then I'll submit it.

@joboet

joboet commented Jun 29, 2026

Copy link
Copy Markdown
Member

Whoops, sorry, I misunderstood the PR and commented too eagerly. I guess this might work?

Comment thread library/std/src/thread/current.rs Outdated
// SAFETY: `current` points to a valid `Thread` created by `init_current`.
let old = unsafe { Thread::from_raw(current) };
if old.name().is_some() {
return false;

@joboet joboet Jun 29, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is risky, old will be dropped here, so the TLS pointer is dangling. It's made sound by aborting immediately afterwards, but I still think it's suboptimal.

View changes since the review

Comment thread library/std/src/thread/current.rs Outdated
/// If `thread::current()` ran before [`super::lifecycle::ThreadInit::init`] on a
/// newly spawned thread (e.g. during `DLL_THREAD_ATTACH` on Windows), replace
/// the temporary handle created by [`init_current`] with the one from `thread::spawn`.
pub(super) fn recover_preinitialized_for_spawn(thread: Thread) -> bool {

@joboet joboet Jun 29, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be better to make set_current replace the current thread unconditionally, as it's only use is in ThreadInit::init.

View changes since the review

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 29, 2026
@rustbot

rustbot commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jun 29, 2026
Address review feedback: fold recover_preinitialized_for_spawn into
set_current, which unconditionally replaces any existing TLS thread
handle (as in drop_current) before installing the spawn handle.

Fixes rust-lang#156277
@rustbot

rustbot commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Warning ⚠️

  • There are issue links (such as #123) in the commit messages of the following commits.
    Please move them to the PR description, to avoid spamming the issues with references to the commit, and so this bot can automatically canonicalize them to avoid issues with subtree.

@anshjaiswal12

Copy link
Copy Markdown
Author

Addressed review feedback in 1d92717: recovery is now in set_current instead of a separate function.
@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 1, 2026
@clarfonthey

Copy link
Copy Markdown
Contributor

r? joboet since you've been doing review

@rustbot rustbot assigned joboet and unassigned clarfonthey Jul 26, 2026
@rustbot

rustbot commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

joboet is currently at their maximum review capacity.
They may take a while to respond.

@joboet joboet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not entirely convinced that we should even fix the issue in question, given that this fix will sacrifice the property that the ThreadId will not change over the lifetime of a thread.

View changes since this review

if current > DESTROYED {
// SAFETY: `current` points to a valid `Thread` created by `init_current`.
unsafe {
CURRENT.set(DESTROYED);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd update the pointer to the new handle immediately.

"set_current() was called while init_current() is in progress, \
which indicates a bug in the Rust threading implementation"
);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guard::enable only needs to be called if the above two conditions are false.

Suggested change
}
} else {
guard::enable();
CURRENT.set(thread.into_raw().cast_mut());
}

/// `thread::spawn`.
pub(super) fn set_current(thread: Thread) {
let current = CURRENT.get();
if current > DESTROYED {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should ensure that there are no outstanding references to the old handle – otherwise you might allow some very confusing behaviour.

@rustbot rustbot 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-review Status: Awaiting review from the assignee but also interested parties. labels Jul 29, 2026
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.

std::thread::spawn aborts when thread::current() is called during DLL_THREAD_ATTACH on Windows

4 participants