-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Forbid inlining thread_local!
's __getit
function on Windows
#101368
Conversation
Just to clarify my understanding of the issue here: |
Or in other words, if we make |
Just to be clear, it's not crate boundaries that are the issue. It's dll/exe boundaries. Ideally it'd be great if it could inline across crate boundaries if that doesn't also cause it to jump across dll boundaries. |
@nikic The issue is that on Windows, if the instantiation of the This happens in practice if we have My understanding is that it's completely possible for this to happen even across a That said, I don't know that anybody has seen it happen. @ChrisDenton indicated that they may have seen it once, but weren't sure. I feel like there are enough configuration options here (including things like However, if you know a reason that I'm wrong and the inlining can't happen without |
I'm going to cc a few people just in case they want to comment on the compiler/dylibs situation with Windows |
Sounds good, there's no rush here, it's mostly a PR made out of caution, and it would be way better to solve this in a better way (it just seems like if we're going to rely on it not being inlined for correctness we shouldn't mark it as something which is allowed to be inlined). |
If the fix is from going between "no Is it "per-CGU copies" while building a single crate (and was that what @nikic was referencing above)? Is it from LTO? Normally a non-(type/const)-generic function doesn't get cross-crate codegen without an If that is the case, it's probably safe to claim that people working on these parts of the stdlib weren't aware that such duplication existed without an |
I just hit this issue on x86_64 Windows on nightly. Please merge this fix, it would be helpful. Thanks! |
@eddyb I think that's right, yes. |
@Subsentient would you be able to give more details? It would be super helpful if you're able. Also did you test if this PR does address the problem you're seeing? No worries if not but it'd be good to confirm. Btw, I am minded to merge this as an interim fix but I would really love for the underlying problem to be addressed somehow. |
So I'm hitting this in a performance library specific to my company. It is happening in __getit(). I can't post source, it's legally not my code, it belongs to the company, but I can post a screenshot of a backtrace. Yes, I would appreciate a merge. It's obviously not a great fix, but if it fixes the functionality, that will be very useful. |
Thank you! As I say, I do think this needs investigating more but this PR should fix it while that happens. @bors r+ |
📌 Commit 4062925df2350e8c51eb59f5d6dd157d38f79274 has been approved by It is now in the queue for this repository. |
Revert last commit? |
Oh oops. @bors r- |
Crap, totally forgot to revert that. |
4062925
to
3099dfd
Compare
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
@bors r=ChrisDenton |
Forbid inlining `thread_local!`'s `__getit` function on Windows Sadly, this will make things slower to avoid UB in an edge case, but it seems hard to avoid... and really whenever I look at this code I can't help but think we're asking for trouble. It's pretty dodgy for us to leave this as a normal function rather than `#[inline(never)]`, given that if it *does* get inlined into a dynamically linked component, it's extremely unsafe (you get some other thread local, or if you're lucky, crash). Given that it's pretty rare for people to use dylibs on Windows, the fact that we haven't gotten bug reports about it isn't really that convincing. Ideally we'd come up with some kind of compiler solution (that avoids paying for this cost when static linking, or *at least* for use within the same crate...), but it's not clear what that looks like. Oh, and because all this is only needed when we're implementing `thread_local!` with `#[thread_local]`, this patch adjusts the `cfg_attr` to be `all(windows, target_thread_local)` as well. r? `@ChrisDenton` See also rust-lang#84933, which is about improving the situation.
Forbid inlining `thread_local!`'s `__getit` function on Windows Sadly, this will make things slower to avoid UB in an edge case, but it seems hard to avoid... and really whenever I look at this code I can't help but think we're asking for trouble. It's pretty dodgy for us to leave this as a normal function rather than `#[inline(never)]`, given that if it *does* get inlined into a dynamically linked component, it's extremely unsafe (you get some other thread local, or if you're lucky, crash). Given that it's pretty rare for people to use dylibs on Windows, the fact that we haven't gotten bug reports about it isn't really that convincing. Ideally we'd come up with some kind of compiler solution (that avoids paying for this cost when static linking, or *at least* for use within the same crate...), but it's not clear what that looks like. Oh, and because all this is only needed when we're implementing `thread_local!` with `#[thread_local]`, this patch adjusts the `cfg_attr` to be `all(windows, target_thread_local)` as well. r? ```@ChrisDenton``` See also rust-lang#84933, which is about improving the situation.
Rollup of 7 pull requests Successful merges: - rust-lang#101368 (Forbid inlining `thread_local!`'s `__getit` function on Windows) - rust-lang#102293 (Add powerpc64-ibm-aix as Tier-3 target) - rust-lang#104717 (Add failing test for projections used as const generic) - rust-lang#104720 (rustdoc: remove no-op CSS `.popover::before / a.test-arrow { display: inline-block }`) - rust-lang#104722 (Speed up mpsc_stress test) - rust-lang#104724 (Fix `ClosureKind::to_def_id`) - rust-lang#104728 (Use `tcx.require_lang_item` instead of unwrapping lang items) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Wow, that's pretty spooky since it definitely shouldn't have an impact like that. That's definitely a compiler bug, but I'll put up a revert anyway... |
…isDenton Revert "Forbid inlining `thread_local!`'s `__getit` function on Windows" Revert of rust-lang#101368, fixes rust-lang#104852. I'd rather not do this since that's a soundness fix and this is hitting some compiler bug, but I don't really know an alternative. r? `@ChrisDenton`
Sadly, this will make things slower to avoid UB in an edge case, but it seems hard to avoid... and really whenever I look at this code I can't help but think we're asking for trouble.
It's pretty dodgy for us to leave this as a normal function rather than
#[inline(never)]
, given that if it does get inlined into a dynamically linked component, it's extremely unsafe (you get some other thread local, or if you're lucky, crash). Given that it's pretty rare for people to use dylibs on Windows, the fact that we haven't gotten bug reports about it isn't really that convincing. Ideally we'd come up with some kind of compiler solution (that avoids paying for this cost when static linking, or at least for use within the same crate...), but it's not clear what that looks like.Oh, and because all this is only needed when we're implementing
thread_local!
with#[thread_local]
, this patch adjusts thecfg_attr
to beall(windows, target_thread_local)
as well.r? @ChrisDenton
See also #84933, which is about improving the situation.