feat: resident guest init (#333)

Get this thing going..







<!-- greptile_comment -->

<!-- greptile_summary -->

<h2><a
href="https://app.greptile.com/api/retrigger?id=63134761"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/RetriggerDark.svg?v=1"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/Retrigger.svg?v=1"><img
alt="Retrigger"
src="https://greptile-static-assets.s3.amazonaws.com/badges/Retrigger.svg?v=1"
align="right"></picture></a>Confidence Score: 5/5</h2>

The PR appears safe to merge; all previous findings are resolved and the
latest readiness change introduces no established actionable regression.

<h3>Summary</h3>

- Establishes required guest filesystems, runtime directories, device
permissions, and service processes.
- Reports initialization and service deaths over the lifecycle channel.
- Supports launch, restart, and shutdown commands for a resident guest.
- Separates service and workload identities and configures per-launch
runtime environments.
- Removes the currently inactive nescope screenshot option and makes
capture-chain verification fail explicitly when compositor readback is
unavailable.
- Reworks the guest image around `nesinit` as PID 1 without a
distribution service manager.

<h3>Diagram</h3>

```mermaid
sequenceDiagram
    participant Host
    participant Init as nesinit
    participant FS as Guest filesystems
    participant Services as Service stack
    participant Workload

    Init->>Host: Ready(protocol version)
    Host->>Init: Boot(mount descriptors)
    Init->>FS: Establish and mount shares
    Init->>Services: Spawn services in order
    Services-->>Init: Required sockets ready
    Init->>Host: Initialized(service names)
    Host->>Init: Launch(id, exec, on_exit)
    Init->>Workload: Spawn with isolated UID/runtime
    Init->>Host: Started(id)
    Workload-->>Init: Exit status
    Init->>Host: WorkloadExited(id, status)
    Host->>Init: Launch / Restart / Shutdown
```

<sub>Reviews (4) · Last reviewed commit: ["fix(nesinit): readiness is a
socket
that..."](731d34df9d)</sub>

<!-- /greptile_comment -->

---------

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kristian Ollikainen
2026-09-14 14:45:13 +03:00
committed by GitHub
parent ec8b13d0c9
commit 8246aa5538
43 changed files with 4448 additions and 1553 deletions

View File

@@ -18,13 +18,11 @@ smithay = { version = "0.7", default-features = false, features = [
"backend_drm",
"desktop",
"backend_libinput",
"renderer_pixman", # needed for on_commit_buffer_handler
#"renderer_pixman", # needed for on_commit_buffer_handler
# Reading a dmabuf back to the CPU. nescope still does not composite or
# present anything -- this is import-and-copy only, so a client that
# renders on the GPU can be screenshotted like any other.
"renderer_gl",
"backend_egl",
"backend_gbm",
#"backend_gbm",
] }
# Wayland client connects to the host compositor to forward buffers.

View File

@@ -60,15 +60,15 @@ use smithay::reexports::wayland_server::Display;
use smithay::wayland::socket::ListeningSocketSource;
mod focus;
mod gpu_readback;
//mod gpu_readback;
mod handlers;
mod hdr;
mod input;
mod input_ipc;
mod libinput_backend;
mod protocols;
mod screenshot_ipc;
mod screenshot_wire;
//mod screenshot_ipc;
//mod screenshot_wire;
mod state;
mod xwm;
@@ -125,14 +125,11 @@ struct Args {
)]
input_ipc: String,
/// Path to the hub's screenshot IPC socket (nescope connects as client).
///
/// Optional, and absent means the feature is simply off: it exists for
/// clients that are not games — a Steam login screen has no Vulkan frames
/// for `nescapture` to take, so its pixels can only come from here.
#[arg(long, env = "NESCOPE_SCREENSHOT_IPC")]
screenshot_ipc: Option<String>,
// There is no `--screenshot-ipc`. The path it named is commented out below,
// and an option that is accepted and does nothing is worse than one that is
// refused: a caller passing it gets no error, no capture, and nothing to
// read that says which. It comes back with the code, or not at all.
//
/// GPU render device (e.g. /dev/dri/renderD128). Sets VK_DRIVER_FILES
/// for the game so it uses the same GPU.
#[arg(long, env = "NESCOPE_RENDER_DEVICE")]
@@ -317,13 +314,13 @@ fn main() {
// The GPU to import dmabufs on for screenshots. Same device the game is
// pointed at, because a buffer the game produced can only be imported on
// the device that made it.
gpu_readback::set_render_device(args.render_device.clone());
//gpu_readback::set_render_device(args.render_device.clone());
// ── Screenshot IPC source ────────────────────────────────────────────
// Same dial-out shape as the input socket below, so the hub is the
// listener and there is no race against a socket that does not exist yet.
// Absent means the feature is off, which is the normal case for a game.
if let Some(path) = args.screenshot_ipc.clone() {
/*if let Some(path) = args.screenshot_ipc.clone() {
match screenshot_ipc::ScreenshotIpcSource::connect(&path) {
Ok(source) => match source.try_clone_writer() {
Ok(mut writer) => {
@@ -357,7 +354,7 @@ fn main() {
},
Err(e) => tracing::warn!("Failed to connect to screenshot IPC socket {path}: {e}"),
}
}
}*/
// ── Input IPC source ─────────────────────────────────────────────────
// Connect to the neshub input socket and feed events into the