diff --git a/hive-bash-mcp/Cargo.toml b/hive-bash-mcp/Cargo.toml index 81699f08..ab7e09fd 100644 --- a/hive-bash-mcp/Cargo.toml +++ b/hive-bash-mcp/Cargo.toml @@ -9,6 +9,7 @@ workspace = true [dependencies] anyhow.workspace = true hive-sh4re.workspace = true +libc.workspace = true rmcp.workspace = true schemars.workspace = true serde.workspace = true diff --git a/hive-bash-mcp/src/runner.rs b/hive-bash-mcp/src/runner.rs index f6a8ee14..f6e901eb 100644 --- a/hive-bash-mcp/src/runner.rs +++ b/hive-bash-mcp/src/runner.rs @@ -358,12 +358,21 @@ async fn exec_cmd( timeout: Duration, ) -> Result<(i32, bool)> { use tokio::process::Command; - let mut child = Command::new("sh") + // SAFETY: `nice` is async-signal-safe and modifies only the calling + // process's scheduling priority before exec. No allocations, no locks. + let mut cmd_builder = Command::new("sh"); + cmd_builder .arg("-c") .arg(cmd) .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn()?; + .stderr(std::process::Stdio::piped()); + unsafe { + cmd_builder.pre_exec(|| { + libc::nice(10); + Ok(()) + }); + } + let mut child = cmd_builder.spawn()?; let stdout = child.stdout.take().expect("stdout piped"); let stderr = child.stderr.take().expect("stderr piped");