Conversation
|
An interesting comment I found in // Note that we **do not** run these tests here. The windows builders get super
// unhappy if a thread outlives the main thread and then exits at the same time
// (something deadlocks) so we just avoid this entirely by not running these
// tests.
/// ```no_run
/// use std::sync::Arc;
/// use std::thread;
///
/// let five = Arc::new(5);
///
/// for _ in 0..10 {
/// let five = Arc::clone(&five);
///
/// thread::spawn(move || {
/// println!("{:?}", five);
/// });
/// }
/// ```
|
src/libstd/thread/mod.rs
Outdated
| /// [`Clone`]: ../../std/clone/trait.Clone.html | ||
| /// [`thread::spawn`]: fn.spawn.html | ||
| /// [`thread::Builder::spawn`]: struct.Builder.html#method.spawn | ||
| #[must_use] |
There was a problem hiding this comment.
It might be a good idea to add a short message, describing the reason for must_use, like
#[must_use = "it is better to explicitly join the spawned thread, otherwise it might be terminated abruptly, without running destructors"]
| //! When the main thread of a Rust program terminates, the entire program shuts | ||
| //! down, even if other threads are still running. However, this module provides | ||
| //! convenient facilities for automatically waiting for the termination of a | ||
| //! child thread (i.e., join). |
There was a problem hiding this comment.
Written in 2014. I wish it were still true.
|
Highfive failed to assign a reviewer, @Kimundi? |
|
I think we might want to cc @rust-lang/libs here: there will be a lot of warnings because of this, so it's better to discuss this at the team level just in case I think? |
|
Yeah, this seems like it might have a lot of impact. |
|
Thanks for the PR @stjepang! I'd personally think, however, that we would not want to do this. I think it's a laudable effort to encourage authors to think about shutdown and how to join threads, but there's a few reasons that I think we won't want to take this strategy:
I wonder though if there's perhaps another route we can take for warning about this? Not much comes to mind though :( |
|
I'd say the key issue here is that Maybe we don't need to "fix" let guard = thread::guarded(move || {
// ...
});
// Join the thread.
// Panics if the thread ended with a panic.
drop(guard);Also, I find the fact that the documentation says the following amusing: //! When the main thread of a Rust program terminates, the entire program shuts
//! down, even if other threads are still running. However, this module provides
//! convenient facilities for automatically waiting for the termination of a
//! child thread (i.e., join).
We're being warned than daemonized threads will not be cleanly shut down, but fret not - we're covered by convenient facilities for automatic joining. Except that's a lie - there is nothing automatic about calling |
|
Having an alternative seems plausible to me! |
|
☔ The latest upstream changes (presumably #48691) made this pull request unmergeable. Please resolve the merge conflicts. |
|
Where does this PR stand? Should it be closed in favor of a new API addition like the proposed |
Well, now you gotta talk about it at your meeting, so there 😝 |
|
Ping from triage @rust-lang/libs! What's the decision on this? |
|
We'll have triage this wednesday and I'll make sure we discuss it there |
|
We discussed this in triage and like the approach of a separate function which has a |
|
Isn’t |
|
Mostly but not entirely! In this case, code like thread::spawn_attached(|| do_expensive_work());Is totally broken - we're presumably doing this work in a separate thread because we want to do other stuff while it's running, but the handle is going to join when it's dropped immediately. |
|
If I understood this correctly the PR needs to change? Marking as waiting on author @stjepang. |
|
Let's close this PR since it's definitely not the direction we're going to take. The alternative is to add a new function for spawning threads that returns a join-on-drop guard. |
|
|
This PR adds a
#[must_use]attribute toJoinHandle.The change may introduce a considerable number of warnings in the Rust code, but that's a good thing! Note that warnings are still easy to get around by writing
let _ = std::thread::spawn(...), but at least they make the user think twice about forgetting to join the thread.Generally speaking, spawning a thread with no intention of ever joining should be discouraged since it may lead to very subtle bugs. See #48820 for an explanation.
Closes #48820
cc @matklad