Repository navigation
[WSLC] (1/2) Set operation and nativeCode on container lifecycle errors - #1671
Soham Das (SohamDas2021) wants to merge 2 commits into
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
🟡 Changes recommended
When timeout or cancellation leaves termination unconfirmed, a WslcGetProcessExitCode failure is only logged, causing quarantine to lose or misattribute the original SDK error details.
1 open issue
What changed in this PR
This PR extends WSLc’s existing lifecycle error classification to carry the failing SDK function and HRESULT through the daemon to callers, addressing part of #1644.
Changes:
- Propagates structured failure details through session, container, image-pull, and exec operations.
- Bumps the internal daemon protocol from 9 to 10 and documents upgrade implications.
- Adds propagation tests and extends the live port-collision regression checks.
| File | Description |
|---|---|
tests/scripts/run_wslc_state_aware_tests.ps1 |
Checks operation and HRESULT for port collisions. |
src/mxc-sdk/src/bin/wslc_daemon/session_manager.rs |
Carries failure details through workers and quarantine handling. |
src/mxc-sdk/src/bin/wslc_daemon/control_server.rs |
Includes failure details in daemon replies and exec frames. |
src/mxc-sdk/src/backends/wslc/common/wsl_container_runner.rs |
Converts step errors to existing create-and-run responses. |
src/mxc-sdk/src/backends/wslc/common/state_aware.rs |
Maps daemon failure details into lifecycle errors. |
src/mxc-sdk/src/backends/wslc/common/image.rs |
Attaches operation and status details to image failures. |
src/mxc-sdk/src/backends/wslc/common/error.rs |
Introduces a step error carrying structured diagnostics. |
src/mxc-sdk/src/backends/wslc/common/daemon_protocol.rs |
Adds failure payloads and advances the protocol version. |
src/mxc-sdk/src/backends/wslc/common/daemon_client.rs |
Preserves diagnostics when receiving daemon errors. |
src/mxc-sdk/src/backends/wslc/common/container_steps.rs |
Records SDK call names and HRESULTs in step failures. |
docs/development/architecture/container-lifecycle.md |
Documents WSLc diagnostic-field availability. |
docs/backends/wslc/wslc-state-aware.md |
Describes structured errors and protocol version 10. |
Review effort: Balanced
Gudge (MGudgin)
left a comment
There was a problem hiding this comment.
Summary
Filing findings 1 and 2 only, both Medium and nonblocking. Rechecked against head 08eb260cc959afe5766789a414fc37073e417c6f and merge-base 92e767a8278c785892c07d8bada456174f199405; both inline anchors are added lines. This is a static review, not an approval or a claim that local tests were run.
Verified behavior
WorkerError::kind()andDisplaycurrently handle both the dedicated variants andStep(src/mxc-sdk/src/bin/wslc_daemon/session_manager.rs:212-251). Finding 1 concerns overlapping representations, not an observed misclassification.- Quarantine already preserves original API detail when present and falls back to deletion detail only when absent (
src/mxc-sdk/src/bin/wslc_daemon/session_manager.rs:2618-2663, specificallyapi_failure.or(delete_error.api_failure)). Finding 2 concerns detail lost before reaching that code, not incorrect quarantine precedence or cleanup.
Findings outside the diff
None filed separately; finding 2 is anchored on the added metadata consumer and explains its dependency on unchanged helper branches.
Verified pre-existing behavior - not charged as new behavior
- The log-only
WslcSignalProcess/ unconfirmedWslcGetProcessExitCodebranches and the finalpost_launch_error: Nonealready exist at the merge-base. They are not alleged to be newly broken kill or cleanup behavior. Finding 2 isnewly_exposed_by_change: this PR adds structured SDK-failure propagation, but these existing producers leave a gap in that new behavior. No standalonepre_existingfinding or merge condition is being posted.
Attribution ledger: finding 1 kept as introduced_by_change; finding 2 kept as newly_exposed_by_change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

