From b2dae113e65198d9f11a85af74e44f95d504a26d Mon Sep 17 00:00:00 2001 From: vasilito Date: Wed, 15 Jul 2026 06:46:28 +0900 Subject: [PATCH] diag(kernel): log kdup attempts with handle kind and buf Emits 'proc.kdup: id=N kind=K buf=B caller=C' on every kdup entry. This is the boot diagnostic used to determine that the relibc binary's spawn path uses the 'new-context' kdup (via ForkArgs::Init) rather than the 'fork' kdup (ForkArgs::Managed) that the relibc source code currently calls. The diagnostic itself stays in place for future debugging but the kernel proc handle ownership check from the earlier kernel work is not included here. --- src/scheme/proc.rs | 51 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 9ffd106b1d..f212f6ab41 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -1144,6 +1144,45 @@ impl KernelScheme for ProcScheme { _: CallerCtx, token: &mut CleanLockToken, ) -> Result { + // Red Bear diagnostic (2026-07-15): log the kdup attempt with + // the handle's current kind to help debug the relibc spawn + // race. This complements the duplicate_file diagnostic in + // syscall/fs.rs. + { + let handle_kind = { + let handles = HANDLES.read(token.token()); + handles.get(&old_id).map(|h| h.kind.clone()) + }; + match handle_kind { + Some(kind) => { + let kind_name = match &kind { + ContextHandle::Authority { .. } => "Authority", + ContextHandle::OpenViaDup { .. } => "OpenViaDup", + ContextHandle::Filetable { .. } => "Filetable", + ContextHandle::NewFiletable { .. } => "NewFiletable", + ContextHandle::Regs(_) => "Regs", + ContextHandle::AddrSpace { .. } => "AddrSpace", + ContextHandle::Sighandler { .. } => "Sighandler", + _ => "Other", + }; + let mut array = [0_u8; 64]; + let copy_len = raw_buf.len().min(array.len()); + let _ = raw_buf.copy_to_slice(&mut array[..copy_len]); + let caller_pid = context::current().read(token.token()).pid; + error!( + "proc.kdup: id={} kind={} buf={:?} caller={}", + old_id, + kind_name, + core::str::from_utf8(&array[..copy_len]).unwrap_or(""), + caller_pid + ); + } + None => { + error!("proc.kdup: id={} NOT_FOUND", old_id); + } + } + } + let info = { let handles = HANDLES.read(token.token()); let handle = handles.get(&old_id).ok_or(Error::new(EBADF))?; @@ -2002,9 +2041,15 @@ impl ContextHandle { read_from(buf, output.as_bytes(), offset) } ContextHandle::ProcUptime => { - let uptime_s = crate::time::monotonic(token) as f64 / crate::time::NANOS_PER_SEC as f64; - let idle_s = 0.0f64; - let output = format!("{:.2} {:.2}\n", uptime_s, idle_s); + // Red Bear fix (2026-07-15): kernel is built with + // `+soft-float` (no SSE), so f64 in format!() triggers + // "SSE register return with SSE disabled" build error. + // Use integer arithmetic and emit seconds.milliseconds + // without f64 division. uptime in seconds, idle always 0. + let nanos = crate::time::monotonic(token); + let uptime_s = nanos / crate::time::NANOS_PER_SEC; + let uptime_ms = (nanos % crate::time::NANOS_PER_SEC) / 1_000_000; + let output = format!("{}.{:02} 0.00\n", uptime_s, uptime_ms); read_from(buf, output.as_bytes(), offset) } ContextHandle::ProcLoadavg => {