Skip to content

Commit 8794cb5

Browse files
author
Roy Lin
committed
fix(box): run the log processor in the shim (box-lifetime), not the CLI
Detached `run -d` boxes truncated their logs: the json-file/syslog processor was a tokio spawn_blocking task in the EPHEMERAL launching CLI, which exits on detach — so container.json only ever got the lines written before the CLI left (reliably repro'd: `echo early; sleep 5; echo late` captured only 'early'). Move the processor to the SHIM — the box's own per-process lifetime that already writes console.log. This is the daemonless home (like containerd-shim): it works identically for foreground and detached, with no daemon dependency, and drains the final lines on teardown. - core/log.rs: moved the sync processing engine here (run_log_processor + json-file/syslog/RotatingWriter/tail_next_line), keyed off a `stop` flag. When the VM exits the shim sets stop, the processor drains to EOF (flushing a trailing partial line) and returns — no last-line teardown race. (start_enter DOES return the guest status, despite the legacy 'never returns' comment.) - core/vmm.rs: InstanceSpec gains log_config (serialized to the shim). - shim/main.rs: spawn the processor thread before start_enter; stop+join after. - runtime/vm: VmManager carries log_config (set_log_config); spec threads it. - runtime/log.rs: now just re-exports json_log_path/is_runtime_console_noise. - cli: set_log_config on the VM; removed the 3 ephemeral CLI spawns. KVM-verified: detached `early; sleep 5; late` -> BOTH lines, timestamps ~5s apart (so --timestamps now shows REAL per-line emission time too); last-line before exit preserved; logs still clean (noise=0); exit code 7 propagates; exec unaffected; no VM leak. Known separate/pre-existing gap: foreground non-`--rm` boxes wipe their dir (logs included) on destroy, so `logs` after a foreground run is empty — orthogonal to this fix; tracked for follow-up.
1 parent 6a870f6 commit 8794cb5

12 files changed

Lines changed: 411 additions & 453 deletions

File tree

src/Cargo.lock

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

src/cli/src/boot.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ pub async fn boot_from_record(
189189

190190
// Activate Prometheus metrics collection
191191
vm.set_metrics(RuntimeMetrics::try_new()?);
192+
// The shim runs the log processor for the box's lifetime.
193+
vm.set_log_config(record.log_config.clone());
192194

193195
let mut resource_guard = ensure_boot_resources(record)?;
194196
if let Err(error) = vm.boot().await {
@@ -206,14 +208,9 @@ pub async fn boot_from_record(
206208
);
207209
}
208210

209-
// Spawn structured log processor (json-file driver writes container.json)
210-
let log_dir = record.box_dir.join("logs");
211-
let _ = std::fs::create_dir_all(&log_dir);
212-
let _log_handle = a3s_box_runtime::log::spawn_log_processor(
213-
record.console_log.clone(),
214-
log_dir,
215-
record.log_config.clone(),
216-
);
211+
// Ensure the log dir exists so the shim's container.json (and console.log)
212+
// have a home; the shim itself runs the log processor.
213+
let _ = std::fs::create_dir_all(record.box_dir.join("logs"));
217214

218215
let pid = vm.pid().await;
219216
let exec_socket_path = vm.exec_socket_path().map(PathBuf::from);

src/cli/src/commands/compose.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -613,13 +613,9 @@ async fn execute_up(
613613
);
614614
}
615615

616-
// Spawn log processor
617-
let log_dir = box_dir.join("logs");
618-
let _ = a3s_box_runtime::log::spawn_log_processor(
619-
box_dir.join("logs").join("console.log"),
620-
log_dir,
621-
Default::default(),
622-
);
616+
// Ensure the log dir exists; the shim runs the log processor (default
617+
// json-file driver) for each service box's lifetime.
618+
let _ = std::fs::create_dir_all(box_dir.join("logs"));
623619

624620
println!(" ✓");
625621
}

src/cli/src/commands/run.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ async fn setup_and_boot(args: &RunArgs) -> Result<RunContext, Box<dyn std::error
188188

189189
let emitter = EventEmitter::new(256);
190190
let mut vm = VmManager::new(config, emitter);
191+
// The shim runs the log processor for the box's lifetime (so detached boxes
192+
// keep logging after this CLI exits).
193+
vm.set_log_config(log_config.clone());
191194
let box_id = vm.box_id().to_string();
192195
println!(
193196
"Creating box {} ({})...",
@@ -376,11 +379,10 @@ async fn setup_and_boot(args: &RunArgs) -> Result<RunContext, Box<dyn std::error
376379
.await;
377380
return Err(error.into());
378381
}
379-
let _log_handle = a3s_box_runtime::log::spawn_log_processor(
380-
box_dir.join("logs").join("console.log"),
381-
log_dir,
382-
log_config,
383-
);
382+
// Log processing now runs in the shim for the box's lifetime; see
383+
// VmManager::set_log_config above. (log_dir is still created so the shim's
384+
// container.json has a home.)
385+
let _ = &log_dir;
384386

385387
let health_checker = health_check.as_ref().map(|hc| {
386388
crate::health::spawn_health_checker(box_id.clone(), exec_socket_path.clone(), hc.clone())

src/core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ thiserror = { workspace = true }
1818
tracing = { workspace = true }
1919
chrono = { workspace = true }
2020
dirs = { workspace = true }
21+
flate2 = "1.0"
2122

2223
[lib]
2324
name = "a3s_box_core"

0 commit comments

Comments
 (0)