@@ -15,6 +15,7 @@ use crate::panic::{RefUnwindSafe, UnwindSafe};
15
15
use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
16
16
use crate :: sync:: { Arc , Mutex , MutexGuard , OnceLock , ReentrantLock , ReentrantLockGuard } ;
17
17
use crate :: sys:: stdio;
18
+ use crate :: thread:: AccessError ;
18
19
19
20
type LocalStream = Arc < Mutex < Vec < u8 > > > ;
20
21
@@ -1054,12 +1055,24 @@ impl fmt::Debug for StderrLock<'_> {
1054
1055
) ]
1055
1056
#[ doc( hidden) ]
1056
1057
pub 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 > {
1057
1070
if sink. is_none ( ) && !OUTPUT_CAPTURE_USED . load ( Ordering :: Relaxed ) {
1058
1071
// OUTPUT_CAPTURE is definitely None since OUTPUT_CAPTURE_USED is false.
1059
- return None ;
1072
+ return Ok ( None ) ;
1060
1073
}
1061
1074
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) )
1063
1076
}
1064
1077
1065
1078
/// Write `args` to the capture buffer if enabled and possible, or `global_s`
0 commit comments