88mod imp {
99 use anyhow:: Result ;
1010 use nix:: unistd;
11- use std:: os:: fd:: { AsRawFd , FromRawFd , IntoRawFd , OwnedFd } ;
11+ use std:: os:: fd:: { AsRawFd , FromRawFd , OwnedFd } ;
1212 use std:: path:: Path ;
1313 use std:: sync:: { Mutex , MutexGuard } ;
1414
@@ -18,7 +18,7 @@ mod imp {
1818 static STDERR_LOCK : Mutex < ( ) > = Mutex :: new ( ( ) ) ;
1919
2020 pub struct Capture {
21- original_stderr : OwnedFd ,
21+ original_stderr : Option < OwnedFd > ,
2222 _guard : MutexGuard < ' static , ( ) > ,
2323 }
2424
@@ -27,23 +27,34 @@ mod imp {
2727 let guard = STDERR_LOCK
2828 . lock ( )
2929 . unwrap_or_else ( |poisoned| poisoned. into_inner ( ) ) ;
30- let capture_fd = std:: fs:: File :: create ( path) ?. into_raw_fd ( ) ;
31- let original_stderr_raw = unistd :: dup ( 2 ) ? ;
32- unistd:: dup2 ( capture_fd , 2 ) ? ;
33- unistd:: close ( capture_fd ) ?;
34- let original_stderr = unsafe { OwnedFd :: from_raw_fd ( original_stderr_raw ) } ;
30+ let capture_file = std:: fs:: File :: create ( path) ?;
31+ let original_stderr =
32+ OwnedFd :: from ( unistd:: dup ( 2 ) . map ( |fd| unsafe { OwnedFd :: from_raw_fd ( fd ) } ) ? ) ;
33+ unistd:: dup2 ( capture_file . as_raw_fd ( ) , 2 ) ?;
34+ // capture_file dropped here — its OwnedFd closes the fd via RAII
3535 Ok ( Self {
36- original_stderr,
36+ original_stderr : Some ( original_stderr ) ,
3737 _guard : guard,
3838 } )
3939 }
4040
4141 pub fn restore ( self ) -> Result < ( ) > {
42- unistd:: dup2 ( self . original_stderr . as_raw_fd ( ) , 2 ) ?;
43- // _guard is dropped here, releasing STDERR_LOCK
42+ if let Some ( ref fd) = self . original_stderr {
43+ unistd:: dup2 ( fd. as_raw_fd ( ) , 2 ) ?;
44+ }
45+ // Drop restores via Drop impl if restore() wasn't called,
46+ // but explicit call lets caller handle errors.
4447 Ok ( ( ) )
4548 }
4649 }
50+
51+ impl Drop for Capture {
52+ fn drop ( & mut self ) {
53+ if let Some ( ref fd) = self . original_stderr . take ( ) {
54+ let _ = unistd:: dup2 ( fd. as_raw_fd ( ) , 2 ) ;
55+ }
56+ }
57+ }
4758}
4859
4960#[ cfg( windows) ]
0 commit comments