Skip to content

Feat/oci runtime groundwork - #1370

Open
Unique-Usman wants to merge 4 commits into
superradcompany:mainfrom
Unique-Usman:feat/oci-runtime-groundwork
Open

Feat/oci runtime groundwork#1370
Unique-Usman wants to merge 4 commits into
superradcompany:mainfrom
Unique-Usman:feat/oci-runtime-groundwork

Conversation

@Unique-Usman

@Unique-Usman Unique-Usman commented Aug 17, 2026

Copy link
Copy Markdown

TL;DR

Add reusable guest-process, state, stdin, and startup-diagnostic support
needed by an OCI runtime, without introducing the runmsb CLI itself.

Description

  • Add OCI bundle parsing, typed lifecycle validation, extension state,
    contextual errors, and an atomic filesystem state store under
    crates/runtime/lib/oci.
  • Harden state creation and updates against concurrent creates, delete/save
    races, shared temporary filenames, and interrupted writes.
  • Extend agentd process execution for OCI workloads, including defensive
    /dev/ptmx setup, standard devpts permissions, bare-command lookup
    through PATH, numeric users, and conventional 128 + signal exit
    statuses.
  • Keep pre_exec failures allocation-free by converting setup failures to
    plain errno-based I/O errors.
  • Capture detached sandbox startup stderr and include a bounded tail in
    startup failures while releasing metrics reservations on every error path.
  • Centralize initial stdin handling for local and cloud execution so null
    stdin sends EOF, byte input sends data followed by EOF, and piped stdin
    remains open.
  • Add an end-to-end regression test proving that cat exits when launched
    with null stdin.
  • Document the user-visible stdin and signal-exit behavior changes in the
    changelog.

Test Plan

cargo +nightly fmt --all -- --check
cargo +nightly clippy -j 2 \
  -p microsandbox-runtime \
  -p microsandbox-agentd \
  -p microsandbox \
  -- -D warnings
cargo +nightly test -j 2 -p microsandbox-runtime --lib oci
cargo +nightly test -j 2 -p microsandbox-agentd --lib
cargo +nightly test -j 2 -p microsandbox --lib initial_stdin_messages
cargo +nightly test -j 2 -p microsandbox --test stdin stdin_null_lets_cat_finish

The final stdin integration test requires a host capable of starting
Microsandbox VMs.

Sequence Diagram

sequenceDiagram
  participant SDK
  participant AgentClient
  participant Agentd
  participant Process
  SDK->>AgentClient: ExecRequest
  AgentClient->>Agentd: Start session
  Agentd->>Process: Spawn with pipe or PTY
  SDK->>AgentClient: Initial ExecStdin messages
  AgentClient->>Agentd: Data and/or empty EOF message
  alt Pipe stdin
    Agentd->>Process: Write data or drop ChildStdin
  else PTY stdin
    Agentd->>Process: Write through PTY master
    Note over Agentd,Process: Empty message cannot close PTY input
  end
  Process-->>Agentd: Output and exit
  Agentd-->>SDK: Exec events
Loading

Fix all with Greploop

Fix All in Codex Fix All in Claude Code

Prompt To Fix All With AI
### Issue 1
sdk/rust/lib/sandbox/exec.rs:513
**Null stdin stays open on PTYs**

When an execution combines the default `StdinMode::Null` with `tty(true)`, this empty message reaches `close_stdin`, which only drops pipe stdin and leaves the PTY master open. A command that reads from stdin, such as `cat`, therefore waits indefinitely instead of receiving EOF.

### Issue 2
crates/runtime/lib/oci/store.rs:103-112
**State directory reuse is unsynchronized**

If save, delete, and recreation of the same container ID overlap, `save` can validate the old directory and then create or rename its temporary file through a newly recreated path. This can overwrite the new container's `state.json` with stale lifecycle data, while the corresponding delete race can remove newly created state.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "fix(exec): send EOF for non-interactive ..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.


pub(crate) fn initial_stdin_messages(stdin_mode: &StdinMode) -> Vec<ExecStdin> {
match stdin_mode {
StdinMode::Null => vec![ExecStdin { data: Vec::new() }],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Null stdin stays open on PTYs

When an execution combines the default StdinMode::Null with tty(true), this empty message reaches close_stdin, which only drops pipe stdin and leaves the PTY master open. A command that reads from stdin, such as cat, therefore waits indefinitely instead of receiving EOF.

Prompt To Fix With AI
This is a comment left during a code review.
Path: sdk/rust/lib/sandbox/exec.rs
Line: 513

Comment:
**Null stdin stays open on PTYs**

When an execution combines the default `StdinMode::Null` with `tty(true)`, this empty message reaches `close_stdin`, which only drops pipe stdin and leaves the PTY master open. A command that reads from stdin, such as `cat`, therefore waits indefinitely instead of receiving EOF.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

Comment thread crates/runtime/lib/oci/store.rs
Parse and validate OCI bundles with `oci-spec`, resolve root filesystem
paths, and model OCI lifecycle transitions with Microsandbox state.

Persist state atomically beneath the runtime root. Keep the bundle, state,
lifecycle, store, and error types independent of the `runmsb` CLI so future
integrations can reuse them.

Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Prepare `devpts` for OCI terminal workloads with standard mount options.
Keep the `/dev/ptmx` symlink as a defensive fallback.

Resolve bare commands through the shared conventional `PATH`, support
numeric OCI users, preserve allocation-safe spawn errors, and apply guest
user and security settings consistently.

Translate signal termination into shell-compatible statuses so Docker
reports 143 for SIGTERM and 137 for SIGKILL instead of 255.

Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Capture detached sandbox stderr in `startup.stderr.log` and include its
final 8 KiB when startup times out or exits before returning valid startup
information.

Release startup log metrics on every completion path so failures remain
visible through Docker and containerd without leaking metric registrations.

Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Centralize initial stdin protocol messages for local and cloud execution.
Close null stdin immediately, leave piped stdin open, and send fixed bytes
followed by EOF.

Add focused and end-to-end coverage so programs such as `cat` and Python do
not wait indefinitely for input. Document this behavior and conventional
signal exit statuses.

Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
@Unique-Usman
Unique-Usman force-pushed the feat/oci-runtime-groundwork branch from 53e880c to c2cf519 Compare August 18, 2026 21:27
@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    OCI[OCI bundle] --> Parse[Parse and validate config]
    Parse --> State[Create durable OCI state]
    State --> Lifecycle[Validate lifecycle operation]
    Lifecycle --> Guest[Execute guest process]
    SDK[SDK exec options] --> Stdin[Build initial stdin messages]
    Stdin --> Guest
    Guest --> Exit[Report conventional exit status]
    Guest --> Diagnostics[Capture startup stderr tail]
Loading

Reviews (2): Last reviewed commit: "fix(exec): send EOF for non-interactive ..." | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant