-
Notifications
You must be signed in to change notification settings - Fork 13k
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
std::thread::JoinHandle should be marked with #[must_use] #48820
Comments
Mea culpa! I'd say it's even worse, because that was deliberate decision not to join the thread on my part :( I wonder if It's also not clear how to deal with panics: if you explicitly call |
It's okay, I'm blaming the compiler for not showing any warnings. :)
Probably. There was a thread on this topic in Rust Internals: https://internals.rust-lang.org/t/scoped-threads-in-the-nursery-maybe-with-rayon/4942 The thing is, we have a very diverse set of options for managing threads: tokio/futures, rayon, crossbeam, various thread pool crates,
I agree, perhaps we should revive |
It was decided that |
Nope. Closing! |
ARGHHHHH!!!!! This actually just caught me in some code I'm working on; I have a separate logging thread whose only job is to listen to a channel, and log the incoming contents. Since there are a large number of producers and only one consumer, it made sense to me to use an unbounded channel and join the logging thread at the very end. Unfortunately, something in the standard library has decided to not join, and in some cases my output logs are corrupted. Forcing something better would make life much easier... |
Here's a problem that caught my attention after reading @matklad's blog post titled Stopping a Rust worker. While the presented thread stopping mechanism is indeed very nice and convenient, I think a serious flaw is being overlooked: the spawned thread is never joined.
I've also noticed that spawning threads without ever joining has become a common pattern in Rust code. As a good example, take a peek at IndraDB's codebase.
Seeing something like the following should give everyone a pause and make them think twice:
Not only this thread is not joined, but the
JoinHandle
returned bythread::spawn
is completely ignored. This is a pattern that should be discouraged.So what's all the fuss about - why is not joining dangerous? Consider this:
At the end of the main function, the channel is closed and the worker thread is signalled that no more messages will be sent. This automatically breaks the loop, which is nice.
However, the thread will not have enough time to actually take notice and drop all its variables. Instead, the thread is abruptly killed. That means it doesn't have a chance to do any kind of final cleanup work, like flushing buffers to disk, closing files, deallocating memory, or anything like that.
Even worse - the exit code is 0, Rust doesn't give any warnings, and everything looks good, while it really isn't!
I believe we should mark
JoinHandle
with#[must_use]
. And if the user really doesn't want to join the thread (which should be very rare), they should acknowledge the possibility of the thread silently getting killed and writelet _handle = thread::spawn(...)
instead.The text was updated successfully, but these errors were encountered: