Skip to content

feat(wxc_common): add the sandbox execution interfaces (SandboxBackend / SandboxProcess / Runner)#554

Merged
MGudgin merged 1 commit into
microsoft:mainfrom
caarlos0:exec-interfaces
Jun 24, 2026
Merged

feat(wxc_common): add the sandbox execution interfaces (SandboxBackend / SandboxProcess / Runner)#554
MGudgin merged 1 commit into
microsoft:mainfrom
caarlos0:exec-interfaces

Conversation

@caarlos0

@caarlos0 caarlos0 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

📖 Description

Part 1 of 3 splitting #524 ("mxc-sdk lib crate") into reviewable, compile-ordered PRs. This PR adds the shared, no-pty sandbox execution interfaces to wxc_common that the containment backends and the new library crate build on. It is purely additive — no existing code path uses these yet, so behavior is unchanged.

  • SandboxProcess — a handle to a running sandboxed child: take_stdin / take_stdout / take_stderr, try_wait, id, kill (process-tree), and wait (drains untaken stdio, honors scriptTimeout), plus stdout/stderr closers for abandoning a backgrounded-descendant-held read without a kill.
  • SandboxBackendvalidate + spawn(request, logger, StdioMode) -> SandboxProcess + a diagnose_exit hook; StdioMode::{Pipes, Inherit}.
  • Runner<B> — the generic adapter bridging any SandboxBackend to the run-to-completion ScriptRunner (spawn Inherit, then wait).
  • StreamCloser, group_kill (Unix leader-first SIGKILL of the child's group), and wait_with_timeout (adaptive 1ms→50ms backoff poll).
  • interruptible_reader (Unix self-pipe + poll) and the Windows pipe helpers in process_util for out-of-band-cancelable streaming reads.
  • FailurePhase::Timeout so a timeout is distinguishable from other failures.

🔗 References

  • Splits feat: mxc-sdk lib crate #524. The library backends + executor binaries are migrated onto this surface in Part 2 (unify-backends), and the importable mxc-sdk crate lands in Part 3 (mxc-sdk). Review in that order.

🔍 Validation

  • cargo test -p wxc_common (macOS, toolchain 1.93): 268 pass.
  • cargo fmt --all -- --check and cargo clippy --all-targets -- -D warnings clean.
  • cargo check against x86_64-pc-windows-msvc and x86_64-unknown-linux-gnu; macOS consumer crates (seatbelt_common, mxc_darwin, mxc_pty) build unchanged (additive-safe).

✅ Checklist

📋 Issue Type

  • Bug fix
  • Feature
  • Task
Microsoft Reviewers: Open in CodeFlow

…d / SandboxProcess / Runner)

Introduce the shared, no-pty execution surface that the containment backends
and a future in-process library build on. Purely additive: no existing code
path uses these yet, so behavior is unchanged.

- `SandboxProcess` — a handle to a running sandboxed child: `take_stdin` /
  `take_stdout` / `take_stderr`, `try_wait`, `id`, `kill` (process-tree), and
  `wait` (drains any untaken stdio, honors `scriptTimeout`), plus stdout/stderr
  closers for abandoning a backgrounded-descendant-held read without a kill.
- `SandboxBackend` — `validate` + `spawn(request, logger, StdioMode) ->
  SandboxProcess` + a `diagnose_exit` hook; `StdioMode::{Pipes, Inherit}`.
- `Runner<B>` — the generic adapter bridging any `SandboxBackend` to the
  run-to-completion `ScriptRunner` (spawn `Inherit`, then `wait`).
- `StreamCloser`, `group_kill` (Unix leader-first SIGKILL of the child's group),
  and `wait_with_timeout` (adaptive 1ms->50ms backoff poll).
- `interruptible_reader` (Unix self-pipe + `poll`) and the Windows pipe helpers
  in `process_util` (`InterruptiblePipeReader` / `PipeReadCanceller` /
  `create_std_pipes`) for out-of-band-cancelable streaming reads.
- `FailurePhase::Timeout` so a timeout is distinguishable from other failures.

The library backends and executor binaries are migrated onto this surface in a
follow-up PR, and the importable `mxc-sdk` crate is built on top of it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds new cross-backend, handle-based (“streaming”) sandbox execution interfaces to wxc_common as the foundational API layer for follow-up backend unification and the forthcoming mxc-sdk Rust library crate. This is additive scaffolding intended to enable spawning and controlling sandboxed processes without a PTY.

Changes:

  • Introduces SandboxProcess / SandboxBackend traits plus a generic Runner<B> adapter to bridge to the existing ScriptRunner run-to-completion model.
  • Adds Unix + Windows primitives for interruptible pipe reads/stdio handling (self-pipe+poll on Unix; CancelIoEx-based cancellation for Windows pipes).
  • Extends FailurePhase with a dedicated Timeout phase and widens wxc_common’s libc dependency to all Unix targets.
Show a summary per file
File Description
src/core/wxc_common/src/sandbox_process.rs New public streaming execution traits/utilities and Runner<B> bridge, including Unix timeout polling and group kill helper.
src/core/wxc_common/src/process_util.rs Adds Windows pipe reader/writer types and an interruptible reader + StreamCloser implementation via CancelIoEx.
src/core/wxc_common/src/models.rs Adds FailurePhase::Timeout to distinguish timeout termination from normal non-zero exits.
src/core/wxc_common/src/lib.rs Wires new modules into the crate (sandbox_process, interruptible_reader) with appropriate platform gating.
src/core/wxc_common/src/interruptible_reader.rs New Unix interruptible reader using self-pipe + poll and a StreamCloser canceller.
src/core/wxc_common/Cargo.toml Expands libc dependency from Linux-only to all Unix targets to support new Unix-only modules/helpers.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 3

Comment on lines +209 to +210
/// [`wait`](SandboxProcess::wait), first cancelling its read so the join can't
/// block. When the stream was drained (a [`spawn_discard`] thread exists), fire
Comment on lines +248 to +253
// SAFETY: `kill(2)` with a plain pid / negative pgid — just integers.
unsafe {
libc::kill(pid, libc::SIGKILL); // leader first
libc::kill(-pid, libc::SIGKILL); // then its group
}
Ok(())
Comment on lines +405 to +410
Err(e) if e.kind() == std::io::ErrorKind::TimedOut => ScriptResponse {
exit_code: -1,
error_message: format!("script timed out after {}ms", request.script_timeout),
failure_phase: FailurePhase::Timeout,
..Default::default()
},
@MGudgin MGudgin merged commit ed7bb1c into microsoft:main Jun 24, 2026
18 checks passed
MGudgin pushed a commit that referenced this pull request Jun 24, 2026
This change adapts the Phase 2B strict-wire-model parser to two crates that
landed on main after 2B was branched, surfaced when rebasing 2B onto current
main: the new in-process `mxc-sdk` library crate (#556) and the
`load_request_from_value` entrypoint (#554/#556).

Details:
- config_parser.rs: port `load_request_from_value` (added on main against the
  deleted `RawConfig` API) to 2B's wire model — deserialize into
  `wire::MxcConfig` and call `convert_wire_config`, matching its sibling
  `load_request_with_options`.
- core/mxc-sdk/src/policy.rs: stop emitting `processContainer.name` (the wire
  `ProcessContainer` is strict and has no `name` field; the id is already carried
  at top-level `containerId`). Suppress the now-unused `container_id` in the
  Windows block.
- sdk/src/sandbox.ts: likewise stop emitting `processContainer.name`; drop the
  now-unused `containerId` parameter from `buildProcessBaseContainerConfig`.

Tests:
- cargo test --workspace -> all pass (the 6 mxc-sdk parse failures from the
  rejected `name` field are resolved).
- cargo fmt --check + cargo clippy --workspace -D warnings -> clean.
- schema codegen + corpus (169/169) + schema-version gates -> green.
- cd sdk && npm test -> 183 pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Generated-with: claude-opus-4.8
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.

3 participants