diff --git a/src/uu/timeout/locales/en-US.ftl b/src/uu/timeout/locales/en-US.ftl index 5456af3f98d..86eba3fa09e 100644 --- a/src/uu/timeout/locales/en-US.ftl +++ b/src/uu/timeout/locales/en-US.ftl @@ -22,6 +22,7 @@ timeout-after-help = Upon timeout, send the TERM signal to COMMAND, if no other # Error messages timeout-error-invalid-signal = { $signal }: invalid signal timeout-error-failed-to-execute-process = failed to execute process: { $error } +timeout-error-monitor-exited-before-child-exec = timeout monitor exited before child exec # Verbose messages timeout-verbose-sending-signal = sending signal { $signal } to command { $command } diff --git a/src/uu/timeout/locales/fr-FR.ftl b/src/uu/timeout/locales/fr-FR.ftl index c04b26e04f4..f1fce5e9bdc 100644 --- a/src/uu/timeout/locales/fr-FR.ftl +++ b/src/uu/timeout/locales/fr-FR.ftl @@ -22,6 +22,7 @@ timeout-after-help = À l'expiration du délai, le signal TERM est envoyé à CO # Messages d'erreur timeout-error-invalid-signal = { $signal } : signal invalide timeout-error-failed-to-execute-process = échec d'exécution du processus : { $error } +timeout-error-monitor-exited-before-child-exec = le processus de délai s'est terminé avant l'exécution du processus enfant # Messages détaillés timeout-verbose-sending-signal = envoi du signal { $signal } à la commande { $command } diff --git a/src/uu/timeout/src/timeout.rs b/src/uu/timeout/src/timeout.rs index 6944794f19c..841bdb111ab 100644 --- a/src/uu/timeout/src/timeout.rs +++ b/src/uu/timeout/src/timeout.rs @@ -3,13 +3,13 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (ToDO) tstr sigstr cmdname setpgid sigchld getpid +// spell-checker:ignore (ToDO) tstr sigstr cmdname setpgid sigchld getpid getppid mod status; use crate::status::ExitStatus; use clap::{Arg, ArgAction, Command}; -use std::io::{ErrorKind, Write}; +use std::io::{Error, ErrorKind, Write}; use std::os::unix::process::ExitStatusExt; use std::process::{self, Child, Stdio}; use std::sync::atomic::{self, AtomicBool}; @@ -26,7 +26,7 @@ use uucore::{ }; use nix::sys::signal::{SigHandler, Signal, kill}; -use nix::unistd::{Pid, getpid, setpgid}; +use nix::unistd::{Pid, getpid, getppid, setpgid}; #[cfg(unix)] use std::os::unix::process::CommandExt; @@ -380,6 +380,13 @@ fn timeout( if let Some(sig) = death_sig { let _ = nix::sys::prctl::set_pdeathsig(sig); } + // Close the post-fork race where the timeout monitor can die + // after PDEATHSIG setup but before exec starts the target command. + if getppid().as_raw() == 1 { + return Err(Error::other( + translate!("timeout-error-monitor-exited-before-child-exec"), + )); + } Ok(()) }); }