Clean up old update executables reliably#47057
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request aims to make PowerToys’ update cleanup more reliable by ensuring stale update installers (and related files) get deleted consistently, including after an update install completes and during normal app startup.
Changes:
- Run
updating::cleanup_updates()unconditionally on Runner startup (in a detached background thread). - Call
updating::cleanup_updates()after a successful install inInstallNewVersionStage2. - Add exception handling and error logging inside
updating::cleanup_updates().
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/runner/main.cpp |
Makes startup cleanup unconditional by always spawning a cleanup background thread. |
src/common/updating/updating.cpp |
Wraps cleanup logic in try/catch and logs failures instead of allowing exceptions to escape. |
src/Update/PowerToys.Update.cpp |
Invokes cleanup after a successful stage-2 install to remove leftover installer artifacts. |
| std::thread{ [] { | ||
| auto state = UpdateState::read(); | ||
| if (state.state == UpdateState::upToDate) | ||
| { | ||
| updating::cleanup_updates(); | ||
| } | ||
| updating::cleanup_updates(); | ||
| } }.detach(); |
There was a problem hiding this comment.
Calling updating::cleanup_updates() unconditionally at startup can delete the already-downloaded installer when UpdateState is readyToInstall. That leaves UpdateState pointing at a missing file, so the update flow can’t proceed (e.g., PowerToys.Update’s ObtainInstaller checks for the file and fails if it’s gone). Consider restoring a state gate (skip cleanup when an installer is pending), or enhance cleanup_updates to preserve the currently-referenced downloadedInstallerFilename when state==readyToInstall.
4051784 to
626d9c5
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/runner/main.cpp:559
- PR description says startup cleanup is now unconditional, but this code still skips cleanup when the state is
readyToInstallanddownloadedInstallerFilenameis set. Either update the PR description to reflect this (to avoid deleting a pending installer), or adjust the implementation to do a safe cleanup that preserves the pending installer instead of skipping cleanup entirely.
if (state.state != UpdateState::readyToInstall || state.downloadedInstallerFilename.empty())
{
updating::cleanup_updates();
}
} }.detach();
| if (err.value()) | ||
| auto entryPath = entry.path().wstring(); | ||
| std::transform(entryPath.begin(), entryPath.end(), entryPath.begin(), ::towlower); | ||
| if (entry.is_regular_file() && entryPath.ends_with(L".log") && entryPath.find(currentVersion) == std::string::npos) |
There was a problem hiding this comment.
entryPath and currentVersion are std::wstring, but the code compares find() against std::string::npos. This works due to the shared size_t type, but it’s confusing and easy to misread—use std::wstring::npos for consistency and clarity.
| if (entry.is_regular_file() && entryPath.ends_with(L".log") && entryPath.find(currentVersion) == std::string::npos) | |
| if (entry.is_regular_file() && entryPath.ends_with(L".log") && entryPath.find(currentVersion) == std::wstring::npos) |
- Make startup cleanup unconditional (remove upToDate state gate) - Add cleanup after successful install in InstallNewVersionStage2 - Add exception safety inside cleanup_updates() to protect all callers Fixes #46816
626d9c5 to
3e6fe88
Compare
Summary of the Pull Request
This pull request improves the update cleanup process in PowerToys by ensuring that old update files are reliably cleaned up after updates, and by making the cleanup code more robust against errors. The main changes include always invoking the cleanup routine, improving error handling, and simplifying the logic around when cleanup occurs.
Update cleanup improvements:
updating::cleanup_updates()function is now always called after an update is installed inInstallNewVersionStage2, ensuring old update files are consistently removed.updating::cleanup_updates()inmain.cpphas been simplified to always run in a background thread, regardless of the update state, ensuring cleanup is not skipped.Error handling enhancements:
cleanup_updates()function now wraps its logic in a try-catch block and logs errors if exceptions occur, making the cleanup process more robust and easier to debug. [1] [2]- Make startup cleanup unconditional (remove upToDate state gate)This pull request improves the update cleanup process by ensuring that old update files are always cleaned up, regardless of the update state, and adds error handling and logging to the cleanup logic. The most important changes are:
Fixes #46816
PR Checklist
Detailed Description of the Pull Request / Additional comments
Validation Steps Performed