Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upSafe access to a `#[thread_local]` should be disallowed #17954
Comments
This comment has been minimized.
This comment has been minimized.
|
Another route would just be disallowing borrows as well, similar to how we only allow borrows of statics in statics. |
This comment has been minimized.
This comment has been minimized.
|
It could be allowed if it gave borrows something like a |
This comment has been minimized.
This comment has been minimized.
|
Where is the unsoundness there? |
This comment has been minimized.
This comment has been minimized.
|
The lifetime |
thestinger
added
A-typesystem
A-lifetimes
labels
Oct 11, 2014
This comment has been minimized.
This comment has been minimized.
|
It seems like it would be really easy to add |
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton: It also permits data races now that internal mutability in a |
This comment has been minimized.
This comment has been minimized.
|
Do we need |
This comment has been minimized.
This comment has been minimized.
|
@eddyb: It needs |
This comment has been minimized.
This comment has been minimized.
|
Preventing data races is a job for @eddyb |
This comment has been minimized.
This comment has been minimized.
A |
This comment has been minimized.
This comment has been minimized.
|
I don't think adding a new 'task lifetime is actually that helpful for thread-locals. If they are Send, and are using fork-join concurrency, 'task means something different in a child thread from a parent thread, so a child 'task might outlive a parent 'task--how do you disambiguate? Does Rust know when the new 'task lifetime is created in the child so it can reason about this soundly? If it does, and they have different lifetime names, why use 'task at all and not just a regular lifetime? On the other hand, if you can't Send them, just make them NoSend and have done with it. The only problem with making thread locals NoSend is that then you can't send them between tasks in fork-join style APIs. If you can't resolve the issues above, there's probably no sane way of determining that anyway so you might as well ban it (and really, I think it's a pretty niche usecase to want shared thread local data). I don't think semantics are a good argument here. There are lots of examples of things that aren't "semantically" 'static, like data in Rcs (which can never outlive its calling thread) that nonetheless get along without special lifetimes. |
This comment has been minimized.
This comment has been minimized.
|
The point of
It would be trivial to add it, and it doesn't need to know anything about other tasks.
It's possible to get a reference to the value inside the thread-local variable, and it should be considered as having a
That's not the point here. The |
This comment has been minimized.
This comment has been minimized.
|
There is already a way to identify 'statics that are not Send, NoSend. As far as I know, it has all the properties you're looking for. What is the purpose of adding something functionally identical? Am I missing some way in which it would or could conceivably work differently? |
This comment has been minimized.
This comment has been minimized.
|
It's not functionally identical. It should be possible for a thread-local |
This comment has been minimized.
This comment has been minimized.
|
There's already a feature gate for In C++, you just mark a global variable as |
This comment has been minimized.
This comment has been minimized.
|
Okay, I see your objection now, that makes sense. |
This comment has been minimized.
This comment has been minimized.
|
Also, the lifetime would likely be called |
This comment has been minimized.
This comment has been minimized.
|
Anyway, until Rust no longer has to worry about 32-bit iOS and old versions of Android it's a dead end. It doesn't really matter if it's safe or not at the moment because it's just an implementation detail for a safe library making use of it. I'm just pointing out that Rust could have TLS that's as easy to use as it is in C++11 and D rather than doing it via library hacks. |
This comment has been minimized.
This comment has been minimized.
|
Updated code:
|
alexcrichton
referenced this issue
Nov 5, 2015
Open
Tracking issue for `thread_local` stabilization #29594
This comment has been minimized.
This comment has been minimized.
|
The updated code still compiles on Code used: #![feature(thread_local)]
#[thread_local]
static FOO: usize = 3;
fn main() {
let a = &FOO;
let jg = std::thread::spawn(move || {
println!("{}", a);
});
jg.join().unwrap();
} |
This comment has been minimized.
This comment has been minimized.
|
Coming back to this: I think I've come to accept the simpler solution of not giving TLS variables a specific named lifetime but rather the outermost scope of the current function. That would require banning references from any other statics too. |
arielb1
added
I-unsound 💥
I-nominated
labels
Mar 15, 2016
eddyb
referenced this issue
Mar 15, 2016
Merged
RFC - Allow Drop types in statics/const functions #1440
This comment has been minimized.
This comment has been minimized.
|
label: T-lang |
This comment has been minimized.
This comment has been minimized.
|
er, meant to add that as a tag... |
alexcrichton
added
the
T-lang
label
Mar 16, 2016
This comment has been minimized.
This comment has been minimized.
|
Removing nomination as it doesn't seem that important to resolve this imminently. It'd be good to have a summary comment though of major points in the thread. |
This comment has been minimized.
This comment has been minimized.
|
triage: P-medium |
rust-highfive
added
the
P-medium
label
Mar 17, 2016
alexcrichton
referenced this issue
Aug 5, 2016
Closed
Remove the `Sync` requirement for `#[thread_local]` statics. #35035
This comment has been minimized.
This comment has been minimized.
Short summary:
¹: Can’t freely use (e.g. return out of function which accesses the TLS) the reference within the thread either, though? |
ghost
referenced this issue
Dec 19, 2016
Closed
Drain on root logger should not require 'static. #95
This comment has been minimized.
This comment has been minimized.
|
So since it seems we don't want the |
This comment has been minimized.
This comment has been minimized.
|
I still want the semantics that make thread-local accesses like function arguments: can't let them escape. |
This comment has been minimized.
This comment has been minimized.
|
To clarify: IMO it's still important to be able to be able to use thread locals directly, since thread_local! does have significant overhead by comparison. |
This comment has been minimized.
This comment has been minimized.
|
@pythonesque do you have benchmarks to back that up? IIRC, @alexcrichton gathered various numbers that seemed to suggest the opposite, but I may be mis-remembering. |
Mark-Simulacrum
added
the
C-bug
label
Jul 22, 2017
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis Can confirm that I'm implementing my own channels (similar to
The difference is significant enough to be a real-world problem. |
This comment has been minimized.
This comment has been minimized.
|
Yes there's no debate that To actually quantify what's going on here, the I do not think we should strive to stabilize |
This comment has been minimized.
This comment has been minimized.
Ok, since
I like this idea. What would it take to implement this today, or at least what would be the first step forward? |
This comment has been minimized.
This comment has been minimized.
I'll just open a PR with my solution, it shouldn't be hard at all...
That's easy in the compiler but |
This comment has been minimized.
This comment has been minimized.
... But we could add an |
This comment has been minimized.
This comment has been minimized.
|
@stjepang yeah right now As for how to implement a "const expr detection" in a macro I'm not entirely sure. We could either move the implementation into the compiler (which I'd prefer to avoid) or take @arielb1's suggestion of a new macro or a variant of the current macro's syntax. For example we could "perverse" the meaning via: |
This was referenced Aug 8, 2017
bors
added a commit
that referenced
this issue
Aug 11, 2017
bors
added a commit
that referenced
this issue
Aug 11, 2017
bors
added a commit
that referenced
this issue
Aug 12, 2017
bors
added a commit
that referenced
this issue
Aug 12, 2017
bors
closed this
in
#43746
Aug 12, 2017
This comment has been minimized.
This comment has been minimized.
|
Thanks @eddyb for fixing this issue! Can we create a new issue for the optimization part (thread locals initialized by a constant expression should bypass the "am I initialized" check on every access)? |
This comment has been minimized.
This comment has been minimized.
|
@stjepang Sure, but I'm not sure how to do that cleanly to be honest. |
alexcrichton commentedOct 11, 2014
Today this code compiles just fine, but it probably shouldn't:
I'm not nominating this because
thread_localis behind a feature gate, just wanted an issue to track it.