mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
Merge pull request #2832 from jfinkels/timeout-uresult
timeout: return UResult from uumain() function
This commit is contained in:
commit
0f4b0fd9cd
1 changed files with 47 additions and 29 deletions
|
@ -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 {
|
} else {
|
||||||
124
|
Err(status_code.into())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue