You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add in-process piped execution for WSLC state-aware sessions so the Rust,
.NET, and Node SDKs can run commands with programmatic stdout and stderr
without invoking an executor process.
The implementation:
routes state-aware piped exec through mxc_engine and the existing WSLC
state-aware backend
extends the WSLC daemon protocol to stream stdout, stderr, and the terminal
execution result
exposes the shared native path through the existing Rust, .NET, and Node
state-aware exec APIs
preserves timeout, cancellation, and typed terminal-result behavior
keeps control and lifecycle requests available when the daemon is at its
concurrent exec limit
rejects duplicate live exec IDs and safely cleans up completed registrations
reports terminal completion without blocking on caller-owned output pipes
quarantines sessions when process termination cannot be confirmed
fails explicitly instead of falling back to an executor process
flowchart LR
A[Rust / .NET / Node state-aware API] --> B[mxc-sdk or mxc_ffi]
B --> C[mxc_engine]
C --> D[WSLC state-aware backend]
D --> E[WSLC daemon client]
E <--> F[WSLC daemon]
F <--> G[Process in WSL container]
G -->|stdout / stderr / terminal result| F
F -->|stream frames| E
E -->|native pipe handles| A
A -->|cancel| E
Loading
mxc_engine remains the single backend-routing layer. The SDKs use the shared
native implementation and do not add backend-specific execution logic or an
executor fallback.
Current limitations
This adds piped streaming exec; it does not add the missing Node
attached-terminal API.
Windows Sandbox piped exec is not added by this change.
A live WSLC workload was not run on the development machine. Host-dependent
execution should be exercised by PR CI or on a WSLC-capable validation host.
If this PR changes Cargo.lock, the dependency-feed-check check passes (see docs/pull-requests.md)
📋 Issue Type
Bug fix
Feature
Task
GitHub Actions runs the PR validation build automatically. The ADO pipeline
(MXC-PR-Build) is the Azure version of the PR pipeline, kept in parity with
the GitHub Actions build; it runs on merge to main, and Microsoft reviewers
with write access can trigger it on a PR with /azp run. See docs/pull-requests.md.
If the dependency-feed-check check fails on a new dependency, the crate must
be added to the feed before the PR can pass. See docs/pull-requests.md
for the steps.
Prevent unread output from blocking completion, preserve control capacity under exec saturation, and make exec cancellation registration identity-safe.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bbe1ffbf-7cf8-48a0-8e3b-956f1d634e6c
Observe cancellation without an exit event, preserve unconfirmed-exit diagnostics, and cover capacity and cancellation dispatch through the request handler.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bbe1ffbf-7cf8-48a0-8e3b-956f1d634e6c
Keep the attached timeout limitation in the canonical WSLC backend guide instead of repeating it in each SDK README.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bbe1ffbf-7cf8-48a0-8e3b-956f1d634e6c
Adds capacity limits and terminal outcomes. Three moderate findings (1 vote each): queued execs can block lifecycle work; disconnects can release permits while executions continue; exec clients can consume the control reserve.
Cap the nonblocking daemon-to-pipe bridge, report truncation explicitly, and update the streaming capability test so ARM64 does not execute WSLC as a non-piped backend.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bbe1ffbf-7cf8-48a0-8e3b-956f1d634e6c
Consider creating an Issue to remove this "packet framing" code in the daemon+daemon_client, and rather expose native stdio handles from daemon process.
Keep exec IDs reserved through terminal frame delivery and gate the native piped bridge on Windows so non-Windows builds fail closed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bbe1ffbf-7cf8-48a0-8e3b-956f1d634e6c
The replay is the cancellation attempt that runs after admission when kill() raced with admit_exec, but its error is discarded. The initial pre-admission CancelExec can return Ok for an unknown ID; if this replay connection then fails, the daemon runs the command uncancelled and read_to_completion can block indefinitely for a no-timeout command. Preserve and handle this post-admission failure so a successful early cancel cannot make teardown assume the exec was stopped.
Reserve control capacity for cancellation and lifecycle traffic
CONTROL_CLIENT_RESERVE is not actually reserved for cancellation/lifecycle traffic: all accepted control handlers use the same client_limiter as execs. If eight long-running Stop/Deprovision requests are queued behind the single worker while exec slots are occupied, the next control connection (including CancelExec) is dropped at accept, so callers cannot cancel the running execs. Use a separate or prioritized control budget that blocked lifecycle handlers cannot consume.
The reason will be displayed to describe this comment to others. Learn more.
The new MAX_CONCURRENT_EXECS = 128 / CONTROL_CLIENT_RESERVE = 8 advertise concurrency the serialized worker can't deliver - the permits admit one running exec plus 127 waiters?
The reason will be displayed to describe this comment to others. Learn more.
The delete result is discarded but the container is removed from the map regardless, so a failed quarantine deletion leaves no handle to retry with and a possibly-running workload goes untracked?
The reason will be displayed to describe this comment to others. Learn more.
admit_exec reads its response with a bare read_frame instead of read_frame_with_deadline/call_timeout(), so a concurrent admission against the busy worker waits indefinitely with no client-side deadline?
The reason will be displayed to describe this comment to others. Learn more.
The new exec_id is deserialized from an ~16 MiB frame and retained several times (ExecConfig, registry key, Arc<ExecRegistration>), shall we bound it at deserialize?
The reason will be displayed to describe this comment to others. Learn more.
The new exec semantics are documented but four operator-visible behaviors are missing: quarantine on unconfirmed termination, the 128-exec ceiling plus 8 reserved control slots, duplicate exec-ID rejection, and bounded-output truncation. Do we need to document this?
The reason will be displayed to describe this comment to others. Learn more.
ProcessCompletion is hand-remapped into ExecCompletion and DaemonExecOutcome - three names for one shape, with TerminationUnconfirmed the only real addition and it never leaves the worker.
A shared ExecTerminal in daemon_protocol plus a daemon-local wrapper would collapse three mapping sites that must stay aligned?
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📖 Description
Goal
Add in-process piped execution for WSLC state-aware sessions so the Rust,
.NET, and Node SDKs can run commands with programmatic stdout and stderr
without invoking an executor process.
The implementation:
mxc_engineand the existing WSLCstate-aware backend
execution result
state-aware exec APIs
concurrent exec limit
flowchart LR A[Rust / .NET / Node state-aware API] --> B[mxc-sdk or mxc_ffi] B --> C[mxc_engine] C --> D[WSLC state-aware backend] D --> E[WSLC daemon client] E <--> F[WSLC daemon] F <--> G[Process in WSL container] G -->|stdout / stderr / terminal result| F F -->|stream frames| E E -->|native pipe handles| A A -->|cancel| Emxc_engineremains the single backend-routing layer. The SDKs use the sharednative implementation and do not add backend-specific execution logic or an
executor fallback.
Current limitations
attached-terminal API.
execution should be exercised by PR CI or on a WSLC-capable validation host.
🔗 References
🔍 Validation
git diff --checkpassed.PR CI or a WSLC-capable validation host.
✅ Checklist
Cargo.lock, thedependency-feed-checkcheck passes (see docs/pull-requests.md)📋 Issue Type
GitHub Actions runs the PR validation build automatically. The ADO pipeline
(
MXC-PR-Build) is the Azure version of the PR pipeline, kept in parity withthe GitHub Actions build; it runs on merge to
main, and Microsoft reviewerswith write access can trigger it on a PR with
/azp run. Seedocs/pull-requests.md.
If the
dependency-feed-checkcheck fails on a new dependency, the crate mustbe added to the feed before the PR can pass. See
docs/pull-requests.md
for the steps.
Microsoft Reviewers: Open in CodeFlow