Skip to content

Conversation

@joboet
Copy link
Member

@joboet joboet commented Nov 8, 2025

Under the hopefully reasonable assumption that std's code is bug-free, all of the mutexes switched here will never be poisoned. The only poisoning mutex left is the one used for output capturing, as that has subtle effects on what gets captured.

@rustbot
Copy link
Collaborator

rustbot commented Nov 8, 2025

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

@rustbot rustbot added O-unix Operating system: Unix-like 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 Nov 8, 2025
Comment on lines +438 to +445
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl UnwindSafe for Stdin {}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl RefUnwindSafe for Stdin {}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manual implementation is necessary to avoid a situation like #146087.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe stick that in a comment?

@rust-log-analyzer

This comment has been minimized.

@joboet joboet force-pushed the nonpoison-mutex-everywhere branch from c5f4eac to 77d3da4 Compare November 8, 2025 12:48
@rust-log-analyzer

This comment has been minimized.

@joboet joboet force-pushed the nonpoison-mutex-everywhere branch from 77d3da4 to d75cc3b Compare November 8, 2025 14:40
@bjorn3
Copy link
Member

bjorn3 commented Nov 8, 2025

If a panic happens anyway, do all these cases preserve correct internal state? If not, then we should actually keep propagating the panic through poisoning IMO.

@Mark-Simulacrum
Copy link
Member

Maybe worth starting with the ones that we always unwrap_or_else(|e| e.into_inner()) on anyway? That seems easy to land.

I think for the ones that we sometimes just unwrap() on I'd lean towards keeping poisoning for the same reason outlined by @bjorn3 -- I'm not that convinced we lack bugs, and it seems like a cheap (good!) defense against those.

@Mark-Simulacrum Mark-Simulacrum added I-libs-nominated Nominated for discussion during a libs team meeting. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 9, 2025
@joboet
Copy link
Member Author

joboet commented Nov 9, 2025

If a panic happens anyway, do all these cases preserve correct internal state? If not, then we should actually keep propagating the panic through poisoning IMO.

They do.

I think for the ones that we sometimes just unwrap() on I'd lean towards keeping poisoning for the same reason outlined by @bjorn3 -- I'm not that convinced we lack bugs, and it seems like a cheap (good!) defense against those.

I think it's important to keep in mind that such bugs would still result in a panic, and would hence need to corrupt the internal state in a way that leads to unsoundness before this would make a meaningful difference.

@bjorn3
Copy link
Member

bjorn3 commented Nov 9, 2025

I think it's important to keep in mind that such bugs would still result in a panic

Only on the thread where the buggy method was called. If this thread is never joined, without poisoning the panic will never propagate to any other threads.

@joboet
Copy link
Member Author

joboet commented Nov 9, 2025

I'd like to point out that T-libs-api wants to switch std::sync::Mutex to the non-poisoning variant at some point. I'd be very confused if std set such a public standard, but then didn't follow it internally. So while I am personally of the opinion that poisoning is far too cautious and rarely helpful, I think your pushback here illustrates the need for a larger discussion on std's policy.

@rustbot label +I-libs-api-nominated

@rustbot rustbot added the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Nov 9, 2025
@Mark-Simulacrum
Copy link
Member

I'd be very confused if std set such a public standard, but then didn't follow it internally.

I think the default matters (and non-poison is probably the right default). But I'm not sure that means std can't use poisoned Mutexes anywhere -- that seems like a strange position to take. In ~95% of cases I'd tend to agree that they don't add value, but sometimes they do, and then we should aim to use them :)

@joboet
Copy link
Member Author

joboet commented Nov 9, 2025

I'd be very confused if std set such a public standard, but then didn't follow it internally.

I think the default matters (and non-poison is probably the right default). But I'm not sure that means std can't use poisoned Mutexes anywhere -- that seems like a strange position to take. In ~95% of cases I'd tend to agree that they don't add value, but sometimes they do, and then we should aim to use them :)

