diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-04-11 22:38:53 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-11 22:38:53 +0200 |
| commit | 1e99af514b68d0ff6891fa3cb6a9946c3888caef (patch) | |
| tree | 9a0e27ae2496b1dceefca827032c57c25ab763b9 /library/std/src/io/stdio.rs | |
| parent | aa6a697a1c75b0aa06954136f7641706edadc2be (diff) | |
| parent | c2e5ee40b699608128654f2b67e0fafa8e1ec8dc (diff) | |
| download | rust-1e99af514b68d0ff6891fa3cb6a9946c3888caef.tar.gz rust-1e99af514b68d0ff6891fa3cb6a9946c3888caef.zip | |
Rollup merge of #122882 - Zoxc:panic-output-panic, r=Amanieu
Avoid a panic in `set_output_capture` in the default panic handler This avoid a panic in the default panic handler by not using `set_output_capture` as `OUTPUT_CAPTURE.with` may panic once `OUTPUT_CAPTURE` is dropped. A new non-panicking `try_set_output_capture` variant of `set_output_capture` is added for use in the default panic handler.
Diffstat (limited to 'library/std/src/io/stdio.rs')
| -rw-r--r-- | library/std/src/io/stdio.rs | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 73fa7cbc3fe..07fa9259e0b 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -15,6 +15,7 @@ use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantLock, ReentrantLockGuard}; use crate::sys::stdio; +use crate::thread::AccessError; type LocalStream = Arc<Mutex<Vec<u8>>>; @@ -1064,12 +1065,31 @@ impl fmt::Debug for StderrLock<'_> { )] #[doc(hidden)] pub fn set_output_capture(sink: Option<LocalStream>) -> Option<LocalStream> { + try_set_output_capture(sink).expect( + "cannot access a Thread Local Storage value \ + during or after destruction", + ) +} + +/// Tries to set the thread-local output capture buffer and returns the old one. +/// This may fail once thread-local destructors are called. It's used in panic +/// handling instead of `set_output_capture`. +#[unstable( + feature = "internal_output_capture", + reason = "this function is meant for use in the test crate \ + and may disappear in the future", + issue = "none" +)] +#[doc(hidden)] +pub fn try_set_output_capture( + sink: Option<LocalStream>, +) -> Result<Option<LocalStream>, AccessError> { if sink.is_none() && !OUTPUT_CAPTURE_USED.load(Ordering::Relaxed) { // OUTPUT_CAPTURE is definitely None since OUTPUT_CAPTURE_USED is false. - return None; + return Ok(None); } OUTPUT_CAPTURE_USED.store(true, Ordering::Relaxed); - OUTPUT_CAPTURE.with(move |slot| slot.replace(sink)) + OUTPUT_CAPTURE.try_with(move |slot| slot.replace(sink)) } /// Write `args` to the capture buffer if enabled and possible, or `global_s` |
