Skip to content

Commit c89b6df

Browse files
authored
fix: Make sure build fails if command returns non-zero code (#1499)
fix: Make sure build fails if command returns non-zero code **What does this PR do?** This PR introduces a `wait_for_success` helper and uses it throughout the builder crate to ensure that the status code for a command is checked, and the build fails if it is non-zero. **Motivation:** I ran into this very sharp edge as I was experimenting with some build changes in libdatadog: whenever an external command exits with a non-zero status code, the build would continue, rather than fail immediately. This happens because we were not previously checking for the command status code. This change fixes this. **Additional Notes:** N/A **How to test the change?** Since the error code only gets triggered when something goes wrong, you won't see it by default. To test this, I replaced command invocations (to e.g. `cargo` in `profiling.rs`) with a call to `false`: this is an actual command that runs successfully, but then returns a non-zero code and thus can be used to see this change in action. Make linters happy Co-authored-by: ivo.anjo <[email protected]>
1 parent cf4684f commit c89b6df

6 files changed

Lines changed: 45 additions & 29 deletions

File tree

builder/src/arch/apple.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use std::ffi::OsStr;
45
use std::os::unix::process::ExitStatusExt;
56
use std::process::Command;
67

7-
use std::ffi::OsStr;
8+
use crate::utils::wait_for_success;
89

910
pub const NATIVE_LIBS: &str =
1011
" -framework Security -framework CoreFoundation -liconv -lSystem -lresolv -lc -lm -liconv";
@@ -43,13 +44,13 @@ pub fn fix_rpath(lib_path: &str) {
4344

4445
pub fn strip_libraries(lib_path: &str) {
4546
// objcopy is not available in macos image. Investigate llvm-objcopy
46-
let mut strip = Command::new("strip")
47+
let strip = Command::new("strip")
4748
.arg("-S")
4849
.arg(lib_path.to_owned() + "/libdatadog_profiling.dylib")
4950
.spawn()
5051
.expect("Failed to spawn strip");
5152

52-
strip.wait().expect("Failed to strip library");
53+
wait_for_success(strip, "strip");
5354
}
5455

5556
pub fn add_additional_files(_lib_path: &str, _target_path: &OsStr) {}

builder/src/arch/linux.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use std::ffi::OsStr;
45
use std::process::Command;
56

6-
use std::ffi::OsStr;
7+
use crate::utils::wait_for_success;
78

89
pub const NATIVE_LIBS: &str = " -ldl -lrt -lpthread -lc -lm -lrt -lpthread -lutil -ldl -lutil";
910
pub const PROF_DYNAMIC_LIB: &str = "libdatadog_profiling.so";
@@ -21,50 +22,50 @@ pub const RUSTFLAGS: [&str; 4] = [
2122

2223
pub fn fix_rpath(lib_path: &str) {
2324
if REMOVE_RPATH {
24-
let mut patchelf = Command::new("patchelf")
25+
let patchelf = Command::new("patchelf")
2526
.arg("--remove-rpath")
2627
.arg(lib_path)
2728
.spawn()
2829
.expect("failed to spawn patchelf");
2930

30-
patchelf.wait().expect("failed to remove rpath");
31+
wait_for_success(patchelf, "patchelf");
3132
}
3233
}
3334

3435
pub fn strip_libraries(lib_path: &str) {
35-
let mut rm_section = Command::new("objcopy")
36+
let rm_section = Command::new("objcopy")
3637
.arg("--remove-section")
3738
.arg(".llvmbc")
3839
.arg(lib_path.to_owned() + "/libdatadog_profiling.a")
3940
.spawn()
4041
.expect("failed to spawn objcopy");
4142

42-
rm_section.wait().expect("Failed to remove llvmbc section");
43+
wait_for_success(rm_section, "objcopy (remove llvmbc section)");
4344

44-
let mut create_debug = Command::new("objcopy")
45+
let create_debug = Command::new("objcopy")
4546
.arg("--only-keep-debug")
4647
.arg(lib_path.to_owned() + "/libdatadog_profiling.so")
4748
.arg(lib_path.to_owned() + "/libdatadog_profiling.debug")
4849
.spawn()
4950
.expect("Failed to spawn objcopy");
5051

51-
create_debug.wait().expect("Failed to extract debug info");
52+
wait_for_success(create_debug, "objcopy (extract debug info)");
5253

53-
let mut strip = Command::new("strip")
54+
let strip = Command::new("strip")
5455
.arg("-S")
5556
.arg(lib_path.to_owned() + "/libdatadog_profiling.so")
5657
.spawn()
5758
.expect("Failed to spawn strip");
5859

59-
strip.wait().expect("Failed to strip library");
60+
wait_for_success(strip, "strip");
6061

61-
let mut debug = Command::new("objcopy")
62+
let debug = Command::new("objcopy")
6263
.arg("--add-gnu-debuglink=".to_string() + lib_path + "/libdatadog_profiling.debug")
6364
.arg(lib_path.to_owned() + "/libdatadog_profiling.so")
6465
.spawn()
6566
.expect("Failed to spawn objcopy");
6667

67-
debug.wait().expect("Failed to set debuglink");
68+
wait_for_success(debug, "objcopy (set debuglink)");
6869
}
6970

7071
pub fn add_additional_files(_lib_path: &str, _target_path: &OsStr) {}

builder/src/arch/musl.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use std::ffi::OsStr;
45
use std::process::Command;
56

6-
use std::ffi::OsStr;
7+
use crate::utils::wait_for_success;
78

89
pub const NATIVE_LIBS: &str = " -lssp_nonshared -lc";
910
pub const PROF_DYNAMIC_LIB: &str = "libdatadog_profiling.so";
@@ -30,39 +31,39 @@ pub fn fix_rpath(lib_path: &str) {
3031
}
3132

3233
pub fn strip_libraries(lib_path: &str) {
33-
let mut rm_section = Command::new("objcopy")
34+
let rm_section = Command::new("objcopy")
3435
.arg("--remove-section")
3536
.arg(".llvmbc")
3637
.arg(lib_path.to_owned() + "/libdatadog_profiling.a")
3738
.spawn()
3839
.expect("failed to spawn objcopy");
3940

40-
rm_section.wait().expect("Failed to remove llvmbc section");
41+
wait_for_success(rm_section, "objcopy (remove llvmbc section)");
4142

42-
let mut create_debug = Command::new("objcopy")
43+
let create_debug = Command::new("objcopy")
4344
.arg("--only-keep-debug")
4445
.arg(lib_path.to_owned() + "/libdatadog_profiling.so")
4546
.arg(lib_path.to_owned() + "/libdatadog_profiling.debug")
4647
.spawn()
4748
.expect("Failed to spawn objcopy");
4849

49-
create_debug.wait().expect("Failed to extract debug info");
50+
wait_for_success(create_debug, "objcopy (extract debug info)");
5051

51-
let mut strip = Command::new("strip")
52+
let strip = Command::new("strip")
5253
.arg("-s")
5354
.arg(lib_path.to_owned() + "/libdatadog_profiling.so")
5455
.spawn()
5556
.expect("Failed to spawn strip");
5657

57-
strip.wait().expect("Failed to strip library");
58+
wait_for_success(strip, "strip");
5859

59-
let mut debug = Command::new("objcopy")
60+
let debug = Command::new("objcopy")
6061
.arg("--add-gnu-debuglink=".to_string() + lib_path + "/libdatadog_profiling.debug")
6162
.arg(lib_path.to_owned() + "/libdatadog_profiling.so")
6263
.spawn()
6364
.expect("Failed to spawn objcopy");
6465

65-
debug.wait().expect("Failed to set debuglink");
66+
wait_for_success(debug, "objcopy (set debuglink)");
6667
}
6768

6869
pub fn add_additional_files(_lib_path: &str, _target_path: &OsStr) {}

builder/src/common.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use crate::arch;
55
use crate::module::Module;
6-
use crate::utils::project_root;
6+
use crate::utils::{project_root, wait_for_success};
77
use anyhow::Result;
88
use std::fs;
99
use std::path::PathBuf;
@@ -18,7 +18,7 @@ pub struct Common {
1818

1919
impl Module for Common {
2020
fn build(&self) -> Result<()> {
21-
let mut cargo = Command::new("cargo")
21+
let cargo = Command::new("cargo")
2222
.env("RUSTFLAGS", arch::RUSTFLAGS.join(" "))
2323
.current_dir(project_root())
2424
.args([
@@ -33,7 +33,7 @@ impl Module for Common {
3333
.spawn()
3434
.expect("failed to spawn cargo");
3535

36-
cargo.wait().expect("Cargo failed");
36+
wait_for_success(cargo, "Cargo");
3737
Ok(())
3838
}
3939

builder/src/profiling.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use crate::arch;
55
use crate::module::Module;
6-
use crate::utils::{file_replace, project_root};
6+
use crate::utils::{file_replace, project_root, wait_for_success};
77
use anyhow::Result;
88
use serde::Deserialize;
99
use std::ffi::OsStr;
@@ -196,14 +196,14 @@ impl Module for Profiling {
196196
let mut args = cargo_args.clone();
197197
args.append(&mut vec!["--crate-type", crate_type]);
198198

199-
let mut cargo = Command::new("cargo")
199+
let cargo = Command::new("cargo")
200200
.env("RUSTFLAGS", arch::RUSTFLAGS.join(" "))
201201
.current_dir(project_root())
202202
.args(args)
203203
.spawn()
204204
.expect("failed to spawn cargo");
205205

206-
cargo.wait().expect("Cargo failed");
206+
wait_for_success(cargo, "Cargo");
207207
}
208208

209209
Ok(())

builder/src/utils.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use anyhow::{anyhow, Result};
55
use std::fs::{self, OpenOptions};
66
use std::io::Write;
77
use std::path::{Path, PathBuf};
8+
use std::process::Child;
89

910
pub fn file_replace(file_in: &str, file_out: &str, target: &str, replace: &str) -> Result<()> {
1011
let content = fs::read_to_string(file_in)?;
@@ -26,3 +27,15 @@ pub fn project_root() -> PathBuf {
2627
.unwrap()
2728
.to_path_buf()
2829
}
30+
31+
/// Waits for a child process to complete and panics if it fails.
32+
pub fn wait_for_success(mut child: Child, name: &str) {
33+
let status = child
34+
.wait()
35+
.unwrap_or_else(|_| panic!("{name} failed to wait"));
36+
assert!(
37+
status.success(),
38+
"{name} failed with exit code: {:?}",
39+
status.code()
40+
);
41+
}

0 commit comments

Comments
 (0)