1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

timeout: support --verbose

This commit is contained in:
Michael Debertol 2021-06-10 18:34:05 +02:00
parent b0b937dc3e
commit 8e0ed2d20e
2 changed files with 37 additions and 1 deletions

View file

@ -17,7 +17,7 @@ use std::io::ErrorKind;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::time::Duration; use std::time::Duration;
use uucore::process::ChildExt; use uucore::process::ChildExt;
use uucore::signals::signal_by_name_or_value; use uucore::signals::{signal_by_name_or_value, signal_name_by_value};
use uucore::InvalidEncodingHandling; use uucore::InvalidEncodingHandling;
static ABOUT: &str = "Start COMMAND, and kill it if still running after DURATION."; static ABOUT: &str = "Start COMMAND, and kill it if still running after DURATION.";
@ -33,6 +33,7 @@ pub mod options {
pub static KILL_AFTER: &str = "kill-after"; pub static KILL_AFTER: &str = "kill-after";
pub static SIGNAL: &str = "signal"; pub static SIGNAL: &str = "signal";
pub static PRESERVE_STATUS: &str = "preserve-status"; pub static PRESERVE_STATUS: &str = "preserve-status";
pub static VERBOSE: &str = "verbose";
// Positional args. // Positional args.
pub static DURATION: &str = "duration"; pub static DURATION: &str = "duration";
@ -45,6 +46,7 @@ struct Config {
signal: usize, signal: usize,
duration: Duration, duration: Duration,
preserve_status: bool, preserve_status: bool,
verbose: bool,
command: Vec<String>, command: Vec<String>,
} }
@ -74,6 +76,7 @@ impl Config {
let preserve_status: bool = options.is_present(options::PRESERVE_STATUS); let preserve_status: bool = options.is_present(options::PRESERVE_STATUS);
let foreground = options.is_present(options::FOREGROUND); let foreground = options.is_present(options::FOREGROUND);
let verbose = options.is_present(options::VERBOSE);
let command = options let command = options
.values_of(options::COMMAND) .values_of(options::COMMAND)
@ -88,6 +91,7 @@ impl Config {
duration, duration,
preserve_status, preserve_status,
command, command,
verbose,
} }
} }
} }
@ -124,6 +128,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.help("specify the signal to be sent on timeout; SIGNAL may be a name like 'HUP' or a number; see 'kill -l' for a list of signals") .help("specify the signal to be sent on timeout; SIGNAL may be a name like 'HUP' or a number; see 'kill -l' for a list of signals")
.takes_value(true) .takes_value(true)
) )
.arg(
Arg::with_name(options::VERBOSE)
.short("v")
.long(options::VERBOSE)
.help("diagnose to stderr any signal sent upon timeout")
)
.arg( .arg(
Arg::with_name(options::DURATION) Arg::with_name(options::DURATION)
.index(1) .index(1)
@ -147,6 +157,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
config.kill_after, config.kill_after,
config.foreground, config.foreground,
config.preserve_status, config.preserve_status,
config.verbose,
) )
} }
@ -159,6 +170,7 @@ fn timeout(
kill_after: Duration, kill_after: Duration,
foreground: bool, foreground: bool,
preserve_status: bool, preserve_status: bool,
verbose: bool,
) -> i32 { ) -> i32 {
if !foreground { if !foreground {
unsafe { libc::setpgid(0, 0) }; unsafe { libc::setpgid(0, 0) };
@ -185,6 +197,13 @@ fn timeout(
match process.wait_or_timeout(duration) { match process.wait_or_timeout(duration) {
Ok(Some(status)) => status.code().unwrap_or_else(|| status.signal().unwrap()), Ok(Some(status)) => status.code().unwrap_or_else(|| status.signal().unwrap()),
Ok(None) => { Ok(None) => {
if verbose {
show_error!(
"sending signal {} to command '{}'",
signal_name_by_value(signal).unwrap(),
cmd[0]
);
}
return_if_err!(ERR_EXIT_STATUS, process.send_signal(signal)); return_if_err!(ERR_EXIT_STATUS, process.send_signal(signal));
match process.wait_or_timeout(kill_after) { match process.wait_or_timeout(kill_after) {
Ok(Some(status)) => { Ok(Some(status)) => {
@ -199,6 +218,9 @@ fn timeout(
// XXX: this may not be right // XXX: this may not be right
return 124; return 124;
} }
if verbose {
show_error!("sending signal KILL to command '{}'", cmd[0]);
}
return_if_err!( return_if_err!(
ERR_EXIT_STATUS, ERR_EXIT_STATUS,
process process

View file

@ -17,3 +17,17 @@ fn test_command_with_args() {
.succeeds() .succeeds()
.stdout_only("abcd"); .stdout_only("abcd");
} }
#[test]
fn test_verbose() {
for &verbose_flag in &["-v", "--verbose"] {
new_ucmd!()
.args(&[verbose_flag, ".1", "sleep", "10"])
.fails()
.stderr_only("timeout: sending signal TERM to command 'sleep'");
new_ucmd!()
.args(&[verbose_flag, "-s0", "-k.1", ".1", "sleep", "10"])
.fails()
.stderr_only("timeout: sending signal EXIT to command 'sleep'\ntimeout: sending signal KILL to command 'sleep'");
}
}