Skip to content

Gate the managed-local provenance probe so it cannot start wsl.exe during Windows session teardown #1572

Open

Description

@petruslin

What

During a Windows session-end sequence the tray can still create a wsl.exe child process. At that point process creation fails with STATUS_DLL_INIT_FAILED (0xc0000142) and Windows shows an Application Error dialog; the same failure is recorded in the System log as Application Popup, Event ID 26.

This issue covers one production file: the process-start boundary of the managed-local gateway port-provenance probe.

Split out of #1571. #1571 keeps the full evidence trail (the 16-day Event 26 burst census, tray log excerpts, the five mid-session bursts, the family split against the unrelated XLGuard.sys popup). Read #1571 for evidence; this issue is the narrow job.

Where

src/OpenClaw.Connection/ManagedLocalGatewayPortProvenanceService.cs

  • IsExpectedWslGatewayListening is declared on the interface at :32 and implemented at :97.
  • The probe is started at :102: using var process = Process.Start(probe.StartInfo);
  • The ProcessStartInfo is built by CreateExpectedWslGatewayProbe at :120–:124.
  • There is a second start in the same file at :213 (process = Process.Start(psi);, psi built at :202).
  • Callers inside the same file: :334, :361, :389, :419.
  • Neither start consults any Windows session-ending signal. Searches across src/, tests/ and docs/ find no SessionEnding, WM_ENDSESSION, WM_QUERYENDSESSION, SM_SHUTTINGDOWN or HasShutdownStarted implementation.

Scope — deliberately one file

  • Change only the process-start boundary in ManagedLocalGatewayPortProvenanceService.cs.
  • Do not touch docs/, settings or configuration, schema, or any other project.
  • Do not change the reconnect loop (src/OpenClaw.Shared/WebSocketClientBase.cs) or the keep-alive path (src/OpenClaw.Tray.WinUI/App.xaml.cs); those are tracked as separate follow-up issues.
  • Do not refactor AppShutdownCoordinator or the existing ordered-shutdown design recorded in docs/ARCHITECTURE.md.
  • Do not add a new user-facing setting.

A previous single issue covering all three spawn paths produced an autonomous fix artifact that spanned three subsystems and was rejected upstream as too broad for autonomous execution. Keeping this to one file is the point of the split.

Required behaviour

  1. Once the process has observed that the Windows session is ending, IsExpectedWslGatewayListening must return without creating a process — no Process.Start, so no wsl.exe, so no 0xc0000142 and no Event 26.
  2. The same applies to the second start at :213.
  3. Behaviour when no session end is in progress must be unchanged, including the existing "no Windows listener remains, check WSL" path.
  4. The session-ending signal must be an injected abstraction (an interface or delegate the probe consults), not a direct static call, so a unit test can force "session ending" without shutting Windows down.
    • Wiring a concrete Windows session-end source (WM_QUERYENDSESSION / WM_ENDSESSION on the tray window, or SystemEvents.SessionEnding) is out of scope here and belongs to a follow-up. This issue only needs the seam plus a safe default.
    • Do not use Environment.HasShutdownStarted as the whole answer; on its own it is not reliable evidence that a Windows session-end sequence is in progress.
  5. The refusal must be observable in the log at the point of refusal (one line is enough), so a future report can be diagnosed from the tray log alone.

Acceptance

./build.ps1
dotnet test ./tests/OpenClaw.Connection.Tests/OpenClaw.Connection.Tests.csproj --no-restore

Required regression test

In tests/OpenClaw.Connection.Tests, a test that:

  • substitutes a session-ending signal that reports "ending",
  • calls IsExpectedWslGatewayListening,
  • asserts that no process was started.

Assert on the injected seam (the process-runner / start-info factory), not on a real wsl.exe — the test must pass on a machine with no WSL and must not launch anything.

What I can and cannot contribute

  • I can confirm the reported behaviour on Windows 11 Home China build 10.0.26300 with OpenClaw Companion 2026.9.4.0, and I can supply Event 26 / Event 1074 timelines and tray-log excerpts on request.
  • I do not have a working build environment for this repository, so I cannot run ./build.ps1 or the test projects. Someone else needs to verify.

Activity

  1. added
    P2Normal priority bug or improvement with limited blast radius.
    clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.
    clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.
    clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.
    impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.
    issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.
    no-staleExempts this issue from stale automation.
    on Oct 1, 2026
  2. clawsweeper commented on Oct 1, 2026

    @clawsweeper

    Codex review: this still needs some work. Reviewed October 1, 2026, 9:02 AM ET / 13:02 UTC.

    Summary
    The process-start guard remains absent on current main and in v2026.9.4. This narrowly scoped prerequisite is still useful; no open PR was found owning the shutdown guard.

    Likely related people: bkudiess and shanselman are medium-confidence routing candidates from merged connection work.

    Reproducibility: yes. for the source-level admission gap: reachable reconnect authorization invokes a platform that starts processes without observing session teardown. The Windows 0xc0000142 race was reported with event timelines but was not independently reproduced.

    Root-cause cluster
    Relationship: partial_overlap
    Canonical: #1571
    Summary: The parent retains the evidence for session-teardown launches; this issue owns one deliberately separated process-start boundary.

    Members:

    Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

    Next step
    A focused launch-admission repair has clear source boundaries and deterministic validation; establish failing regression coverage before implementing the seam.

    Review details

    Best possible solution:

    Gate both launch boundaries through injected lifecycle state, preserve failed-proof semantics, and connect the shared production signal in a separate focused follow-up.

    Do we have a high-confidence way to reproduce the issue?

    Yes for the source-level admission gap: reachable reconnect authorization invokes a platform that starts processes without observing session teardown. The Windows 0xc0000142 race was reported with event timelines but was not independently reproduced.

    Is this the best way to solve the issue?

    Yes as a staged boundary repair: injected lifecycle and process-start seams allow deterministic zero-launch regression coverage within the requested scope. Real shutdown protection still needs the separately deferred production signal.

    AGENTS.md: found and applied where relevant.

    Remaining risk / open question:

    • Concrete Windows session-end detection and production wiring are explicitly deferred; landing this seam alone cannot establish that real shutdown popups are fixed.

    Codex review notes: model internal, reasoning medium; reviewed against f4122a8927e7.

    Label changes

    Label changes:

    • add P2: The reported shutdown dialogs are alarming but do not prevent the gateway from working after reboot.
    • add impact:ux-friction: Background process launches can produce confusing Windows application-error dialogs during ordinary shutdown.
    • add issue-rating: 🦞 diamond lobster: Current issue advisory state selects this label.
    • add clawsweeper:source-repro: Current issue advisory state selects this label.
    • add clawsweeper:queueable-fix: Current issue advisory state selects this label.
    • add clawsweeper:fix-shape-clear: Current issue advisory state selects this label.

    Label justifications:

    • P2: The reported shutdown dialogs are alarming but do not prevent the gateway from working after reboot.
    • impact:ux-friction: Background process launches can produce confusing Windows application-error dialogs during ordinary shutdown.
    Evidence reviewed

    Acceptance criteria:

    • ./build.ps1
    • dotnet test ./tests/OpenClaw.Shared.Tests/OpenClaw.Shared.Tests.csproj --no-restore
    • dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --no-restore
    • dotnet test ./tests/OpenClaw.Connection.Tests/OpenClaw.Connection.Tests.csproj --no-restore
    • Establish a failing regression before the fix; assert zero injected process-start invocations for both launch boundaries when session-ending is true.

    What I checked:

    Likely related people:

    • bkudiess: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
    • shanselman: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
    How this review workflow works
    • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
    • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
    • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
    • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
    • Maintainers can also comment @clawsweeper review to request a fresh review only.
    • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
    • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
    • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
  3. petruslin commented on Oct 1, 2026

    @petruslin
    Author

    There is now a shared session-ending contract to code against

    Filed as reporter: #1575 — Provide one shared Windows session-ending signal and wire it for production use.

    This issue's text asks for an injected session-ending abstraction and then explicitly puts the concrete Windows source out of scope, deferring it to a follow-up. #1575 is that follow-up. It owns the contract, the Windows implementation, and the production wiring; it deliberately does not touch any of the three consumer call sites (#1572, #1573, #1574).

    So the shape of this one is unchanged but its dependency is now concrete:

    #1575 also asks for the transition and not only a latched state, which matters here: declining as early as possible is preferable, and a latched flag that only becomes visible after teardown has begun may be read too late.

    Nothing here requires a maintainer decision, so this one can proceed as soon as #1575 lands.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal priority bug or improvement with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.no-staleExempts this issue from stale automation.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions