install: don't panic when the strip program is killed by a signal (#12730)

`install -s --strip-program=PROG` aborted with an Option::unwrap panic when
PROG was terminated by a signal: the strip-failure branch formatted its error
with `status.code().unwrap()`, but `ExitStatus::code()` is `None` for a
signal-terminated process.

Branch on `status.code()`: keep the existing "exit code: N" message for a
normal non-zero exit, and use a new `install-error-strip-terminated` message
("strip process terminated abnormally") for the signal case — matching GNU,
which reports the same and exits 1. Adds the locale key to en-US and fr-FR and
a regression test.
This commit is contained in:
Wei Li
2026-06-09 22:17:37 +02:00
committed by GitHub
parent 3db0433c41
commit f24a8ced07
4 changed files with 33 additions and 3 deletions
+1
View File
@@ -33,6 +33,7 @@ install-error-backup-failed = cannot backup { $from } to { $to }
install-error-install-failed = cannot install { $from } to { $to }: { $error }
install-error-strip-failed = strip program failed: { $error }
install-error-strip-abnormal = strip process terminated abnormally - exit code: { $code }
install-error-strip-terminated = strip process terminated abnormally
install-error-metadata-failed = metadata error
install-error-invalid-user = invalid user: { $user }
install-error-invalid-group = invalid group: { $group }
+1
View File
@@ -33,6 +33,7 @@ install-error-backup-failed = impossible de sauvegarder { $from } vers { $to }
install-error-install-failed = impossible d'installer { $from } vers { $to }: { $error }
install-error-strip-failed = échec du programme strip : { $error }
install-error-strip-abnormal = le processus strip s'est terminé anormalement - code de sortie : { $code }
install-error-strip-terminated = le processus strip s'est terminé anormalement
install-error-metadata-failed = erreur de métadonnées
install-error-invalid-user = utilisateur invalide : { $user }
install-error-invalid-group = groupe invalide : { $group }
+11 -3
View File
@@ -97,6 +97,9 @@ enum InstallError {
#[error("{}", translate!("install-error-strip-failed", "error" => .0.clone()))]
StripProgramFailed(String),
#[error("{}", translate!("install-error-strip-terminated"))]
StripTerminated,
#[error("{}", translate!("install-error-metadata-failed"))]
MetadataFailed(#[source] std::io::Error),
@@ -1024,9 +1027,14 @@ fn strip_file(to: &Path, b: &Behavior) -> UResult<()> {
if !status.success() {
// Follow GNU's behavior: if strip fails, removes the target
let _ = fs::remove_file(to);
return Err(InstallError::StripProgramFailed(
translate!("install-error-strip-abnormal", "code" => status.code().unwrap()),
)
// A signal-terminated strip has no exit code; report GNU's
// "strip process terminated abnormally" instead of unwrapping None.
return Err(match status.code() {
Some(code) => InstallError::StripProgramFailed(
translate!("install-error-strip-abnormal", "code" => code),
),
None => InstallError::StripTerminated,
}
.into());
}
}
+20
View File
@@ -935,6 +935,26 @@ fn test_install_and_strip_with_invalid_program() {
assert!(!at.file_exists(STRIP_TARGET_FILE));
}
#[test]
#[cfg(not(windows))]
fn test_install_and_strip_with_signal_terminated_program() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.write("src.sh", "kill -9 $$\n");
scene
.ucmd()
.args(&[
"-s",
"--strip-program",
"/bin/sh",
"src.sh",
STRIP_TARGET_FILE,
])
.fails()
.stderr_only("install: strip process terminated abnormally\n");
assert!(!at.file_exists(STRIP_TARGET_FILE));
}
#[test]
#[cfg(not(windows))]
fn test_install_and_strip_with_non_existent_program() {