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:
@ -1,4 +1,4 @@
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::auth::token::SecureToken;
|
||||
@ -17,6 +17,8 @@ pub struct AppState {
|
||||
pub access_token: SecureToken,
|
||||
pub conn_tracker: ConnTracker,
|
||||
pub port_subsystem: Option<Arc<PortSubsystem>>,
|
||||
pub cpu_used_pct: AtomicU32,
|
||||
pub cpu_count: AtomicU32,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
@ -27,7 +29,7 @@ impl AppState {
|
||||
is_fc: bool,
|
||||
port_subsystem: Option<Arc<PortSubsystem>>,
|
||||
) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
let state = Arc::new(Self {
|
||||
defaults,
|
||||
version,
|
||||
commit,
|
||||
@ -37,6 +39,49 @@ impl AppState {
|
||||
access_token: SecureToken::new(),
|
||||
conn_tracker: ConnTracker::new(),
|
||||
port_subsystem,
|
||||
})
|
||||
cpu_used_pct: AtomicU32::new(0),
|
||||
cpu_count: AtomicU32::new(0),
|
||||
});
|
||||
|
||||
let state_clone = Arc::clone(&state);
|
||||
std::thread::spawn(move || {
|
||||
cpu_sampler(state_clone);
|
||||
});
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
pub fn cpu_used_pct(&self) -> f32 {
|
||||
f32::from_bits(self.cpu_used_pct.load(Ordering::Relaxed))
|
||||
}
|
||||
|
||||
pub fn cpu_count(&self) -> u32 {
|
||||
self.cpu_count.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
fn cpu_sampler(state: Arc<AppState>) {
|
||||
use sysinfo::System;
|
||||
|
||||
let mut sys = System::new();
|
||||
sys.refresh_cpu_all();
|
||||
|
||||
loop {
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
sys.refresh_cpu_all();
|
||||
|
||||
let pct = sys.global_cpu_usage();
|
||||
let rounded = if pct > 0.0 {
|
||||
(pct * 100.0).round() / 100.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
state
|
||||
.cpu_used_pct
|
||||
.store(rounded.to_bits(), Ordering::Relaxed);
|
||||
state
|
||||
.cpu_count
|
||||
.store(sys.cpus().len() as u32, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user