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.
This commit is contained in:
2026-07-15 06:46:28 +09:00
parent 8a5921410a
commit b2dae113e6
+48 -3
View File
@@ -1144,6 +1144,45 @@ impl KernelScheme for ProcScheme {
_: CallerCtx,
token: &mut CleanLockToken,
) -> Result<OpenResult> {
// 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("<binary>"),
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 => {