Skip to content

fix: kill stale wine processes before launch#1195

Open
xXJSONDeruloXx wants to merge 4 commits intoutkarshdalal:masterfrom
xXJSONDeruloXx:fix/prelaunch-kill-orphan-wine-procs
Open

fix: kill stale wine processes before launch#1195
xXJSONDeruloXx wants to merge 4 commits intoutkarshdalal:masterfrom
xXJSONDeruloXx:fix/prelaunch-kill-orphan-wine-procs

Conversation

@xXJSONDeruloXx
Copy link
Copy Markdown
Contributor

@xXJSONDeruloXx xXJSONDeruloXx commented Apr 12, 2026

Description

fixes the case where users swipe app away while a game is running, then relaunch the app to have infinite booting screen because a stray wine proc is running. This acts as a hammer to see if any wine pros exist on a game launch, and clear them out if exists.

Recording

Checklist

  • If I have access to #code-changes, I have discussed this change there and it has been green-lighted. If I do not have access, I have still provided clear context in this PR. If I skip both, I accept that this change may face delays in review, may not be reviewed at all, or may be closed.
  • I have attached a recording of the change.
  • I have read and agree to the contribution guidelines in CONTRIBUTING.md.

Summary by cubic

Kill stale Wine processes before starting the X environment and wait up to 5s for them to exit to prevent conflicts. Also blocks Back during prelaunch so cleanup can finish; fails fast if any Wine PIDs remain.

  • Bug Fixes
    • Centralized prelaunch cleanup in ProcessHelper.hardKillStaleWineProcesses(); XServerScreen calls it before starting X. Sends SIGKILL to Wine PIDs, waits up to 5s, logs warnings, and throws if any remain.
    • Added ProcessHelper.killProcess, ProcessHelper.killAllWineProcesses, and ProcessHelper.hardKillStaleWineProcesses to support the cleanup.
    • Blocked Back via BackHandler in PluviaMain while the loading dialog is visible and SteamService.keepAlive is false to avoid interrupting prelaunch.

Written for commit ea948b5. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes
    • Improved launch stability by forcibly clearing stale Wine processes before startup, waiting briefly to confirm they exit; launch aborts and logs a warning if they persist.
  • New Features
    • Disabled the back action while the loading dialog is visible to prevent accidental interruption during startup.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c21fdc2f-745a-42c2-bf06-b2a6efc657bd

📥 Commits

Reviewing files that changed from the base of the PR and between d9dbf7e and ea948b5.

📒 Files selected for processing (2)
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/com/winlator/core/ProcessHelper.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/com/winlator/core/ProcessHelper.java

📝 Walkthrough

Walkthrough

Adds new hard-kill APIs to ProcessHelper (killProcess, killAllWineProcesses, hardKillStaleWineProcesses) and invokes hardKillStaleWineProcesses at the start of XServerScreen.setupXEnvironment(...). Also adds a BackHandler in PluviaMain to suppress Back while a loading dialog is visible.

Changes

Cohort / File(s) Summary
Process Termination Utilities
app/src/main/java/com/winlator/core/ProcessHelper.java
Added killProcess(int), killAllWineProcesses() and hardKillStaleWineProcesses(). hardKillStaleWineProcesses() enumerates Wine PIDs, logs them, calls killAllWineProcesses(), polls every 100ms up to 5s for remaining PIDs, and throws IllegalStateException if any persist; declared to throw InterruptedException.
Pre-launch cleanup (XServer)
app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
Calls ProcessHelper.hardKillStaleWineProcesses() at the very start of setupXEnvironment(...) to remove stale Wine processes before further environment setup.
UI Navigation Handling
app/src/main/java/app/gamenative/ui/PluviaMain.kt
Adds a BackHandler active when state.loadingDialogVisible && !SteamService.keepAlive to suppress default Back behavior while loading (handler body TODO).

Sequence Diagram

sequenceDiagram
    participant XServer as XServerScreen
    participant Helper as ProcessHelper
    participant OS as OS_Process_Manager

    XServer->>XServer: setupXEnvironment()
    XServer->>Helper: hardKillStaleWineProcesses()
    Helper->>OS: listRunningWineProcesses()
    OS-->>Helper: current Wine PIDs
    Helper->>Helper: log stale PIDs (if any)
    Helper->>OS: killProcess(pid) for each PID (SIGKILL)
    OS-->>Helper: kill acknowledgements / process state
    Helper->>OS: poll listRunningWineProcesses() every 100ms (<=5s)
    OS-->>Helper: remaining PIDs (empty or non-empty)
    alt no remaining PIDs
        Helper-->>XServer: completion
        XServer->>XServer: continue setup
    else remaining PIDs after timeout
        Helper-->>XServer: throw IllegalStateException (remaining PIDs)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐇 I sniff the midnight PIDs,
