1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

timeout: return UResult from uumain() function

This commit is contained in:
Jeffrey Finkelstein 2021-12-31 14:42:15 -05:00
parent cd1a0fbe36
commit cb92db322b

View file

@ -17,6 +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::display::Quotable; use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError};
use uucore::process::ChildExt; use uucore::process::ChildExt;
use uucore::signals::{signal_by_name_or_value, signal_name_by_value}; use uucore::signals::{signal_by_name_or_value, signal_name_by_value};
use uucore::InvalidEncodingHandling; use uucore::InvalidEncodingHandling;
@ -99,7 +100,8 @@ impl Config {
} }
} }
pub fn uumain(args: impl uucore::Args) -> i32 { #[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let args = args let args = args
.collect_str(InvalidEncodingHandling::ConvertLossy) .collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any(); .accept_any();
@ -188,32 +190,36 @@ fn timeout(
foreground: bool, foreground: bool,
preserve_status: bool, preserve_status: bool,
verbose: bool, verbose: bool,
) -> i32 { ) -> UResult<()> {
if !foreground { if !foreground {
unsafe { libc::setpgid(0, 0) }; unsafe { libc::setpgid(0, 0) };
} }
let mut process = match Command::new(&cmd[0]) let mut process = Command::new(&cmd[0])
.args(&cmd[1..]) .args(&cmd[1..])
.stdin(Stdio::inherit()) .stdin(Stdio::inherit())
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.spawn() .spawn()
{ .map_err(|err| {
Ok(p) => p, let status_code = if err.kind() == ErrorKind::NotFound {
Err(err) => {
show_error!("failed to execute process: {}", err);
if err.kind() == ErrorKind::NotFound {
// FIXME: not sure which to use // FIXME: not sure which to use
return 127; 127
} else { } else {
// FIXME: this may not be 100% correct... // FIXME: this may not be 100% correct...
return 126; 126
} };
} USimpleError::new(status_code, format!("failed to execute process: {}", err))
}; })?;
unblock_sigchld(); unblock_sigchld();
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)) => {
let status_code = status.code().unwrap_or_else(|| status.signal().unwrap());
if status_code == 0 {
Ok(())
} else {
Err(status_code.into())
}
}
Ok(None) => { Ok(None) => {
if verbose { if verbose {
show_error!( show_error!(
@ -222,38 +228,50 @@ fn timeout(
cmd[0].quote() cmd[0].quote()
); );
} }
crash_if_err!(ERR_EXIT_STATUS, process.send_signal(signal)); process
.send_signal(signal)
.map_err(|e| USimpleError::new(ERR_EXIT_STATUS, format!("{}", e)))?;
if let Some(kill_after) = kill_after { if let Some(kill_after) = kill_after {
match process.wait_or_timeout(kill_after) { match process.wait_or_timeout(kill_after) {
Ok(Some(status)) => { Ok(Some(status)) => {
if preserve_status { if preserve_status {
status.code().unwrap_or_else(|| status.signal().unwrap()) let status_code =
status.code().unwrap_or_else(|| status.signal().unwrap());
if status_code == 0 {
Ok(())
} else {
Err(status_code.into())
}
} else { } else {
124 Err(124.into())
} }
} }
Ok(None) => { Ok(None) => {
if verbose { if verbose {
show_error!("sending signal KILL to command {}", cmd[0].quote()); show_error!("sending signal KILL to command {}", cmd[0].quote());
} }
crash_if_err!( process
ERR_EXIT_STATUS, .send_signal(uucore::signals::signal_by_name_or_value("KILL").unwrap())
process.send_signal( .map_err(|e| USimpleError::new(ERR_EXIT_STATUS, format!("{}", e)))?;
uucore::signals::signal_by_name_or_value("KILL").unwrap() process
) .wait()
); .map_err(|e| USimpleError::new(ERR_EXIT_STATUS, format!("{}", e)))?;
crash_if_err!(ERR_EXIT_STATUS, process.wait()); Err(137.into())
137
} }
Err(_) => 124, Err(_) => Err(124.into()),
} }
} else { } else {
124 Err(124.into())
} }
} }
Err(_) => { Err(_) => {
crash_if_err!(ERR_EXIT_STATUS, process.send_signal(signal)); // We're going to return ERR_EXIT_STATUS regardless of
ERR_EXIT_STATUS // whether `send_signal()` succeeds or fails, so just
// ignore the return value.
process
.send_signal(signal)
.map_err(|e| USimpleError::new(ERR_EXIT_STATUS, format!("{}", e)))?;
Err(ERR_EXIT_STATUS.into())
} }
} }
} }