forked from wrenn/wrenn
fix: resolve PTY failure, MMDS file writes, and metrics instability in envd-rs
Three bugs fixed:
1. PTY connections failed because home directory was hardcoded as
/home/{username} instead of reading from /etc/passwd. For root,
this produced /home/root/ which doesn't exist — CWD validation
rejected every PTY Start request without explicit cwd. Fixed all
6 locations to use user.dir from nix::unistd::User.
2. MMDS polling silently failed to parse metadata because the
logs_collector_address field lacked #[serde(default)]. The host
agent only sends instanceID + envID — missing "address" field
caused every deserialize attempt to fail, so .WRENN_SANDBOX_ID
and .WRENN_TEMPLATE_ID were never written. Also added error
logging and create_dir_all before file writes.
3. Metrics CPU values were non-deterministic because a fresh
sysinfo::System was created per request with a 100ms sleep
between reads. Replaced with a background thread that samples
CPU at fixed 1-second intervals via a persistent System instance,
matching gopsutil's internal caching behavior. Metrics endpoint
now reads cached atomic values — no blocking, consistent window.
Also: close master PTY fd in child pre_exec, add process.Start
request logging, bump version to 0.2.0.
This commit is contained in:
@ -36,7 +36,7 @@ impl FilesystemServiceImpl {
|
||||
ConnectError::new(ErrorCode::Unauthenticated, format!("invalid user: {e}"))
|
||||
})?;
|
||||
|
||||
let home_dir = format!("/home/{}", user.name);
|
||||
let home_dir = user.dir.to_string_lossy().to_string();
|
||||
let default_workdir = self.state.defaults.workdir.as_deref();
|
||||
|
||||
expand_and_resolve(path, &home_dir, default_workdir)
|
||||
|
||||
@ -141,7 +141,7 @@ pub fn spawn_process(
|
||||
) -> Result<Arc<ProcessHandle>, ConnectError> {
|
||||
let mut env: Vec<(String, String)> = Vec::new();
|
||||
env.push(("PATH".into(), std::env::var("PATH").unwrap_or_default()));
|
||||
let home = format!("/home/{}", user.name);
|
||||
let home = user.dir.to_string_lossy().to_string();
|
||||
env.push(("HOME".into(), home));
|
||||
env.push(("USER".into(), user.name.clone()));
|
||||
env.push(("LOGNAME".into(), user.name.clone()));
|
||||
@ -206,7 +206,9 @@ pub fn spawn_process(
|
||||
unsafe {
|
||||
use std::os::unix::io::AsRawFd;
|
||||
let slave_raw = slave_fd.as_raw_fd();
|
||||
let master_raw = master_fd.as_raw_fd();
|
||||
command.pre_exec(move || {
|
||||
libc::close(master_raw);
|
||||
nix::unistd::setsid()
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||
libc::ioctl(slave_raw, libc::TIOCSCTTY, 0);
|
||||
|
||||
@ -83,7 +83,7 @@ impl ProcessServiceImpl {
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect();
|
||||
|
||||
let home_dir = format!("/home/{}", user.name);
|
||||
let home_dir = user.dir.to_string_lossy().to_string();
|
||||
let cwd_str: &str = proc_config.cwd.unwrap_or("");
|
||||
let cwd = expand_and_resolve(cwd_str, &home_dir, self.state.defaults.workdir.as_deref())
|
||||
.map_err(|e| ConnectError::new(ErrorCode::InvalidArgument, e))?;
|
||||
@ -105,6 +105,17 @@ impl ProcessServiceImpl {
|
||||
let enable_stdin = request.stdin.unwrap_or(true);
|
||||
let tag = request.tag.map(|s| s.to_string());
|
||||
|
||||
tracing::info!(
|
||||
cmd = cmd,
|
||||
has_pty = pty_opts.is_some(),
|
||||
pty_size = ?pty_opts,
|
||||
tag = ?tag,
|
||||
stdin = enable_stdin,
|
||||
cwd = effective_cwd,
|
||||
user = %username,
|
||||
"process.Start request"
|
||||
);
|
||||
|
||||
let handle = process_handler::spawn_process(
|
||||
cmd,
|
||||
&args,
|
||||
|
||||
Reference in New Issue
Block a user