Keep wine session and component installs alive across screen lock#320
Keep wine session and component installs alive across screen lock#320maxjivi05 wants to merge 3 commits intoWinNative-Emu:mainfrom
Conversation
Add a foreground SessionKeepAliveService (dataSync, stopWithTask=false) that holds the app process alive while a wine session is in the background or while the setup wizard is downloading/installing components. Without it, locking the phone could let the OS reap the process and tear down a paused container, or interrupt an in-flight component install. XServerDisplayActivity starts the service in onCreate and stops it from exit() and performForcedSessionCleanup, so existing session teardown paths are unchanged. The service's onTaskRemoved runs the same terminateSessionProcessesAndWait + drainDeadChildren cleanup the exit path uses, so user swipe-away still closes the app cleanly with no zombie wine processes. SetupWizardActivity acquires a keep-alive tag around installImageFs, installAllRecommended, and installAdvancedComponent (released in finally) so screen lock cannot interrupt those operations.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 36211af52c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| com.winlator.cmod.runtime.system.SessionKeepAliveService.stopDownload( | ||
| applicationContext, | ||
| keepAliveTag, | ||
| ) |
There was a problem hiding this comment.
Release keep-alive tag in finally for advanced installs
stopDownload(...) is called only at the end of the coroutine, so any exception thrown before that point (for example during the post-install refresh calls) skips tag release and leaves activeDownloads populated for that URL. In that state, the keep-alive foreground service can remain active longer than intended, and a later install of the same component will not trigger a fresh start command because HashSet.add returns false. Wrap the whole lifecycleScope.launch body in try/finally so the stop call always runs.
Useful? React with 👍 / 👎.
Settings → Components and Settings → Drivers now wrap downloads and installs with SessionKeepAliveService.startDownload/.stopDownload, so locking the screen during a Wine/Proton/driver install doesn't tear the process down. The setup wizard already had this; the runtime entry points were missed. While in a game, the wine launcher's process.waitFor() callback or the Steam exit watch could call exit() while the activity was backgrounded — after a screen lock the user would unlock to "Closing Container..." and a torn-down session. Both async exit paths now defer when activityBackgrounded is true; onResume reconciles by checking ProcessHelper.listRunningWineProcesses() and only honors the deferred exit if no wine session processes remain. Spurious triggers (where the launcher waitFor returned but wine itself is still alive) are dropped and the session keeps running. Existing exit paths (drawer Exit, swipe-away cleanup, onDestroy/onStop) are unchanged.
Two changes that together let the user lock the phone for any duration and come back to a usable container: 1. Stop auto-pausing wine on activity onPause/onResume. Suspending wine processes for minutes-to-hours of screen-off time made them prime targets for the kernel OOM killer (and the cgroup freezer); the process death then surfaced as "Closing Container..." on unlock. Wine now keeps running while backgrounded, with the keep-alive foreground service holding the app process alive. The drawer "Pause all Wine processes" toggle is the only path that suspends wine and is still untouched. 2. When the user does manually pause wine, write /proc/[pid]/oom_score_adj=-1000 for each suspended process. That marks them as OOM_SCORE_ADJ_MIN so the kernel will not reap them on memory pressure during a long lock. Resume restores the default score before SIGCONT so a running wine session has normal priority. xServerView.onPause/onResume are still wired up so GL rendering pauses with the screen, and existing exit/teardown paths are unchanged.
Add a foreground SessionKeepAliveService (dataSync, stopWithTask=false) that holds the app process alive while a wine session is in the background or while the setup wizard is downloading/installing components. Without it, locking the phone could let the OS reap the process and tear down a paused container, or interrupt an in-flight component install.
XServerDisplayActivity starts the service in onCreate and stops it from exit() and performForcedSessionCleanup, so existing session teardown paths are unchanged. The service's onTaskRemoved runs the same terminateSessionProcessesAndWait + drainDeadChildren cleanup the exit path uses, so user swipe-away still closes the app cleanly with no zombie wine processes.
SetupWizardActivity acquires a keep-alive tag around installImageFs, installAllRecommended, and installAdvancedComponent (released in finally) so screen lock cannot interrupt those operations.