Skip to content

fix(steam): roll back failed proxy preparation - #304

Open
bobtista wants to merge 1 commit into
developmentfrom
fix/steam-proxy-rollback
Open

fix(steam): roll back failed proxy preparation#304
bobtista wants to merge 1 commit into
developmentfrom
fix/steam-proxy-rollback

Conversation

@bobtista

@bobtista bobtista commented Jul 27, 2026

Copy link
Copy Markdown

Summary

Prevent failed Steam proxy preparation from leaving the proxy installed.

Changes

  • Validate filesystem prerequisites before replacing the executable.
  • Roll back mutations after failures or cancellation.
  • Preserve pre-existing backups and artifacts.
  • Retain recovery files when rollback cannot safely proceed.
  • Add focused filesystem regression tests.

Testing

  • Release solution build passed.
  • All 1,228 tests passed.

Risks and rollback

Process termination can bypass managed rollback. File locks or concurrent changes may prevent restoration; recovery files are retained and reported.

Related issues

Fixes #303

Greptile Summary

The PR adds transactional filesystem handling for Steam proxy preparation.

  • Validates filesystem prerequisites before replacing the game executable.
  • Snapshots and rolls back executable, configuration, App ID, and dependency mutations after failures or cancellation.
  • Preserves recovery artifacts when executable restoration cannot safely proceed.
  • Adds focused filesystem regression tests for success, failure, cancellation, and conflict paths.

Confidence Score: 2/5

This PR should not merge until preparation is serialized per installation and preserved unrelated backups cannot be restored on a later launch.

Concurrent profiles can interleave mutations and invalidate each other's rollback state, while an unrelated backup preserved by a successful attempt is unconditionally restored during the next pre-launch cleanup.

Files Needing Attention: GenHub/GenHub/Features/Launching/SteamLauncher.cs

Important Files Changed

Filename Overview
GenHub/GenHub/Features/Launching/SteamLauncher.cs Adds transactional proxy preparation and rollback, but installation-wide attempts remain unsynchronized and stale preserved backups can later replace valid executables.
GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/SteamLauncherTests.cs Adds strong single-attempt filesystem regression coverage, but does not cover concurrent profiles or a successful preparation followed by cleanup with an unrelated backup.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Launch Steam profile] --> B[Pre-launch cleanup]
    B --> C[Validate prerequisites]
    C --> D[Snapshot executable and files]
    D --> E[Create or preserve backup]
    E --> F[Deploy proxy]
    F --> G[Write config and App ID]
    G --> H{Preparation completed?}
    H -->|Yes| I[Commit and launch]
    H -->|Failure or cancellation| J[Rollback mutations]
    J --> K{Executable unchanged?}
    K -->|Yes| L[Restore original and clean artifacts]
    K -->|No| M[Retain recovery files and report conflict]
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
GenHub/GenHub/Features/Launching/SteamLauncher.cs:207-211
**Installation mutations are not serialized**

When two profiles sharing a Steam installation launch concurrently, their separate per-profile locks allow both preparations to snapshot and mutate the same executable, backup, config, and App ID files. One rollback can then overwrite the surviving profile's configuration or delete the backup it requires, leaving the wrong launch configuration or an unrestorable proxy executable.

### Issue 2 of 2
GenHub/GenHub/Features/Launching/SteamLauncher.cs:540-548
**Stale backups become authoritative**

When an unrelated `.ghbak` already exists beside a valid executable, successful preparation preserves it without validation. The next launch's cleanup unconditionally replaces the current executable with that stale backup, after which preparation backs up the stale contents and the valid original is no longer recoverable.

Reviews (1): Last reviewed commit: "fix(steam): roll back failed proxy prepa..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

Context used:

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@bobtista, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 11 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 946a2430-2355-485f-9aa9-7a65f6116b1e

📥 Commits

Reviewing files that changed from the base of the PR and between 5ba2a51 and 2ad21f2.

📒 Files selected for processing (2)
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/SteamLauncherTests.cs
  • GenHub/GenHub/Features/Launching/SteamLauncher.cs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/steam-proxy-rollback

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.

