diff options
author | Fred Hebert <mononcqc@ferd.ca> | 2019-06-07 13:45:07 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-07 13:45:07 -0400 |
commit | 1328a9a2049bfd511554f21e608444c784b4e6d3 (patch) | |
tree | 33e3530b0ef3eb92ff12e40d431af30b83c20465 | |
parent | dec3aeb6c548452ff559b1c41717831f59e84201 (diff) | |
parent | a399fd0b3377b06a819733377a0b890d225ced48 (diff) |
Merge pull request #2099 from ferd/gracious-shell-reloading
Gracious loading of unloaded but blacklisted mods
-rw-r--r-- | src/rebar_agent.erl | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/src/rebar_agent.erl b/src/rebar_agent.erl index ed23fb7..b669ac4 100644 --- a/src/rebar_agent.erl +++ b/src/rebar_agent.erl @@ -167,7 +167,6 @@ maybe_show_warning(State) -> %% that makes sense. -spec refresh_paths(rebar_state:t()) -> ok. refresh_paths(RState) -> - RefreshPaths = application:get_env(rebar, refresh_paths, [all_deps, test]), ToRefresh = parse_refresh_paths(RefreshPaths, RState, []), %% Modules from apps we can't reload without breaking functionality @@ -201,18 +200,39 @@ refresh_path(Path, Blacklist) -> false -> refresh_path_do(Path, App); true -> - ?DEBUG("skipping app ~p, stable copy required", [App]) + refresh_path_blacklisted(Path) end end end. + refresh_path_do(Path, App) -> - Files = filelib:wildcard(filename:join([Path, "*.beam"])), - Modules = [list_to_atom(filename:basename(F, ".beam")) - || F <- Files], + Modules = mods_in_path(Path), ?DEBUG("reloading ~p from ~ts", [Modules, Path]), code:replace_path(App, Path), reload_modules(Modules). +%% @private blacklisted paths are not reloaded, but if they were not loaded +%% already, we try and ensure they are loaded once. This is a soft operation +%% that does not provoke crashes in existing processes, but hides issues +%% as seen in issue #2013 comments where some loaded modules that are currently +%% run by no processes get unloaded by rebar_paths, without being loaded back in. +refresh_path_blacklisted(Path) -> + Modules = [M || M <- mods_in_path(Path), not is_loaded(M)], + ?DEBUG("ensure ~p loaded", [Modules]), + code:add_pathz(Path), % in case the module is only in a new non-clashing path + _ = [code:ensure_loaded(M) || M <- Modules], + ok. + +%% @private fetch module names from a given directory that contains +%% pre-build beam files. +mods_in_path(Path) -> + Files = filelib:wildcard(filename:join([Path, "*.beam"])), + [list_to_atom(filename:basename(F, ".beam")) || F <- Files]. + +%% @private check that a module is already loaded +is_loaded(Mod) -> + code:is_loaded(Mod) =/= false. + %% @private parse refresh_paths option %% no_deps means only project_apps's ebin path %% no_test means no test path |