From 5f1da52502f6c2c267edf4756710d42e9f55f60d Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Tue, 30 Jun 2026 06:33:11 +0300 Subject: [PATCH] redbear-sessiond: port ACPI shutdown watcher to new Fd-based scheme Phase D of the ACPI fork-sync plan (continuation). Phase B replaced the `/scheme/kernel.acpi/kstop` filesystem file with a single Fd-based call() interface. This consumer (redbear-sessiond) still tried to open the old path and got EBADF, leaving sessiond without shutdown-watchdog signal emission. The new implementation: - Opens `/scheme/kernel.acpi` and uses `openat("kstop", ...)` to get the kstop sub-handle. The kernel requires the CheckShutdown kcall to target the sub-handle (HandleBits::KSTOP_HANDLE), not the parent. - Uses the new `AcpiVerb::CheckShutdown` (value 2) kcall to poll the kernel-side shutdown flag every 250ms. - The poll-based approach was chosen over the event-queue subscription path (which would require pulling in `redox_event` and dealing with the `llvm_asm!` macro deprecation). The kernel's new design supports this polling pattern natively; the wakeup latency is bounded at 250ms. Also updates the inner-fork submodule pointers to pick up the Phase A (kernel re-sync) and Phase C+D (base gap-closing) commits from local/sources/{kernel,base}. Files: - local/recipes/system/redbear-sessiond/source/src/acpi_watcher.rs: rewrote wait_for_shutdown_edge() to use the new Fd interface. - local/sources/base: pointer bumped to include Phase C+D gap fixes (4f2a043 in kernel paired with ae57fe3, d844111, 8140a2c in base). - local/sources/kernel: pointer bumped to include the Phase A ACPI re-sync (RSDP validation, AcpiScheme fevent, new kcall interface). Verified by: redbear-mini ISO rebuilt cleanly (2026-06-30 06:28) and QEMU boot reaches Red Bear login: prompt with redbear-sessiond working (login1 registered on D-Bus, ACPI shutdown watcher no longer errors). --- .../source/src/acpi_watcher.rs | 53 +++++++++++++++---- local/sources/base | 2 +- local/sources/kernel | 2 +- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/local/recipes/system/redbear-sessiond/source/src/acpi_watcher.rs b/local/recipes/system/redbear-sessiond/source/src/acpi_watcher.rs index 3803c52c65..4a3bd67e90 100644 --- a/local/recipes/system/redbear-sessiond/source/src/acpi_watcher.rs +++ b/local/recipes/system/redbear-sessiond/source/src/acpi_watcher.rs @@ -3,17 +3,50 @@ use zbus::Connection; use crate::runtime_state::SharedRuntime; #[cfg(target_os = "redox")] -const KSTOP_PATH: &str = "/scheme/kernel.acpi/kstop"; +mod redox_shutdown { + /// Block until the kernel signals a shutdown. + /// + /// Phase B of the ACPI fork-sync replaced the `/scheme/kernel.acpi/kstop` + /// file with a single Fd-based call() interface. The kstop sub-handle + /// is event-driven (see kernel/scheme/acpi.rs register_kstop). + /// + /// Rather than subscribing to the event queue (which would require + /// pulling in `redox_event` and dealing with the macro-deprecation + /// churn), we poll the `AcpiVerb::CheckShutdown` kcall every 250ms. + /// This is the supported pattern for userspace that just wants + /// the boolean "is shutdown pending" signal. + pub fn wait_for_shutdown_edge() -> std::io::Result<()> { + let parent = libredox::Fd::open( + "/scheme/kernel.acpi", + libredox::flag::O_CLOEXEC, + 0, + )?; + // Open the kstop sub-handle. The kernel requires us to call + // CheckShutdown on the kstop handle (HandleBits::KSTOP_HANDLE), + // not on the parent handle. + let kstop = parent.openat("kstop", libredox::flag::O_CLOEXEC, 0)?; + + // AcpiVerb::CheckShutdown = 2. + loop { + let mut buf = [0u8; 8]; + let n = kstop.call_ro( + &mut buf, + redox_syscall::flag::CallFlags::empty(), + &[2u64], + )?; + if n > 0 { + let shutdown = u64::from_le_bytes(buf[..8].try_into().unwrap_or([0; 8])); + if shutdown != 0 { + return Ok(()); + } + } + std::thread::sleep(std::time::Duration::from_millis(250)); + } + } +} #[cfg(target_os = "redox")] -fn wait_for_shutdown_edge() -> std::io::Result<()> { - use std::io::Read; - - let mut file = std::fs::File::open(KSTOP_PATH)?; - let mut byte = [0_u8; 1]; - let _ = file.read(&mut byte)?; - Ok(()) -} +use redox_shutdown::wait_for_shutdown_edge; pub async fn watch_and_emit(connection: Connection, runtime: SharedRuntime) { #[cfg(target_os = "redox")] @@ -45,4 +78,4 @@ pub async fn watch_and_emit(connection: Connection, runtime: SharedRuntime) { let _ = connection; let _ = runtime; } -} +} \ No newline at end of file diff --git a/local/sources/base b/local/sources/base index de9d1f495f..8140a2cd27 160000 --- a/local/sources/base +++ b/local/sources/base @@ -1 +1 @@ -Subproject commit de9d1f495f0444aeb93e10407e0c76514c9bde14 +Subproject commit 8140a2cd2753d8b85d536068bf4a79b8a5a7e961 diff --git a/local/sources/kernel b/local/sources/kernel index 4cb9d80396..4f2a0436eb 160000 --- a/local/sources/kernel +++ b/local/sources/kernel @@ -1 +1 @@ -Subproject commit 4cb9d80396f727bacff1dc41fefaa2df18197a8b +Subproject commit 4f2a0436eb98863e400496557fb529d447ff66e2