Skip to content

Document that destructors in running threads are not run on program exit#156788

Open
jwodder wants to merge 1 commit into
rust-lang:mainfrom
jwodder:thread-shutdown
Open

Document that destructors in running threads are not run on program exit#156788
jwodder wants to merge 1 commit into
rust-lang:mainfrom
jwodder:thread-shutdown

Conversation

@jwodder

@jwodder jwodder commented May 20, 2026

Copy link
Copy Markdown

It's my understanding that, when a Rust program's main thread terminates and thereby causes any still-running threads to be shut down, destructors are not run for the shut-down threads; however, the documentation doesn't seem to come out and say that explicitly anywhere. This PR therefore adds an explicit statement about this to the std::thread docs.

If I am mistaken and destructors are run, that's worth documenting explicitly, too.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels May 20, 2026
@rustbot

rustbot commented May 20, 2026

Copy link
Copy Markdown
Collaborator

r? @Mark-Simulacrum

rustbot has assigned @Mark-Simulacrum.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ChrisDenton, libs
  • @ChrisDenton, libs expanded to 8 candidates

@clarfonthey clarfonthey added T-lang Relevant to the language team and removed T-libs Relevant to the library team, which will review and decide on the PR/issue. labels May 24, 2026
@clarfonthey

Copy link
Copy Markdown
Contributor

r? lang

Since this feels like more a lang decision than a libs decision. I also believe this is the case currently, but don't know if we have any other documentation that's relevant here, and whether this is desired as a guarantee.

@rustbot rustbot assigned scottmcm and unassigned Mark-Simulacrum May 24, 2026
@scottmcm scottmcm added the I-lang-nominated Nominated for discussion during a lang team meeting. label Jun 13, 2026
@traviscross traviscross added the P-lang-drag-2 Lang team prioritization drag level 2.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. label Jun 17, 2026
Comment thread library/std/src/thread/mod.rs Outdated
@traviscross

Copy link
Copy Markdown
Contributor

We talked about this in the lang call. We wanted to change the text to say "may", as @joshtriplett has now left a review comment about. After that's updated, one of us will r+ it.

@jwodder

jwodder commented Jun 17, 2026

Copy link
Copy Markdown
Author

@traviscross I've applied Josh's suggested wording change.

@traviscross

Copy link
Copy Markdown
Contributor

Please squash.

Co-authored-by: Josh Triplett <josh@joshtriplett.org>
@traviscross traviscross assigned traviscross and unassigned scottmcm Jun 17, 2026
@traviscross traviscross added I-lang-radar Items that are on lang's radar and will need eventual work or consideration. and removed I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-2 Lang team prioritization drag level 2.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. labels Jun 17, 2026
@jwodder

jwodder commented Jun 17, 2026

Copy link
Copy Markdown
Author

@traviscross Squashed.

@traviscross

Copy link
Copy Markdown
Contributor

@bors r+ rollup

@rust-bors

rust-bors Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 8410d26 has been approved by traviscross

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 17, 2026
@traviscross

Copy link
Copy Markdown
Contributor

Thanks @jwodder.

@steffahn

steffahn commented Jun 17, 2026

Copy link
Copy Markdown
Member

Actually, this behavior is already documented elsewhere (mentioning this not as an argument against documenting it here, too, but to ensure consistency):

In the documentation of std::process::exit:

Note that because this function never returns, and that it terminates the process, no destructors on the current stack or any other thread’s stack will be run.

and later

Note that returning from main also calls exit, […]

and one more time even further below

Note that returning from main is equivalent to calling exit

@jwodder

jwodder commented Jun 17, 2026

Copy link
Copy Markdown
Author

Actually, this behavior is already documented elsewhere (mentioning this not as an argument against documenting it here, too, but to ensure consistency):

In the documentation of std::process::exit:

Note that because this function never returns, and that it terminates the process, no destructors on the current stack or any other thread’s stack will be run.

and later

Note that returning from main also calls exit, […]

and one more time even further below

Note that returning from main is equivalent to calling exit

That last line is a bit too buried for my liking, and the "returning from main also calls exit" bit doesn't preclude the existence of other code being run between the return and the exit().

@steffahn

steffahn commented Jun 17, 2026

Copy link
Copy Markdown
Member

I wonder if it would be sufficient to instead just turn "shuts down" into a link to make the connection clear? This would also avoid the need for duplicate documentation of this detail.

(Idea for revised version:)
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 thread (i.e., join).


Additionally on that page, I see

If a clean shutdown is needed it is recommended to only call this function at a known point where there are no more destructors left to run; or, preferably, simply return […] from the main function and avoid this function altogether[…]

But the “preferable” way described there doesn’t actually ensure “no more destructors left to run” for you, in case there are other threads not being waited on; so maybe the std::process::exit page could benefit from a mention of threads…

(Idea for revised version:)
If a clean shutdown is needed it is recommended to only call this function at a known point where there are no more destructors left to run; or, preferably, simply return […] from the main function, ensure main doesn't forget, wait for any other threads you have spawned, and avoid this function altogether


That last line is a bit too buried for my liking

highlighting the “equivalent” phrasing too early could lead to misconceptions that they’re also equivalent for the purpose of handling local variables inside of main.

The ambiguity that could cause this comes from the fact that “returning from main” may be understood as “the thing that happens after main has finished and has ran all local destructors” or “all effects of “evaluating” a return expression in main” (which one could intuit does include the dropping of local variables).

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jun 17, 2026
…ross

Document that destructors in running threads are not run on program exit

It's my understanding that, when a Rust program's main thread terminates and thereby causes any still-running threads to be shut down, destructors are not run for the shut-down threads; however, the documentation doesn't seem to come out and say that explicitly anywhere.  This PR therefore adds an explicit statement about this to the `std::thread` docs.

If I am mistaken and destructors *are* run, that's worth documenting explicitly, too.
rust-bors Bot pushed a commit that referenced this pull request Jun 17, 2026
…uwer

Rollup of 6 pull requests

Successful merges:

 - #157816 (make more slice mutable ref getters rustc_no_writable)
 - #156788 (Document that destructors in running threads are not run on program exit)
 - #157957 (Add documentation for the `must_use` attribute)
 - #158006 (Simplify `HardwiredLints` and `SoftLints`)
 - #158007 (Pin dependencies)
 - #158025 (Enable `symbol_intern_string_literal` lint for rustdoc)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

I-lang-radar Items that are on lang's radar and will need eventual work or consideration. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-lang Relevant to the language team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants