mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
timeout: support --verbose
This commit is contained in:
parent
b0b937dc3e
commit
8e0ed2d20e
2 changed files with 37 additions and 1 deletions
|
@ -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
|
||||||
|
|
|
@ -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'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue