subagent: keep runs at +1000 when their cgroup is unavailable
Without a run cgroup (no delegation, setup failed, or one create failed) a subagent run was started plain at oom_score_adj 0, below the +500 the unit gave it before. Every run of the daemon now goes through the entry wrapper; it sets +1000 and enters the cgroup only when there is one. run_cgroup::entry takes the cgroup as an Option.
This commit is contained in:
parent
b31db6c7d9
commit
afe6026d44
5 changed files with 159 additions and 64 deletions
|
|
@ -14,9 +14,11 @@
|
|||
//! everything it later forks is born inside:
|
||||
//! - [`enter_in_pre_exec`], from a `Command::pre_exec` hook, for a spawn
|
||||
//! this crate's caller builds itself;
|
||||
//! - [`RunCgroup::entry`], for a spawn built by a library with no such hook:
|
||||
//! - [`entry`], for a spawn built by a library with no such hook:
|
||||
//! it runs this daemon's own binary, whose `main` calls [`exec_entry`]
|
||||
//! first thing, which enters the cgroup and then execs the real program.
|
||||
//! It also sets the run's `oom_score_adj`, and does that alone when the
|
||||
//! run has no cgroup.
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::File;
|
||||
|
|
@ -149,30 +151,34 @@ impl RunCgroup {
|
|||
.write(true)
|
||||
.open(self.dir.join("cgroup.procs"))
|
||||
}
|
||||
}
|
||||
|
||||
/// The program and extra environment that run `program` inside this
|
||||
/// cgroup with `oom_score_adj`: this daemon's own binary, whose `main`
|
||||
/// starts with [`exec_entry`].
|
||||
#[must_use]
|
||||
pub fn entry(&self, program: &Path, oom_score_adj: i32) -> (PathBuf, Vec<(String, String)>) {
|
||||
/// The program and extra environment that run `program` at `oom_score_adj`,
|
||||
/// inside `cgroup` when there is one: this daemon's own binary, whose `main`
|
||||
/// starts with [`exec_entry`].
|
||||
#[must_use]
|
||||
pub fn entry(
|
||||
program: &Path,
|
||||
oom_score_adj: i32,
|
||||
cgroup: Option<&RunCgroup>,
|
||||
) -> (PathBuf, Vec<(String, String)>) {
|
||||
let mut env = vec![
|
||||
(
|
||||
PathBuf::from("/proc/self/exe"),
|
||||
vec![
|
||||
(
|
||||
ENTRY_PROGRAM_ENV.to_owned(),
|
||||
program.to_string_lossy().into_owned(),
|
||||
),
|
||||
(
|
||||
ENTRY_CGROUP_ENV.to_owned(),
|
||||
self.dir.to_string_lossy().into_owned(),
|
||||
),
|
||||
(
|
||||
ENTRY_OOM_SCORE_ADJ_ENV.to_owned(),
|
||||
oom_score_adj.to_string(),
|
||||
),
|
||||
],
|
||||
)
|
||||
ENTRY_PROGRAM_ENV.to_owned(),
|
||||
program.to_string_lossy().into_owned(),
|
||||
),
|
||||
(
|
||||
ENTRY_OOM_SCORE_ADJ_ENV.to_owned(),
|
||||
oom_score_adj.to_string(),
|
||||
),
|
||||
];
|
||||
if let Some(cgroup) = cgroup {
|
||||
env.push((
|
||||
ENTRY_CGROUP_ENV.to_owned(),
|
||||
cgroup.dir.to_string_lossy().into_owned(),
|
||||
));
|
||||
}
|
||||
(PathBuf::from("/proc/self/exe"), env)
|
||||
}
|
||||
|
||||
impl Drop for RunCgroup {
|
||||
|
|
@ -218,8 +224,8 @@ pub fn enter_in_pre_exec(procs: RawFd) -> io::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// When this process was started by [`RunCgroup::entry`]: enter the run's
|
||||
/// cgroup, set its `oom_score_adj`, and exec the run's program with this
|
||||
/// When this process was started by [`entry`]: enter the run's
|
||||
/// cgroup if it has one, set its `oom_score_adj`, and exec the run's program with this
|
||||
/// process's arguments; on failure print the reason and exit 127. Otherwise
|
||||
/// return, doing nothing. Call it first in `main`.
|
||||
pub fn exec_entry() {
|
||||
|
|
@ -336,7 +342,7 @@ mod tests {
|
|||
let (root, _unit) = unit_tree();
|
||||
let cgroups = RunCgroups::init_at(root.path(), OWN, KIND).expect("init");
|
||||
let run = cgroups.create("alpha-0").expect("create");
|
||||
let (program, env) = run.entry(Path::new("claude"), 1000);
|
||||
let (program, env) = entry(Path::new("claude"), 1000, Some(&run));
|
||||
assert_eq!(program, Path::new("/proc/self/exe"));
|
||||
let get = |k: &str| env.iter().find(|(n, _)| n == k).map(|(_, v)| v.as_str());
|
||||
assert_eq!(get(ENTRY_PROGRAM_ENV), Some("claude"));
|
||||
|
|
@ -344,6 +350,16 @@ mod tests {
|
|||
assert_eq!(get(ENTRY_OOM_SCORE_ADJ_ENV), Some("1000"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn entry_without_a_cgroup_still_sets_the_score() {
|
||||
let (program, env) = entry(Path::new("claude"), 1000, None);
|
||||
assert_eq!(program, Path::new("/proc/self/exe"));
|
||||
let get = |k: &str| env.iter().find(|(n, _)| n == k).map(|(_, v)| v.as_str());
|
||||
assert_eq!(get(ENTRY_PROGRAM_ENV), Some("claude"));
|
||||
assert_eq!(get(ENTRY_OOM_SCORE_ADJ_ENV), Some("1000"));
|
||||
assert_eq!(get(ENTRY_CGROUP_ENV), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enter_in_pre_exec_writes_zero_to_the_fd() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
|
|
|
|||
Loading…
Reference in a new issue