Skip to content

Commit

Permalink
Unrolled build for rust-lang#122882
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#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.
  • Loading branch information
rust-timer committed Apr 12, 2024
2 parents 616a8f8 + c2e5ee4 commit 29aa707
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 9 deletions.
6 changes: 3 additions & 3 deletions library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,14 +311,14 @@ pub use self::buffered::WriterPanicked;
#[unstable(feature = "raw_os_error_ty", issue = "107792")]
pub use self::error::RawOsError;
pub(crate) use self::stdio::attempt_print_to_stderr;
#[unstable(feature = "internal_output_capture", issue = "none")]
#[doc(no_inline, hidden)]
pub use self::stdio::set_output_capture;
#[stable(feature = "is_terminal", since = "1.70.0")]
pub use self::stdio::IsTerminal;
#[unstable(feature = "print_internals", issue = "none")]
#[doc(hidden)]
pub use self::stdio::{_eprint, _print};
#[unstable(feature = "internal_output_capture", issue = "none")]
#[doc(no_inline, hidden)]
pub use self::stdio::{set_output_capture, try_set_output_capture};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::{
buffered::{BufReader, BufWriter, IntoInnerError, LineWriter},
Expand Down
24 changes: 22 additions & 2 deletions library/std/src/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>>;

Expand Down Expand Up @@ -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`
Expand Down
8 changes: 4 additions & 4 deletions library/std/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ use crate::sys_common::backtrace;
use crate::thread;

#[cfg(not(test))]
use crate::io::set_output_capture;
use crate::io::try_set_output_capture;
// make sure to use the stderr output configured
// by libtest in the real copy of std
#[cfg(test)]
use realstd::io::set_output_capture;
use realstd::io::try_set_output_capture;

// Binary interface to the panic runtime that the standard library depends on.
//
Expand Down Expand Up @@ -284,9 +284,9 @@ fn default_hook(info: &PanicInfo<'_>) {
}
};

if let Some(local) = set_output_capture(None) {
if let Ok(Some(local)) = try_set_output_capture(None) {
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()));
set_output_capture(Some(local));
try_set_output_capture(Some(local)).ok();
} else if let Some(mut out) = panic_output() {
write(&mut out);
}
Expand Down

0 comments on commit 29aa707

Please sign in to comment.