Comment on lines +207 to +211
rollback = new PreparationRollback(
targetExePath,
backupPath,
proxySourcePath,
filesToCapture);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Installation mutations are not serialized

When two profiles sharing a Steam installation launch concurrently, their separate per-profile locks allow both preparations to snapshot and mutate the same executable, backup, config, and App ID files. One rollback can then overwrite the surviving profile's configuration or delete the backup it requires, leaving the wrong launch configuration or an unrestorable proxy executable.

Knowledge Base Used: Game Profiles and Launching

Prompt To Fix With AI
This is a comment left during a code review.
Path: GenHub/GenHub/Features/Launching/SteamLauncher.cs
Line: 207-211

Comment:
**Installation mutations are not serialized**

When two profiles sharing a Steam installation launch concurrently, their separate per-profile locks allow both preparations to snapshot and mutate the same executable, backup, config, and App ID files. One rollback can then overwrite the surviving profile's configuration or delete the backup it requires, leaving the wrong launch configuration or an unrestorable proxy executable.

**Knowledge Base Used:** [Game Profiles and Launching](https://app.greptile.com/genhub/-/custom-context/knowledge-base/community-outpost/genhub/-/docs/game-profiles-launching.md)

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +540 to +548
if (!File.Exists(_backupPath))
{
var backupStagingPath = CreateTemporaryPath(_backupPath);
_temporaryFiles.Add(backupStagingPath);
File.Copy(_targetExePath, backupStagingPath, overwrite: false);
File.Move(backupStagingPath, _backupPath, overwrite: false);
_temporaryFiles.Remove(backupStagingPath);
_backupCreated = true;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Stale backups become authoritative

When an unrelated .ghbak already exists beside a valid executable, successful preparation preserves it without validation. The next launch's cleanup unconditionally replaces the current executable with that stale backup, after which preparation backs up the stale contents and the valid original is no longer recoverable.

Prompt To Fix With AI
This is a comment left during a code review.
Path: GenHub/GenHub/Features/Launching/SteamLauncher.cs
Line: 540-548

Comment:
**Stale backups become authoritative**

When an unrelated `.ghbak` already exists beside a valid executable, successful preparation preserves it without validation. The next launch's cleanup unconditionally replaces the current executable with that stale backup, after which preparation backs up the stale contents and the valid original is no longer recoverable.

How can I resolve this? If you propose a fix, please make it concise.

{
var backupStagingPath = CreateTemporaryPath(_backupPath);
_temporaryFiles.Add(backupStagingPath);
File.Copy(_targetExePath, backupStagingPath, overwrite: false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL: Missing file existence check before copying target executable

The code attempts to copy _targetExePath without checking if it exists. This can fail when the target executable doesn't exist but the backup file does (e.g., after previous proxy deployment).

The validation in PrepareForProfileAsync (line 129) allows this scenario, so File.Copy(_targetExePath, backupStagingPath, overwrite: false) at line 544 will throw FileNotFoundException if _targetExePath doesn't exist.

Suggested change
File.Copy(_targetExePath, backupStagingPath, overwrite: false);
if (!File.Exists(_backupPath))
{
var backupStagingPath = CreateTemporaryPath(_backupPath);
_temporaryFiles.Add(backupStagingPath);
if (_targetInitiallyExisted)
{
File.Copy(_targetExePath, backupStagingPath, overwrite: false);
File.Move(backupStagingPath, _backupPath, overwrite: false);
_temporaryFiles.Remove(backupStagingPath);
_backupCreated = true;
}
}

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

@kilo-code-bot

kilo-code-bot Bot commented Jul 27, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

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

CRITICAL

File Line Issue
GenHub/GenHub/Features/Launching/SteamLauncher.cs 544 Missing file existence check before copying target executable
Files Reviewed (2 files)
  • GenHub/GenHub/Features/Launching/SteamLauncher.cs - 1 issues
  • GenHub/GenHub.Tests/GenHub.Tests.Core/Features/Launching/SteamLauncherTests.cs - 0 issues

Fix these issues in Kilo Cloud


Reviewed by glm-4.7 · Input: 63.2K · Output: 9.6K · Cached: 534.4K

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