A gentle hop, a thunderous SIG,
I count, I chase, I hush the list,
No stale Wine left to beg or dig.
Now systems clear — let games run big!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: killing stale wine processes before game launch.
Description check ✅ Passed The description explains the bug being fixed and the solution approach, but lacks a recording and leaves checklist items incomplete as noted in PR objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@xXJSONDeruloXx xXJSONDeruloXx marked this pull request as ready for review April 13, 2026 00:34
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt`:
- Around line 2551-2561: The current code calls
ProcessHelper.killAllWineProcesses() then immediately re-scans via
ProcessHelper.listRunningWineProcesses() and only logs any remaining PIDs;
change this to poll until no wine PIDs remain or a short timeout elapses: after
calling ProcessHelper.killAllWineProcesses() repeatedly call
ProcessHelper.listRunningWineProcesses(), parse to ints (as in
remainingWinePids), and if non-empty sleep briefly (e.g., 100–500ms) and retry
with a total timeout (e.g., 3–10s) and exponential/backoff cap; if the set
becomes empty continue, otherwise fail the launch path (throw an exception or
return a failed Result) instead of just Timber.w, and keep the Timber.w/logging
for diagnostics when timing out.

In `@app/src/main/java/com/winlator/core/ProcessHelper.java`:
- Around line 50-53: The current killAllWineProcesses() calls killProcess(pid)
for every PID returned by listRunningWineProcesses(), but that scanner is too
broad; update listRunningWineProcesses() to only return PIDs that are owned by
this app's UID and whose executable/comm is an exact "wine" or whose filename
ends with ".exe" (no substring matches like "exe" or "wine" inside other names).
To implement: read /proc/<pid>/status or use ProcessHandle/Posix API to compare
the process UID to the current process UID, and read /proc/<pid>/comm or
/proc/<pid>/exe to check for exact name or suffix; then have
killAllWineProcesses() only call killProcess(pid) on those validated PIDs
(optionally prefer a graceful SIGTERM before SIGKILL inside killProcess()).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 44750659-7da4-4c1b-a6e5-31896a5d532d

📥 Commits

Reviewing files that changed from the base of the PR and between f3e8d53 and e61abec.

📒 Files selected for processing (2)
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/com/winlator/core/ProcessHelper.java

Comment thread app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt Outdated
Comment thread app/src/main/java/com/winlator/core/ProcessHelper.java
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/app/gamenative/ui/PluviaMain.kt`:
- Around line 1100-1102: Back press is currently swallowed by BackHandler when
state.loadingDialogVisible is true and SteamService.keepAlive is false;
implement a safe cancel/timeout fallback so Back can restore normal behavior:
add a cancellable prelaunch signal (e.g., a MutableState or Job started when
state.loadingDialogVisible becomes true via LaunchedEffect or
rememberCoroutineScope) and in the BackHandler callback cancel that job and set
state.loadingDialogVisible = false (or call your prelaunch cancellation
routine), and also launch a timeout coroutine (e.g., 30s) when showing the
dialog that will clear state.loadingDialogVisible if prelaunch doesn't complete;
reference BackHandler, state.loadingDialogVisible and SteamService.keepAlive
when locating where to wire the cancel() call and timeout.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0b66c21d-4342-4541-affb-a27271282272

📥 Commits

Reviewing files that changed from the base of the PR and between b106e51 and d9dbf7e.

📒 Files selected for processing (1)
  • app/src/main/java/app/gamenative/ui/PluviaMain.kt

Comment thread app/src/main/java/app/gamenative/ui/PluviaMain.kt
return environment
}

private fun hardKillStaleWineProcessesBeforeLaunch() {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

remove from XServerScreen, it could be in processhelper or somewhere else. Generally we should not be adding to this file, it's already very bloated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

}
}

public static void killAllWineProcesses() {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

we already have terminateAllWineProcesses is that not enough?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

thats the whole point, sigterm seems ignored in some cases, so sigkill is more aggressive which it needs to be on anything that remains in this state

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.

2 participants