@@ -15,6 +15,7 @@ use crate::panic::{RefUnwindSafe, UnwindSafe};
1515use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
1616use crate :: sync:: { Arc , Mutex , MutexGuard , OnceLock , ReentrantLock , ReentrantLockGuard } ;
1717use crate :: sys:: stdio;
18+ use crate :: thread:: AccessError ;
1819
1920type LocalStream = Arc < Mutex < Vec < u8 > > > ;
2021
@@ -1054,12 +1055,31 @@ impl fmt::Debug for StderrLock<'_> {
10541055) ]
10551056#[ doc( hidden) ]
10561057pub fn set_output_capture ( sink : Option < LocalStream > ) -> Option < LocalStream > {
1058+ try_set_output_capture ( sink) . expect (
1059+ "cannot access a Thread Local Storage value \
1060+ during or after destruction",
1061+ )
1062+ }
1063+
1064+ /// Tries to set the thread-local output capture buffer and returns the old one.
1065+ /// This may fail once thread-local destructors are called. It's used in panic
1066+ /// handling instead of `set_output_capture`.
1067+ #[ unstable(
1068+ feature = "internal_output_capture" ,
1069+ reason = "this function is meant for use in the test crate \
1070+ and may disappear in the future",
1071+ issue = "none"
1072+ ) ]
1073+ #[ doc( hidden) ]
1074+ pub fn try_set_output_capture (
1075+ sink : Option < LocalStream > ,
1076+ ) -> Result < Option < LocalStream > , AccessError > {
10571077 if sink. is_none ( ) && !OUTPUT_CAPTURE_USED . load ( Ordering :: Relaxed ) {
10581078 // OUTPUT_CAPTURE is definitely None since OUTPUT_CAPTURE_USED is false.
1059- return None ;
1079+ return Ok ( None ) ;
10601080 }
10611081 OUTPUT_CAPTURE_USED . store ( true , Ordering :: Relaxed ) ;
1062- OUTPUT_CAPTURE . with ( move |slot| slot. replace ( sink) )
1082+ OUTPUT_CAPTURE . try_with ( move |slot| slot. replace ( sink) )
10631083}
10641084
10651085/// Write `args` to the capture buffer if enabled and possible, or `global_s`
0 commit comments