@@ -16,7 +16,7 @@ use crate::pipes::pipe;
1616use :: {
1717 nix:: sys:: select:: FdSet ,
1818 nix:: sys:: select:: select,
19- nix:: sys:: signal:: { self , signal } ,
19+ nix:: sys:: signal:: { SaFlags , SigAction , SigHandler , SigSet , sigaction } ,
2020 nix:: sys:: time:: TimeVal ,
2121 std:: fs:: File ,
2222 std:: io:: { Read , Write } ,
@@ -126,19 +126,19 @@ pub trait ChildExt {
126126}
127127
128128#[ cfg( feature = "pipes" ) ]
129- pub struct SelfPipe ( File , Option < Signal > , PhantomData < * mut ( ) > ) ;
129+ pub struct SelfPipe ( File , SigSet , PhantomData < * mut ( ) > ) ;
130130
131131#[ cfg( feature = "pipes" ) ]
132132pub trait CommandExt {
133- fn set_up_timeout ( & mut self , other : Option < Signal > ) -> io:: Result < SelfPipe > ;
133+ fn set_up_timeout ( & mut self , others : SigSet ) -> io:: Result < SelfPipe > ;
134134}
135135
136136/// Concise enum of [`ChildExt::wait_or_timeout`] possible returns.
137137#[ derive( Debug ) ]
138138#[ cfg( feature = "pipes" ) ]
139139pub enum WaitOrTimeoutRet {
140140 InTime ( ExitStatus ) ,
141- CustomSignaled ,
141+ CustomSignaled ( i32 ) ,
142142 TimedOut ,
143143}
144144
@@ -197,24 +197,24 @@ impl ChildExt for Child {
197197 // if empty, we'd stall on the read. However, this may
198198 // happen spuriously, so we try to select again.
199199 if fd_set. contains ( self_pipe. 0 . as_fd ( ) ) {
200- let mut buf = [ 0 ] ;
200+ let mut buf = [ 0 ; std :: mem :: size_of :: < Signal > ( ) ] ;
201201 self_pipe. 0 . read_exact ( & mut buf) ?;
202- return match buf[ 0 ] {
202+ let sig = i32:: from_ne_bytes ( buf) ;
203+ return match sig {
203204 // SIGCHLD
204- 1 => match self . try_wait ( ) ? {
205+ libc :: SIGCHLD => match self . try_wait ( ) ? {
205206 Some ( e) => Ok ( WaitOrTimeoutRet :: InTime ( e) ) ,
206207 None => Ok ( WaitOrTimeoutRet :: InTime ( ExitStatus :: default ( ) ) ) ,
207208 } ,
208209 // Received SIGALRM externally, for compat with
209210 // GNU timeout we act as if it had timed out.
210- 2 => Ok ( WaitOrTimeoutRet :: TimedOut ) ,
211+ libc :: SIGALRM => Ok ( WaitOrTimeoutRet :: TimedOut ) ,
211212 // Custom signals on zero timeout still succeed.
212- 3 if timeout. is_zero ( ) => {
213+ _ if timeout. is_zero ( ) => {
213214 Ok ( WaitOrTimeoutRet :: InTime ( ExitStatus :: default ( ) ) )
214215 }
215216 // We received a custom signal and fail.
216- 3 => Ok ( WaitOrTimeoutRet :: CustomSignaled ) ,
217- _ => unreachable ! ( ) ,
217+ x => Ok ( WaitOrTimeoutRet :: CustomSignaled ( x) ) ,
218218 } ;
219219 }
220220 }
@@ -250,7 +250,7 @@ fn duration_to_timeval_elapsed(time: Duration, start: Instant) -> Option<TimeVal
250250
251251#[ cfg( feature = "pipes" ) ]
252252impl CommandExt for Command {
253- fn set_up_timeout ( & mut self , other : Option < Signal > ) -> io:: Result < SelfPipe > {
253+ fn set_up_timeout ( & mut self , others : SigSet ) -> io:: Result < SelfPipe > {
254254 static SELF_PIPE_W : Mutex < Option < File > > = Mutex :: new ( None ) ;
255255 let ( r, w) = pipe ( ) ?;
256256 * SELF_PIPE_W . lock ( ) . unwrap ( ) = Some ( w) ;
@@ -259,31 +259,33 @@ impl CommandExt for Command {
259259 let Ok ( & mut Some ( ref mut writer) ) = lock. as_deref_mut ( ) else {
260260 return ;
261261 } ;
262- if signal == Signal :: SIGCHLD as c_int {
263- let _ = writer. write ( & [ 1 ] ) ;
264- } else if signal == Signal :: SIGALRM as c_int {
265- let _ = writer. write ( & [ 2 ] ) ;
266- } else {
267- let _ = writer. write ( & [ 3 ] ) ;
268- }
262+ let _ = writer. write ( & signal. to_ne_bytes ( ) ) ;
269263 }
264+ let action = SigAction :: new (
265+ SigHandler :: Handler ( sig_handler) ,
266+ SaFlags :: SA_NOCLDSTOP ,
267+ SigSet :: all ( ) ,
268+ ) ;
270269 unsafe {
271- signal ( Signal :: SIGCHLD , signal :: SigHandler :: Handler ( sig_handler ) ) ?;
272- signal ( Signal :: SIGALRM , signal :: SigHandler :: Handler ( sig_handler ) ) ?;
273- if let Some ( other ) = other {
274- signal ( other , signal :: SigHandler :: Handler ( sig_handler ) ) ?;
270+ sigaction ( Signal :: SIGCHLD , & action ) ?;
271+ sigaction ( Signal :: SIGALRM , & action ) ?;
272+ for signal in & others {
273+ sigaction ( signal , & action ) ?;
275274 }
276275 } ;
277- Ok ( SelfPipe ( r, other , PhantomData ) )
276+ Ok ( SelfPipe ( r, others , PhantomData ) )
278277 }
279278}
280279
281280#[ cfg( feature = "pipes" ) ]
282281impl SelfPipe {
283- pub fn unset_other ( & self ) -> io:: Result < ( ) > {
284- if let Some ( other ) = self . 1 {
282+ pub fn unset_other ( & self , signal : Signal ) -> io:: Result < ( ) > {
283+ if self . 1 . contains ( signal ) {
285284 unsafe {
286- signal ( other, signal:: SigHandler :: SigDfl ) ?;
285+ sigaction (
286+ signal,
287+ & SigAction :: new ( SigHandler :: SigDfl , SaFlags :: empty ( ) , SigSet :: empty ( ) ) ,
288+ ) ?;
287289 }
288290 }
289291 Ok ( ( ) )
@@ -293,8 +295,11 @@ impl SelfPipe {
293295#[ cfg( feature = "pipes" ) ]
294296impl Drop for SelfPipe {
295297 fn drop ( & mut self ) {
296- let _ = unsafe { signal ( Signal :: SIGCHLD , signal:: SigHandler :: SigDfl ) } ;
297- let _ = self . unset_other ( ) ;
298+ let action = SigAction :: new ( SigHandler :: SigDfl , SaFlags :: empty ( ) , SigSet :: empty ( ) ) ;
299+ let _ = unsafe { sigaction ( Signal :: SIGCHLD , & action) } ;
300+ for signal in & self . 1 {
301+ let _ = unsafe { sigaction ( signal, & action) } ;
302+ }
298303 }
299304}
300305
0 commit comments