Skip to content

Commit f34e5dd

Browse files
authored
Merge pull request #943 from cgwalters/cmd-pdeathsig
Cmd pdeathsig
2 parents dcd3373 + 479cbca commit f34e5dd

File tree

7 files changed

+30
-8
lines changed

7 files changed

+30
-8
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/install.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,8 @@ async fn install_container(
840840
/// Run a command in the host mount namespace
841841
pub(crate) fn run_in_host_mountns(cmd: &str) -> Command {
842842
let mut c = Command::new("/proc/self/exe");
843-
c.args(["exec-in-host-mount-namespace", cmd]);
843+
c.lifecycle_bind()
844+
.args(["exec-in-host-mount-namespace", cmd]);
844845
c
845846
}
846847

lib/src/utils.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::process::Command;
55
use std::time::Duration;
66

77
use anyhow::{Context, Result};
8+
use bootc_utils::CommandRunExt;
89
#[cfg(feature = "install")]
910
use camino::Utf8Path;
1011
use cap_std_ext::cap_std::fs::Dir;
@@ -116,15 +117,12 @@ pub(crate) fn spawn_editor(tmpf: &tempfile::NamedTempFile) -> Result<()> {
116117
let argv0 = editor_args
117118
.next()
118119
.ok_or_else(|| anyhow::anyhow!("Invalid editor: {editor}"))?;
119-
let status = Command::new(argv0)
120+
Command::new(argv0)
120121
.args(editor_args)
121122
.arg(tmpf.path())
122-
.status()
123-
.context("Spawning editor")?;
124-
if !status.success() {
125-
anyhow::bail!("Invoking editor: {editor} failed: {status:?}");
126-
}
127-
Ok(())
123+
.lifecycle_bind()
124+
.run()
125+
.with_context(|| format!("Invoking editor {editor} failed"))
128126
}
129127

130128
/// Convert a combination of values (likely from CLI parsing) into a signature source

ostree-ext/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ ostree = { features = ["v2022_6"], version = "0.19.0" }
1919

2020
# Private dependencies
2121
anyhow = { workspace = true }
22+
bootc-utils = { path = "../utils" }
2223
camino = { workspace = true, features = ["serde1"] }
2324
chrono = { workspace = true }
2425
olpc-cjson = "0.1.1"

ostree-ext/src/container/deploy.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::os::fd::BorrowedFd;
55
use std::process::Command;
66

77
use anyhow::Result;
8+
use bootc_utils::CommandRunExt;
89
use cap_std_ext::cmdext::CapStdExtCommandExt;
910
use fn_error_context::context;
1011
use ocidir::cap_std::fs::Dir;
@@ -148,6 +149,7 @@ pub async fn deploy(
148149
let st = Command::new("/proc/self/exe")
149150
.args(["internals", "bootc-install-completion", ".", stateroot])
150151
.cwd_dir(sysroot_dir.try_clone()?)
152+
.lifecycle_bind()
151153
.status()?;
152154
if !st.success() {
153155
anyhow::bail!("Failed to complete bootc install");

utils/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ repository = "https://github.com/containers/bootc"
88

99
[dependencies]
1010
anyhow = { workspace = true }
11+
rustix = { workspace = true }
1112
serde = { workspace = true, features = ["derive"] }
1213
serde_json = { workspace = true }
1314
tempfile = { workspace = true }

utils/src/command.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use std::{
44
io::{Read, Seek},
5+
os::unix::process::CommandExt,
56
process::Command,
67
};
78

@@ -15,6 +16,9 @@ pub trait CommandRunExt {
1516
/// Execute the child process.
1617
fn run(&mut self) -> Result<()>;
1718

19+
/// Ensure the child does not outlive the parent.
20+
fn lifecycle_bind(&mut self) -> &mut Self;
21+
1822
/// Execute the child process and capture its output. This uses `run` internally
1923
/// and will return an error if the child process exits abnormally.
2024
fn run_get_output(&mut self) -> Result<Box<dyn std::io::BufRead>>;
@@ -84,6 +88,19 @@ impl CommandRunExt for Command {
8488
self.status()?.check_status(stderr)
8589
}
8690

91+
#[allow(unsafe_code)]
92+
fn lifecycle_bind(&mut self) -> &mut Self {
93+
// SAFETY: This API is safe to call in a forked child.
94+
unsafe {
95+
self.pre_exec(|| {
96+
rustix::process::set_parent_process_death_signal(Some(
97+
rustix::process::Signal::Term,
98+
))
99+
.map_err(Into::into)
100+
})
101+
}
102+
}
103+
87104
/// Output a debug-level log message with this command.
88105
fn log_debug(&mut self) -> &mut Self {
89106
// We unconditionally log at trace level, so avoid double logging

0 commit comments

Comments
 (0)