I fully agree – I just think that they don't add value in any of the cases here.

@joboet joboet removed the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Nov 9, 2025
@Amanieu Amanieu removed the I-libs-nominated Nominated for discussion during a libs team meeting. label Nov 19, 2025
@Amanieu
Copy link
Member

Amanieu commented Nov 19, 2025

This was discussed in the @rust-lang/libs meeting last week and we were overall happy with this change. Poisoning doesn't bring much value to the standard library since we are careful to maintain invariants when we may panic while holding a lock.

@hawkw
Copy link
Contributor

hawkw commented Nov 27, 2025

This was discussed in the @rust-lang/libs meeting last week and we were overall happy with this change. Poisoning doesn't bring much value to the standard library since we are careful to maintain invariants when we may panic while holding a lock.

I, too, would simply choose to only ever write correct code.

@joboet joboet added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 28, 2025
@bors
Copy link
Collaborator

bors commented Nov 29, 2025

☔ The latest upstream changes (presumably #144465) made this pull request unmergeable. Please resolve the merge conflicts.

@opeik
Copy link

opeik commented Dec 3, 2025

This was discussed in the @rust-lang/libs meeting last week and we were overall happy with this change. Poisoning doesn't bring much value to the standard library since we are careful to maintain invariants when we may panic while holding a lock.

This statement feels antithetical to Rust's design philosophy.

@slanterns
Copy link
Contributor

It's somewhat like how std uses some unsafe code to improve performance. If carefully checked I don't think it will be a big problem.

@the8472
Copy link
Member

the8472 commented Dec 3, 2025

#134645 (comment) provides some context

@Mark-Simulacrum
Copy link
Member

I fully agree – I just think that they don't add value in any of the cases here.

Can you say more about how you performed the audit in question? I think it would be easier for me to approve this PR (though I won't stop someone else on libs doing so) if we had some form of 'proof' here for said audit. For example:

  • All lock() call sites already bypass poisoning
  • We've confirmed that the state inside the mutex can't be contaminated during the critical section (e.g., mutex is not really used for more than ~one method call on the inner state, and said method is atomic in a single threaded sense in its operation)

As-is just flipping the imports makes that especially hard to review because I can't even see the individual Mutexes without digging into the code.

There are definitely lock().unwrap() calls that have become lock(), i.e., we've removed panics in this PR (e.g., in mpmc waker code, which is the second page of changes in the diff). The code within those is fairly complex and I'm pretty sure can panic (e.g., there's calls to getting the thread ID which I'd expect panic in edge cases). I haven't audited deeply myself to say whether there's anything truly problematic -- but this seems like it exposes a class of problem that used to be 'panics led to more panics' and now is maybe 'panics lead to ~deadlocks' (depending on what exactly the impl does on panic), which seems worse to me.

I think the overall goal of saying that the standard library shouldn't care about poisoning because it's "correct" and doesn't panic except on bad ~programmer input and those panics don't poison data structures is nice, but I'm not convinced that's actually empirically the case today. I'd guess that in 99% (maybe 100%) of the cases we don't have any unsoundness as a result of landing this, just bad behavior (e.g., the deadlocks I suggested above). But that also seems non-great.

If this moved all Mutexes to nonpoison::Mutex<Poison<T>>, then I'd happily r+ it.

@tbu-
Copy link
Contributor

tbu- commented Dec 10, 2025

Under the hopefully reasonable assumption that std's code is bug-free, all of the mutexes switched here will never be poisoned.

"Under the hopefully reasonable assumption that std's code is bug-free, all of the slice bounds check panics will never be triggered. Hence, I'm removing the bounds checks as they have a runtime cost."

Wait what? That's not what I want Rust to do.

I'd assume that the standard library would only remove dynamic safety checks if they were found to be performance related…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

O-unix Operating system: Unix-like 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.