Repository navigation
fix[closes #4820]: report failed dependency installers - #4904
Merged
mirkobrombin merged 3 commits intoOct 26, 2026
Merged
mirkobrombin merged 3 commits into
mirkobrombin merged 3 commits into
Conversation
Installing a dependency ran the installer through WineExecutor and ignored the outcome. Installers that live outside the bottle are launched through `wine start /wait`, and that path reported success as soon as the process had been started, so a dependency was recorded as installed even when its installer exited with an error. Let the caller ask WineExecutor to follow the exit status (`success_codes`). Start and MsiExec now return the launch result and WineProgram keeps the exit status of its last launch. The dependency install step fails when the installer exits with a status that is not 0, 1638, 1641, 3010 or 3011, or a code listed in the step's optional `success_codes`. A failed step makes the whole install fail, so the dependency is not recorded as installed and the existing failure UI is used. Wine reports exit statuses as a single byte, so codes are compared on their low byte, like the installer manager does. Without `success_codes`, WineExecutor behaves as before. bottles/backend/managers/dependency.py | 45 +++-- bottles/backend/wine/executor.py | 38 +++- bottles/backend/wine/msiexec.py | 2 +- bottles/backend/wine/start.py | 2 +- bottles/backend/wine/wineprogram.py | 7 +- .../manager/test_dependency_install.py | 167 ++++++++++++++++++ bottles/tests/backend/wine/test_executor.py | 131 ++++++++++++++ bottles/tests/backend/wine/test_start.py | 29 +++ 8 files changed, 403 insertions(+), 18 deletions(-) create mode 100644 bottles/tests/backend/manager/test_dependency_install.py
mirkobrombin
requested changes
Oct 26, 2026
mirkobrombin
left a comment
Member
There was a problem hiding this comment.
The exit-status handling is useful, but is_success_exit_code currently accepts negative subprocess return codes. For example, -62 is a killed process and (-62 & 0xff) equals the low byte of 3010, so it becomes a successful install. Please reject negative statuses before masking and add that regression case.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
A dependency whose installer fails was still reported as installed: the toast said
"dotnet35" installed, the dependency was added toInstalled_Dependenciesand the row showed Remove/Reinstall.I found two causes.
DependencyManager.__step_install_exe_msicallsWineExecutor.run()and throws the result away. And even if it had looked at it, dependency installers are downloaded toPaths.temp, outside the bottle, so they are launched throughwine start /wait(orMsiExecfor.msi), and those launch paths return success as soon as the process has been started. 4e5bdab added exit code handling for program installers, but dependencies never got it.What I changed:
WineExecutortakes an optionalsuccess_codes. When it is set, the result of an exe or msi launch follows the exit status of the installer. When it is not set (every other caller), nothing changes.Start.runandMsiExec.installreturn the launch result, andWineProgramkeeps the exit status of its last launch inreturncode, so the executor can see it.success_codesand fails when the installer exits with a status that is not accepted. The accepted ones are 0, 1638 (another version is already installed), 1641, 3010 and 3011 (done, restart needed), plus an optionalsuccess_codeslist on the step, same name as ininstaller.py.install()return a failure, so the dependency is not recorded as installed and the UI uses the existing "failed to install" state. The failure message now also says why (for exampleOne or more steps failed for dotnet35. Command exited with status 67.) and a failed download gets a message too.Wine passes the exit status to the host as one byte, so Windows codes above 255 arrive truncated (3010 becomes 194, 1603 becomes 67). I compare the low byte on both sides, like the
& 0xFFcheck from 4e5bdab. I did not reuse the cmd.exe batch wrapper from that commit, because installers here are host paths launched throughstart /unix, andstartdoes not setERRORLEVEL, so the wrapper would not see the full code either.Other steps (
register_dll,override_dll,set_register_key,register_fontand so on) also ignore their result. I left them alone on purpose: Wine's regsvr32 and reg often return non-zero for harmless reasons, so failing on them could break dependencies that work today. The program installer manager has the same unconditional-success launch forinstall_exe/install_msisteps ininstaller.py. I kept it out of this PR to keep it focused, and I'm happy to send it as a follow-up.Related issues
dotnet35installation fails #4818: thedotnet35failure the report uses as its example (closed as a duplicate). With this change that failure is reported instead of shown as installed.cab_extractfails. This does the same for exe/msi installer steps.Fixes #4820
Type of change
How Has This Been Tested?
success_codes), forStart/WineProgram, and forDependencyManager.install(failed installer is not recorded, message, prerequisites, download failure). The new dependency and executor tests fail onmainand pass with this change.DependencyManager.install) against a real Wine 11.20 prefix with a test installer that exits with a chosen code. Onmainevery code is reported as installed. With this change 0, 3010 and 1641 install, 1603 and 1 fail and are not recorded, 1603 installs when listed insuccess_codes, and a broken.msifails.Generative AI assistance
AI assistance: none