Conversation
Contributor
|
This is pretty dicey. I'm going to have to think about this one 😓 |
Contributor
Author
|
@zachdaniel please let me know if you need me to do any additional validation or help with anything. |
This branch has not been deployed
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.
Fixes #403
Condition
mix igniter.upgraderuns the old version's<package>.upgradetask whenthe old version of that dep was compiled in the same VM before the upgrade.
This happens with a fresh or stale
_build, with or without theigniter_newarchive. With_buildalready compiled for the old lock, thenew task runs.
Cause
by
Mix.Task.run("compile", [])atlib/igniter/upgrades.ex:106.lib/igniter/util/install.ex:287-288runsmix deps.getandmix deps.compilein a separate OS process. The new.beamfiles landon disk; this VM keeps the old modules.
lib/igniter/upgrades.ex:189-193finds nothingstale, so nothing purges them.
Mix.Task.get(task)atlib/igniter/upgrades.ex:415returns the oldmodule.
Fix
After the recompile,
Igniter.Upgrades.upgrade/1unloads every loadedmodule whose
.beamlives in a changed dep'sebin, soMix.Task.get/1loads the new task from disk. It skips igniter and the deps it runs on
(
igniter,glob_ex,rewrite,sourceror,spitfire); upgrading thosealready raises earlier. That list moves into
@igniter_apps, shared withthe check.
It never kills a process. For each module it calls
:code.soft_purge/1and deletes the module only when that returns
true; after the delete itsoft-purges again, so a process running the deleted version keeps it.
Limit: when a process still runs a module's old code, the module stays
loaded as it is, so that module keeps the old version for this run. The
upgrade task's own modules run in no process, so they always reload.
Tests
Two new tests in
test/igniter/upgrades_test.exs:.beamto its ebin,calls
purge_stale_modules/1, and asserts version 2 runs. It failswithout the fix.
purge_stale_modules/1. It asserts the process is alive, the modulestill returns version 1, and the process exits normally. It fails with
:code.purge/1, which kills the process.mix test: 1 doctest, 441 tests, 0 failures.mix format --check-formatted,mix credo --strictandmix dialyzerpass. Elixir 1.18.4, OTP 27.Reproduction
A git dep with an upgrade task at two versions;
0.2.0adds a notice.Running
mix compilebeforemix igniter.upgradehides the bug.Contributor checklist