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 upstd::thread::JoinGuard (and scoped) are unsound because of reference cycles #24292
Comments
arielb1
changed the title
std::thread::JoinGuard is unsound because of reference cycles
std::thread::JoinGuard (and scoped) are unsound because of reference cycles
Apr 10, 2015
sfackler
added
the
I-nominated
label
Apr 10, 2015
This comment has been minimized.
This comment has been minimized.
|
Seems pretty bad, nominating. |
This comment has been minimized.
This comment has been minimized.
|
Sigh. Good point! This seems very similar to the dropck rules, I suspect we can address it in a similar fashion to how we addressed cc @pnkfelix UPDATE: Spelled out what I meant a bit more. |
This comment has been minimized.
This comment has been minimized.
|
I don't think this is so bad, because I can't really think of this happening accidentally. I think the best way to fix this would be to add a |
This comment has been minimized.
This comment has been minimized.
|
triage: P-backcompat-libs (1.0) I definitely think we need to address this for 1.0. I'm still not sure the best way to do it. |
rust-highfive
added
P-backcompat-libs
and removed
I-nominated
labels
Apr 10, 2015
rust-highfive
added this to the 1.0 milestone
Apr 10, 2015
aturon
added a commit
to aturon/rust
that referenced
this issue
Apr 13, 2015
aturon
added a commit
to aturon/rust
that referenced
this issue
Apr 13, 2015
bors
added a commit
that referenced
this issue
Apr 13, 2015
bors
added a commit
that referenced
this issue
Apr 13, 2015
bors
added a commit
that referenced
this issue
Apr 14, 2015
bors
added a commit
that referenced
this issue
Apr 14, 2015
This comment has been minimized.
This comment has been minimized.
|
From a pragmatic perspective, I like the idea of |
bors
added a commit
that referenced
this issue
Apr 14, 2015
carllerche
referenced this issue
Apr 15, 2015
Closed
`Future::spawn` should not require `'static` #3
This comment has been minimized.
This comment has been minimized.
|
This doesn't seem like innate unsoundness so much as a way to turn one form of unsoundness (the ability to cause a leak) into a worse form of unsoundness (the ability to cause a crash). Have there been any previous efforts to eliminate the uncollectability of reference cycles? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@joshtriplett raw memory leaks explicitly do not qualify as unsound, or at least, "unsafe", under Rust's use of the term, as explicitly discussed here: http://doc.rust-lang.org/1.0.0-beta/reference.html#behaviour-not-considered-unsafe There is further detailed discussion on an internals thread here: http://internals.rust-lang.org/t/are-memory-leaks-considered-to-violate-memory-safety/1674 I point this out merely to establish that is not a gradient; it is a firm boolean condition, marking a line beyond which one risks undefined behavior. In any case, a garbage collector is part of our future goals for Rust. That, when used, will allow cycles using |
This comment has been minimized.
This comment has been minimized.
theemathas
commented
Apr 15, 2015
|
@reem and @nikomatsakis proposed different solutions for solving this on IRC @reem's solution: make @nikomatsakis's solution: create a new |
This comment has been minimized.
This comment has been minimized.
|
I changed my mind about the "make |
theemathas
referenced this issue
Apr 15, 2015
Closed
`mem::forget` is unsafe, but can be written in entirely safe code #24456
This comment has been minimized.
This comment has been minimized.
|
Note that a hypothetical |
This comment has been minimized.
This comment has been minimized.
|
@reem (well there might be some other bound we come up with in the future that is more flexible than |
This comment has been minimized.
This comment has been minimized.
|
Well making I think we do want to introduce |
This comment has been minimized.
This comment has been minimized.
|
After thinking about this for a bit, I think that dealing with
Each of these can definitely be classified as a bug in its own right, but it goes to show that a targeted solution at |
This comment has been minimized.
This comment has been minimized.
|
Yeah I'm a bit confused that std::thread::JoinGuard is getting the blame here. It seems to me that the real problem is that Rc+RefCell enables writing mem::forget in safe code: fn safe_forget<T>(data: T) {
use std::rc::Rc;
use std::cell::RefCell;
struct Leak<T> {
cycle: RefCell<Option<Rc<Rc<Leak<T>>>>>,
data: T,
}
let e = Rc::new(Leak {
cycle: RefCell::new(None),
data: data,
});
*e.cycle.borrow_mut() = Some(Rc::new(e.clone())); // Create a cycle
}
fn main() {
struct Foo<'a>(&'a mut i32);
impl<'a> Drop for Foo<'a> {
fn drop(&mut self) {
*self.0 += 1;
}
}
let mut data = 0;
{
let foo = Foo(&mut data);
safe_forget(foo);
}
data += 1; // super make sure there's no outstanding borrows
println!("{:?}", data); // prints 1, should print 2
}
Planned features like |
This comment has been minimized.
This comment has been minimized.
|
@RalfJung with |
This comment has been minimized.
This comment has been minimized.
SirVer
commented
Aug 17, 2015
|
The |
This comment has been minimized.
This comment has been minimized.
nicola-gigante
commented
Sep 5, 2015
|
Hi all. |
This comment has been minimized.
This comment has been minimized.
|
The API is coming back, so this is mostly a temporary state. |
This comment has been minimized.
This comment has been minimized.
nicola-gigante
commented
Sep 5, 2015
|
Interesting! Can you point me to the place (if any) where people are discussing how to safely implement it? |
This comment has been minimized.
This comment has been minimized.
|
I can't find it right now, but there already were some working scoped threads designs posted on the RfC. Not sure what the timeline for bringing this back is. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Crate crossbeam implements scoped threads. |
huonw
added a commit
to huonw/simple_parallel
that referenced
this issue
Oct 11, 2015
This comment has been minimized.
This comment has been minimized.
Guys, do you realise how ridiculous this looks? Let's see: "Hi, I read about this amazing scoped threads feature in Rust, but... I can't actually find it? What's the deal?" "Oh, that... The thing is... [wiggle squirm] We actually dropped it like half a year ago... But it's just temporary! We have ideas for a replacement! In fact, if you spend half a day wading through discussions on issues and pull requests, perhaps you will ultimately stumble upon a crate far away called Crossbeam that indeed implements a viable replacement, stuffed in along with various other experimental features... And surely something along these lines will someday somehow end up in the standard library again in some form (even though nothing actually seems to be happening regarding that right now)... So you see, it's all temporary! No need to even mention it in existing literature!" "Riiiiiight.... [slowly backing away] You know, I think I'll actually look for some other language... But you kids keep having fun!" |
This comment has been minimized.
This comment has been minimized.
|
You don't need crossbeam. This is an old thread, the state of scoped threads has moved past this since then. https://crates.io/crates/scoped_threadpool gives you the functionality. That's it. It's in an external crate which works and is sound, there's no pressing need to include it in the standard library. |
This comment has been minimized.
This comment has been minimized.
|
@antrik please try to be a bit more substantial and less sarcastic with your criticism. This kind of comment isn't particularly welcome here. |
This comment has been minimized.
This comment has been minimized.
Pools are nice; yet crossbeam::Scope seems a more straightforward replacement for the old functionality?... Anyway, debating this actually serves to demonstrate the existing confusion and lack of communication regarding this situation; creating an unacceptable story for any newcomer. thread::scoped() is prominently featured in a major piece of Rust advocacy (the mentioned blog post), without any hint that it's gone, or where to look for replacements; nor am I aware of any other clear communication regarding this, that people looking for thread::scoped() are likely to find -- and nobody seems to be willing to even acknowledge that there is a communication problem... If my post wasn't substantial in illustrating how this feels to people outside the bubble, I really don't know what would be. |
This comment has been minimized.
This comment has been minimized.
|
Sure, that's a straightforward thing to propose. You could have just done that. Your initial comment didn't complain about the communication error, it just ranted unconstructively without anything really helpful. @alexcrichton could you update the blog post with a note about scoped threads being moved out of the standard library to scoped_threadpool and Crossbeam? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Thanks. I was frustrated that the last person who suggested updating the post was brushed off, so I tried to illustrate why this is serious problem... Sorry that I failed to make my motivation clear. Note though that updating this blog post only solves part of the problem. The Why Rust? "report" for example only vaguely hints at changes; and there might be other mentions out there as well -- so it would be helpful to have some kind of "landing page" for people looking for thread::scoped(). (Ideally right in the standard library documentation where it used to live -- though I guess that might be technically impossible after it has been dropped for good?...) |
This comment has been minimized.
This comment has been minimized.
|
We could add a dummy documentation page or something. Or just add a note in the thread module. Not sure what to do in this case, @steveklabnik As for Why Rust I think the author was informed about this later, not sure if he changed anything. |
This comment has been minimized.
This comment has been minimized.
|
I'm not aware of anyone being brushed off, but I think editing the post is a great idea. Merged. I wouldn't be a fan of adding dummy doc pages. Sent from my iPhone
|
This comment has been minimized.
This comment has been minimized.
|
I'll update the Why Rust? report. (I used both scoped_threadpool and crossbeam::scope in my presentation at OSCON Amsterdam last week; they're great.) (In the future, please feel free to contact me directly about these things, rather than just mention me obliquely!) |
arielb1 commentedApr 10, 2015
You can use a reference cycle to leak a
JoinGuardand then the scoped thread can access freed memory: