Skip to content

feat(launching): detect and surface post-spawn launch failures - #340

Open
bobtista wants to merge 6 commits into
developmentfrom
feat/post-spawn-failure-detection
Open

feat(launching): detect and surface post-spawn launch failures#340
bobtista wants to merge 6 commits into
developmentfrom
feat/post-spawn-failure-detection

Conversation

@bobtista

@bobtista bobtista commented Jul 30, 2026

Copy link
Copy Markdown

Summary

Detect engine initialization failures both during startup and after a launch has been reported as running, preserving stderr evidence so users receive actionable errors.

Changes

  • Replace the fixed exit snapshot with bounded exit-or-settle detection and continuous stderr capture.
  • Recognize advisory [ggc] mount-failure sentinels and name affected archives.
  • Record late non-zero exits in the launch registry and surface them through the existing status, error, and notification channel.
  • Buffer unmatched exit events and synchronize buffering with real-PID registration to prevent the placeholder-registration race.
  • Apply exit events idempotently, including double delivery.
  • Mark requested termination before killing the process and classify it as a normal stop rather than a crash.

Testing

  • dotnet test GenHub/GenHub.sln -c Release — 1,461 tests passed.
  • Real native-client test collection passed.

Risks and rollback

The Windows system-modal crash dialog remains an engine-side limitation because the process does not exit while the dialog is open. A crash occurring immediately before a requested Stop may be classified as intentional termination; this tradeoff is documented. Reverting this PR restores the previous fixed-window behavior.

Related issues

Fixes #334

Greptile Summary

The PR expands launch-failure detection and propagation:

  • Watches newly spawned processes through a bounded startup window while continuously retaining bounded stderr output.
  • Extracts advisory archive-mount failure sentinels and includes affected archive names in launch errors.
  • Propagates late abnormal exits through process events, the launch registry, profile status, and user notifications.
  • Buffers unmatched exit events across placeholder-to-real-PID registration and applies them idempotently.
  • Marks requested process termination so deliberate stops are not reported as crashes.

Confidence Score: 4/5

The PR does not yet appear safe to merge because cancellation can orphan a spawned process, failed termination can suppress a later crash, and late exits update Avalonia-bound state from a worker thread.

A process started before the new cancellable settling wait is neither registered nor terminated when that wait is cancelled; requested-termination markers are not rolled back when killing fails; and the process-exit callback directly mutates observable UI state without dispatching to Avalonia's UI thread.

Files Needing Attention: GenHub/GenHub/Features/GameProfiles/Infrastructure/GameProcessManager.cs; GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs

Important Files Changed

Filename Overview
GenHub/GenHub/Features/GameProfiles/Infrastructure/GameProcessManager.cs Adds bounded startup-exit detection, persistent stderr capture, late-exit evidence, and requested-stop classification; cancellation and failed-kill lifecycle defects remain.
GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs Surfaces late process failures to profile state and notifications, but the callback still mutates UI-bound state from the process event thread.
GenHub/GenHub/Features/Launching/LaunchRegistry.cs Buffers unmatched PID exit events, synchronizes registration with event delivery, and records late failures idempotently.
GenHub/GenHub.Core/Models/Events/GameProcessExitedEventArgs.cs Extends process-exit events with stderr, archive details, requested-stop state, and centralized failure formatting.
GenHub/GenHub.Core/Models/GameProfile/GameLaunchInfo.cs Adds exit-code and late-failure state to in-memory launch records.

Sequence Diagram

sequenceDiagram
    participant UI as Launcher ViewModel
    participant Launcher as GameLauncher
    participant PM as GameProcessManager
    participant Registry as LaunchRegistry
    participant OS as Game Process

    Launcher->>Registry: Register placeholder launch (PID -1)
    Launcher->>PM: StartProcessAsync
    PM->>OS: Spawn process
    PM->>PM: Capture bounded stderr
    alt Exit during startup window
        OS-->>PM: Exit
        PM-->>Launcher: Failed start with exit details
    else Process outlives window
        PM-->>Launcher: Successful start with real PID
        Launcher->>Registry: Replace placeholder with real PID
        OS-->>PM: Late exit
        PM-->>Registry: ProcessExited
        PM-->>UI: ProcessExited
        Registry->>Registry: Record termination and failure
        UI->>UI: Clear running state and surface failure
    end
Loading

Reviews (3): Last reviewed commit: "fix(launching): classify requested termi..." | Re-trigger Greptile

Context used:

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • development

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e4093842-0c36-48d3-8b86-eb76da9b6e33

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kilo-code-bot

kilo-code-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 3
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

CRITICAL

File Line Issue
GenHub/GenHub/Features/GameProfiles/Infrastructure/GameProcessManager.cs 521 Stale requested-termination marker — when process.Kill fails or is cancelled after the marker is set, subsequent crashes are misclassified as intentional stops (reported by Greptile, re-verified on current HEAD)
GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs 1610 Worker-thread UI state updates — UI-bound StatusMessage/ErrorMessage updated from the process-exit worker thread without dispatching to the Avalonia UI thread (reported by Greptile, re-verified on current HEAD)
GenHub/GenHub/Features/GameProfiles/Infrastructure/GameProcessManager.cs 258 Cancellation orphans spawned process — token cancellation during the post-spawn wait leaves the already-started process running without management control (reported by Greptile, re-verified on current HEAD)

WARNING

File Line Issue
GenHub/GenHub/Features/Launching/LaunchRegistry.cs 30 Pending-exit retention (30 s) is orders of magnitude larger than the millisecond race gap it buffers; a buffered exit for a recycled PID can be falsely applied to a later, unrelated launch, marking it terminated/failed
Files Reviewed (11 files)
  • GenHub/GenHub.Core/Constants/ProcessConstants.cs
  • GenHub/GenHub.Core/Constants/RetailArchiveConstants.cs
  • GenHub/GenHub.Core/Models/Events/GameProcessExitedEventArgs.cs
  • GenHub/GenHub.Core/Models/GameProfile/GameLaunchInfo.cs
  • GenHub/GenHub/Features/GameProfiles/Infrastructure/GameProcessManager.cs - 2 issues
  • GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs - 1 issue
  • GenHub/GenHub/Features/Launching/LaunchRegistry.cs - 1 issue
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/GameProfiles/NativeClientLaunchIntegrationTests.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/GameProfiles/PostSpawnFailureDetectionTests.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/GameProfiles/ViewModels/GameProfileLauncherViewModelTests.cs
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/LaunchRegistryTests.cs

Note: The previous review SHA was rebased away, so this pass re-reviewed the full PR diff against current HEAD (f2eba92). The 3 CRITICAL findings were re-verified and remain open; the WARNING is newly reported. The PR's post-spawn failure detection, exit buffering, and requested-termination classification are otherwise well-structured and well-tested.

Fix these issues in Kilo Cloud

Previous Review Summary (commit 163343e)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 163343e)

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 3
WARNING 0
SUGGESTION 0
Issue Details (click to expand)

CRITICAL

File Line Issue
GenHub/GenHub/Features/GameProfiles/Infrastructure/GameProcessManager.cs 521 Stale requested-termination marker - when process.Kill fails or is cancelled after marker is set, subsequent crashes are misclassified as intentional stops
GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs 1608-1610 Worker-thread UI state updates - updating UI-bound properties from process-exit worker thread without dispatching to Avalonia UI thread
GenHub/GenHub/Features/GameProfiles/Infrastructure/GameProcessManager.cs 258 Cancellation orphans spawned process - token cancellation during post-spawn wait leaves process running without management control
Files Reviewed (11 files)
  • GenHub/GenHub.Core/Constants/ProcessConstants.cs - Added detection window constant
  • GenHub/GenHub.Core/Constants/RetailArchiveConstants.cs - Added sentinel constants
  • GenHub/GenHub.Core/Models/Events/GameProcessExitedEventArgs.cs - Added failure detection support
  • GenHub/GenHub.Core/Models/GameProfile/GameLaunchInfo.cs - Added failure tracking properties
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/GameProfiles/PostSpawnFailureDetectionTests.cs - Added comprehensive tests
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/GameProfiles/ViewModels/GameProfileLauncherViewModelTests.cs - Added UI tests
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/LaunchRegistryTests.cs - Added race condition tests
  • GenHub/GenHub/Features/GameProfiles/Infrastructure/GameProcessManager.cs - 3 CRITICAL issues - Added failure detection logic
  • GenHub/GenHub/Features/GameProfiles/ViewModels/GameProfileLauncherViewModel.cs - 1 CRITICAL issue - Added UI failure handling
  • GenHub/GenHub/Features/Launching/LaunchRegistry.cs - Added exit buffering and failure recording
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/GameProfiles/NativeClientLaunchIntegrationTests.cs - Updated test assertions

Note: All identified issues have already been reported by Greptile inline comments. No duplicate issues found. The PR makes significant improvements to post-spawn failure detection but has critical threading and error handling issues that need to be addressed.


Reviewed by glm-5.2 · Input: 106.7K · Output: 24.5K · Cached: 2M

@bobtista
bobtista force-pushed the feat/post-spawn-failure-detection branch from 163343e to f2eba92 Compare August 3, 2026 12:43
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 3, 2026
@bobtista
bobtista changed the base branch from feat/native-launch to development August 3, 2026 12:44
@bobtista
bobtista dismissed coderabbitai[bot]’s stale review August 3, 2026 12:44

The base branch was changed.

@bobtista

bobtista commented Aug 3, 2026

Copy link
Copy Markdown
Author

Rebased onto development and retargeted from feat/native-launch.

feat/native-launch was squash-merged as #332, so this PR was stacked on a branch that no longer exists in development's history. Retargeting alone would have produced a diff of 57 files, +1763/-3642 — one that deletes the work merged since #331 (#332, #337, #338, #339, #348, #349). That is the squash-orphaning failure #327 describes.

Instead the six commits unique to this branch were replayed onto development with git rebase --onto origin/development d1adeeb. No conflicts. The diff is now 11 files, +1297/-29 — this branch's own work and nothing else.

Verified after rebase: full core suite 1,553 passed, 0 failed.

No approvals existed, so nothing was dismissed by the force-push.

/// PIDs are recycled: an event held indefinitely could be applied to an unrelated
/// later launch that happened to receive the same PID.
/// </remarks>
private static readonly TimeSpan PendingExitRetention = TimeSpan.FromSeconds(30);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Pending-exit retention is far larger than the race it covers, so a buffered exit can be applied to a later, unrelated launch that recycles the PID.

PendingExitRetention is 30 s, but the gap it buffers (between StartProcessAsync returning and the launcher updating the placeholder entry with the real PID) is described above as milliseconds. Buffered exits are keyed by PID, and this PR explicitly targets Windows, where PIDs recycle. If a later launch is handed a PID that was recycled within the 30 s window, RegisterLaunchAsync drains the stale exit via TryRemove at line 118 and calls ApplyProcessExit, marking the unrelated (possibly still-running) launch as terminated/failed using the dead process exit code and stderr. A second consequence: a terminated launch is never removed from _activeLaunches, so its lingering PID makes OnProcessExited match the recycled-PID event against it (idempotency then drops it) instead of buffering it for the new launch. Tightening this to ~1-2 s still covers the millisecond race with a large margin while shrinking the recycling exposure by an order of magnitude.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

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