@@ -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,24 @@ 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+ pub ( crate ) fn try_set_output_capture (
1068+ sink : Option < LocalStream > ,
1069+ ) -> Result < Option < LocalStream > , AccessError > {
10571070 if sink. is_none ( ) && !OUTPUT_CAPTURE_USED . load ( Ordering :: Relaxed ) {
10581071 // OUTPUT_CAPTURE is definitely None since OUTPUT_CAPTURE_USED is false.
1059- return None ;
1072+ return Ok ( None ) ;
10601073 }
10611074 OUTPUT_CAPTURE_USED . store ( true , Ordering :: Relaxed ) ;
1062- OUTPUT_CAPTURE . with ( move |slot| slot. replace ( sink) )
1075+ OUTPUT_CAPTURE . try_with ( move |slot| slot. replace ( sink) )
10631076}
10641077
10651078/// Write `args` to the capture buffer if enabled and possible, or `global_s`
0 commit comments