📖 Description
When a WSLc container lifecycle operation failed in a WSLc SDK call, the error named the call and its HRESULT only inside
message. ItsoperationandnativeCodefields stayed empty, so a caller had to parse the message to tell, for example, a host port already in use from any other start failure.WSLc container lifecycle errors now fill both fields when a WSLc SDK call fails:
operationis the SDK function andnativeCodeis its HRESULT. Starting a container whose host port is already in use returnsbackend_errorwithoperationWslcStartContainerandnativeCode0x80072740.operationWslcPullSessionImagewithoutnativeCode, because no HRESULT exists.WslcSignalProcess) or read its exit code (WslcGetProcessExitCode), unless an earlier SDK call in that exec already failed.Error codes, messages, exit codes, and create-and-run results are unchanged.
The WSLc daemon protocol version changes from 9 to 10. A client refuses a running daemon from an older version, so upgrading means letting that daemon idle out or stopping it, which ends the containers it holds.
The lifecycle error contract now lists WSLc as filling
operationandnativeCode, and the WSLc lifecycle guide describes the fields and the new protocol version.No spec is required: the fields already exist in the error contract, and the daemon protocol is internal to the WSLc backend.
Limitation: errors from waiting on a process started in a container through the Rust, .NET, and Node SDK process APIs still lack these fields. That is planned as a follow-up PR for #1644.
🔗 References
Refs #1644
Follows #1240, which carried the failure's classification across the WSLc daemon protocol but not the failing call or its status.
🔍 Validation
Run on Windows 11 (build 26300, x64) with WSL 3.0.5. Cargo commands run from
src.cargo fmt --all -- --check: passed.cargo clippy -p mxc-sdk --all-targets --features wslc -- -D warnings: passed.cargo test -p mxc-sdk --lib --features wslc: 2,944 passed, 8 ignored.cargo test -p mxc-sdk --bin wxc-wslc-daemon --features wslc: 178 passed, 13 ignored.cargo test -p mxc-sdk --test wslc_daemon_ipc --features wslc: 1 passed, 3 ignored.Live WSL2 host, with a release build from
cargo build --features wslc --release --target x86_64-pc-windows-msvc:pwsh -File tests\scripts\run_wslc_all_tests.ps1 -WxcExecPath src\target\x86_64-pc-windows-msvc\release\wxc-exec.exe: all 50 results passed. That is 49 create-and-run results and the lifecycle suite, which passed 140 of 140 checks, including the port-collision checks forbackend_error,operationWslcStartContainer, andnativeCode0x80072740.cargo test -p mxc-sdk --bin wxc-wslc-daemon --features wslc -- --ignored --test-threads=1 --skip measure_whether_session_sizing_reserves_or_caps --skip a_session_larger_than_the_host_is_refused: 11 passed. The oversize-session test passed on its own with--ignored --exact session_manager::tests::a_session_larger_than_the_host_is_refused. The sizing measurement was not run, since it reports figures rather than checking behavior.cargo test -p mxc-sdk --test wslc_daemon_ipc --features wslc -- --ignored --test-threads=1: 3 passed.cargo test -p mxc-sdk --lib --features wslc -- --ignored --test-threads=1 store_slots::host_tests filesystem_probe::launch_tests::: 7 passed.cargo test -p mxc-sdk --features wslc --test wslc_stdin_handle_probe -- --ignored --nocapture --test-threads=1: 1 passed.wslcsdk.dllfrom beside the test binary, so it was copied fromtarget\debugintotarget\debug\depsfirst.sdk\node\tests\integrationwithMXC_ENABLE_WSLC_TESTS=1:node --test --test-force-exit --test-reporter=spec --test-reporter-destination=stdout dist/wslc-state-aware.test.jspassed 2 of 2, and the same command withdist/wslc-e2e.test.jspassed 8 of 8. None were skipped.dotnet publish sdk\dotnet\Microsoft.Mxc.Sdk.Tests\Microsoft.Mxc.Sdk.Tests.csproj -c Release -f net10.0 -r win-x64 -p:MxcWithIsolationSession=true -p:MxcWithWslc=true -p:MxcTestPrebuiltNativeLibrary=<mxc_ffi.dll> --self-contained true -o <out>, thenMicrosoft.Mxc.Sdk.Tests.exe -class *.MxcLifecycleWslcE2ETests -class *.MxcContainerWslcE2ETests -result-xml <file>withMXC_ENABLE_WSLC_TESTS=1: 20 passed, none skipped. The test project's own native build failed inrc.exeunder MSBuild on this machine, so its command,cargo build -p mxc_ffi --features "dotnetsdk test-support isolation_session wslc" --target x86_64-pc-windows-msvc --target-dir target\dotnet-test-support, was run directly and itsmxc_ffi.dllpassed in.Windows CI commands, with
CARGO_TARGET_DIRset to a short path because this worktree's path pushes the hyperlight helper build past the Windows path length limit:cargo test --locked --release --target x86_64-pc-windows-msvc --no-default-features --features "hyperlight isolation_session microvm wslc": passed. 4,935 passed and 64 ignored across 54 test binaries, including doc tests.cargo clippy --target x86_64-pc-windows-msvc --locked --all-targets --all-features --release -- -D warnings: passed.✅ Checklist
feature-acceptedCargo.lock, thedependency-feed-checkcheck passes (see pull request builds)📋 Issue Type
Microsoft Reviewers: Open in CodeFlow