mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-31 13:07:46 +00:00
Merge pull request #6061 from cre4ture/fix/flaky_timeout_kill_subprocess
Fix/flaky timeout kill subprocess
This commit is contained in:
commit
f89cfe2a5e
2 changed files with 31 additions and 11 deletions
|
@ -202,14 +202,15 @@ fn send_signal(process: &mut Child, signal: usize, foreground: bool) {
|
||||||
// NOTE: GNU timeout doesn't check for errors of signal.
|
// NOTE: GNU timeout doesn't check for errors of signal.
|
||||||
// The subprocess might have exited just after the timeout.
|
// The subprocess might have exited just after the timeout.
|
||||||
// Sending a signal now would return "No such process", but we should still try to kill the children.
|
// Sending a signal now would return "No such process", but we should still try to kill the children.
|
||||||
_ = process.send_signal(signal);
|
match foreground {
|
||||||
if !foreground {
|
true => _ = process.send_signal(signal),
|
||||||
_ = process.send_signal_group(signal);
|
false => {
|
||||||
let kill_signal = signal_by_name_or_value("KILL").unwrap();
|
_ = process.send_signal_group(signal);
|
||||||
let continued_signal = signal_by_name_or_value("CONT").unwrap();
|
let kill_signal = signal_by_name_or_value("KILL").unwrap();
|
||||||
if signal != kill_signal && signal != continued_signal {
|
let continued_signal = signal_by_name_or_value("CONT").unwrap();
|
||||||
_ = process.send_signal(continued_signal);
|
if signal != kill_signal && signal != continued_signal {
|
||||||
_ = process.send_signal_group(continued_signal);
|
_ = process.send_signal_group(continued_signal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,8 +343,15 @@ fn timeout(
|
||||||
send_signal(process, signal, foreground);
|
send_signal(process, signal, foreground);
|
||||||
match kill_after {
|
match kill_after {
|
||||||
None => {
|
None => {
|
||||||
|
let status = process.wait()?;
|
||||||
if preserve_status {
|
if preserve_status {
|
||||||
Err(ExitStatus::SignalSent(signal).into())
|
if let Some(ec) = status.code() {
|
||||||
|
Err(ec.into())
|
||||||
|
} else if let Some(sc) = status.signal() {
|
||||||
|
Err(ExitStatus::SignalSent(sc.try_into().unwrap()).into())
|
||||||
|
} else {
|
||||||
|
Err(ExitStatus::CommandTimedOut.into())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(ExitStatus::CommandTimedOut.into())
|
Err(ExitStatus::CommandTimedOut.into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,18 @@ fn test_preserve_status() {
|
||||||
.no_stdout();
|
.no_stdout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_preserve_status_even_when_send_signal() {
|
||||||
|
// When sending CONT signal, process doesn't get killed or stopped.
|
||||||
|
// So, expected result is success and code 0.
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-s", "CONT", "--preserve-status", ".1", "sleep", "5"])
|
||||||
|
.succeeds()
|
||||||
|
.code_is(0)
|
||||||
|
.no_stderr()
|
||||||
|
.no_stdout();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dont_overflow() {
|
fn test_dont_overflow() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
@ -151,10 +163,10 @@ fn test_kill_subprocess() {
|
||||||
"10",
|
"10",
|
||||||
"sh",
|
"sh",
|
||||||
"-c",
|
"-c",
|
||||||
"sh -c \"trap 'echo xyz' TERM; sleep 30\"",
|
"trap 'echo inside_trap' TERM; sleep 30",
|
||||||
])
|
])
|
||||||
.fails()
|
.fails()
|
||||||
.code_is(124)
|
.code_is(124)
|
||||||
.stdout_contains("xyz")
|
.stdout_contains("inside_trap")
|
||||||
.stderr_contains("Terminated");
|
.stderr_contains("Terminated");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue