Skip to content

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

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
jwodder:thread-shutdown
Jun 17, 2026
Merged

Document that destructors in running threads are not run on program exit#156788
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
jwodder:thread-shutdown

Conversation

@jwodder

@jwodder jwodder commented May 20, 2026

Copy link
Copy Markdown
Contributor

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
Contributor 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
Contributor 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
Contributor 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).

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)
@rust-bors rust-bors Bot merged commit 7c3eb23 into rust-lang:main Jun 17, 2026
13 checks passed
@rustbot rustbot added this to the 1.98.0 milestone Jun 17, 2026
rust-timer added a commit that referenced this pull request Jun 17, 2026
Rollup merge of #156788 - jwodder:thread-shutdown, r=traviscross

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.
@ChrisDenton

Copy link
Copy Markdown
Member

On std::process::exit, personally I would want to emphasise that returning from main is strongly preferred in just about all cases (and btw process::abort would be better in most cases it's not). This is a very niche function that made more sense before we were able to return errors from main. It has soundness issues and skipping even normal drops can be surprising (e.g. TempFile cleanup on drop).

And I'm not sure noting "equivalence" with process::exit and returning from main is particularly useful at all. Yes, the runtime (CRT or otherwise) may call something like exit as an implementation detail. But that's not actually useful information on its own because it says nothing about the behaviour when exiting from main (which will depend on the platform anyway).

@traviscross

This comment was marked as resolved.

pull Bot pushed a commit to xtqqczze/rust-lang-miri that referenced this pull request Jun 18, 2026
…uwer

Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#157816 (make more slice mutable ref getters rustc_no_writable)
 - rust-lang/rust#156788 (Document that destructors in running threads are not run on program exit)
 - rust-lang/rust#157957 (Add documentation for the `must_use` attribute)
 - rust-lang/rust#158006 (Simplify `HardwiredLints` and `SoftLints`)
 - rust-lang/rust#158007 (Pin dependencies)
 - rust-lang/rust#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.

9 participants