selfhost-verify: módulos del kernel booteado + build a stderr (E2BIG)
Dos bugs latentes que sólo aparecían en un build real (in-VM); en el host quedan tapados porque todo sale de caché. 1. scripts/selfhost-verify.sh: los módulos se sacaban de /lib/modules/$(uname -r) pero la VM bootea $KERNEL (/boot/vmlinuz-linux), que puede ser otra versión. Mismatch de version-magic ⇒ overlay.ko no carga ⇒ bwrap muere "No such device". Ahora la versión se deriva del bzImage booteado (file -bL "$KERNEL"; fallback uname -r). 2. crates/hammer-build/src/sandbox.rs: spawn_pump teeaba el stdout del build al stdout del padre. rebuild-stage1 hace PRIME=$(hammer ... bootstrap stage1); en un build real son miles de líneas de configure/make capturadas en $PRIME ⇒ el paso siguiente --rootfs "$PRIME" exec con un arg gigante ⇒ E2BIG (Argument list too long). Ahora el tee va a stderr; stdout queda para el hash legible-por-máquina. Con esto el verify corre end-to-end in-VM: los 4 componentes reproducen bit a bit, pero of_tree(stage1) diverge (host vs VM vs baseline) — no-determinismo del ensamblado a cazar (SDD 09 §2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -90,8 +90,8 @@ impl Sandbox {
|
||||
let tail = Arc::new(Mutex::new(VecDeque::<String>::with_capacity(TAIL_LINES)));
|
||||
let out = child.stdout.take().expect("stdout piped");
|
||||
let err = child.stderr.take().expect("stderr piped");
|
||||
let h_out = spawn_pump(out, tail.clone(), false);
|
||||
let h_err = spawn_pump(err, tail.clone(), true);
|
||||
let h_out = spawn_pump(out, tail.clone());
|
||||
let h_err = spawn_pump(err, tail.clone());
|
||||
|
||||
let status = child
|
||||
.wait()
|
||||
@@ -201,12 +201,19 @@ impl Sandbox {
|
||||
}
|
||||
}
|
||||
|
||||
/// Lanza un thread que lee `reader` línea a línea, la reenvía al stream del padre
|
||||
/// (`to_stderr` decide cuál) y la acumula en el ring `tail`. Devuelve el handle para join.
|
||||
/// Lanza un thread que lee `reader` línea a línea, la reenvía a stderr del padre y la
|
||||
/// acumula en el ring `tail`. Devuelve el handle para join.
|
||||
///
|
||||
/// El tee va SIEMPRE a stderr (tanto el stdout como el stderr del build): stdout del proceso
|
||||
/// queda reservado para el resultado legible-por-máquina (el content-hash que imprime la CLI,
|
||||
/// p. ej. `bootstrap stage1`). Antes el stdout del build se teeaba al stdout del padre y se
|
||||
/// colaba en capturas tipo `PRIME=$(hammer … bootstrap stage1)`; con builds reales (no cacheados,
|
||||
/// p. ej. el rebuild in-VM) eso son miles de líneas de `configure`/`make` ⇒ el argumento crece y
|
||||
/// la fase de verificación siguiente (`--rootfs "$PRIME"`) revienta el exec con E2BIG
|
||||
/// (Argument list too long). Va a stderr, junto a los logs de tracing. Ver runbook §8c.
|
||||
fn spawn_pump<R: std::io::Read + Send + 'static>(
|
||||
reader: R,
|
||||
tail: Arc<Mutex<VecDeque<String>>>,
|
||||
to_stderr: bool,
|
||||
) -> std::thread::JoinHandle<()> {
|
||||
std::thread::spawn(move || {
|
||||
let buf = BufReader::new(reader);
|
||||
@@ -215,12 +222,8 @@ fn spawn_pump<R: std::io::Read + Send + 'static>(
|
||||
Ok(l) => l,
|
||||
Err(_) => break,
|
||||
};
|
||||
// Tee en vivo al padre (sin bufferizar de más: el build puede tardar).
|
||||
if to_stderr {
|
||||
// Tee en vivo al padre por stderr (sin bufferizar de más: el build puede tardar).
|
||||
let _ = writeln!(std::io::stderr(), "{line}");
|
||||
} else {
|
||||
let _ = writeln!(std::io::stdout(), "{line}");
|
||||
}
|
||||
if let Ok(mut g) = tail.lock() {
|
||||
push_tail(&mut g, line, TAIL_LINES);
|
||||
}
|
||||
|
||||
@@ -83,8 +83,14 @@ fi
|
||||
|
||||
# 3) Inyectar los módulos del kernel DE ESTA máquina al toolchain (el builder los carga: overlay para
|
||||
# el sandbox bwrap, e1000 para la red del vendoring). Deben matchear el kernel que bootea la VM.
|
||||
say "inyectar overlay.ko + e1000.ko (kernel $(uname -r)) al toolchain"
|
||||
moddir="/lib/modules/$(uname -r)"
|
||||
# La versión de los módulos DEBE matchear el kernel que bootea la VM ($KERNEL), no el del host
|
||||
# corriendo el script ($(uname -r)) — en máquinas con varios kernels instalados difieren y el
|
||||
# insmod falla con "version magic mismatch" → sin overlayfs, bwrap revienta. Sacamos la versión
|
||||
# del propio bzImage; si no se puede, caemos a uname -r.
|
||||
KVER="$(file -bL "$KERNEL" 2>/dev/null | grep -oE 'version [0-9][^ ]*' | awk '{print $2}')"
|
||||
[[ -n "$KVER" && -d "/lib/modules/$KVER" ]] || KVER="$(uname -r)"
|
||||
say "inyectar overlay.ko + e1000.ko (kernel $KVER) al toolchain"
|
||||
moddir="/lib/modules/$KVER"
|
||||
for m in overlay e1000; do
|
||||
src="$(find "$moddir" -name "$m.ko*" 2>/dev/null | head -1)"
|
||||
if [[ -n "$src" ]]; then
|
||||
|
||||
Reference in New Issue
Block a user