diff options
-rw-r--r-- | erts/emulator/beam/beam_bif_load.c | 18 | ||||
-rw-r--r-- | lib/kernel/test/code_SUITE.erl | 50 |
2 files changed, 55 insertions, 13 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 14ddb74324..023ee3ef4b 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -261,7 +261,7 @@ struct m { Binary* code; Eterm module; Module* modp; - Uint exception; + Eterm exception; }; static Eterm staging_epilogue(Process* c_p, int, Eterm res, int, struct m*, int, int); @@ -282,7 +282,7 @@ exception_list(Process* p, Eterm tag, struct m* mp, Sint exceptions) Eterm res = NIL; while (exceptions > 0) { - if (mp->exception) { + if (is_value(mp->exception)) { res = CONS(hp, mp->module, res); hp += 2; exceptions--; @@ -383,9 +383,9 @@ finish_loading_1(BIF_ALIST_1) exceptions = 0; for (i = 0; i < n; i++) { - p[i].exception = 0; + p[i].exception = THE_NON_VALUE; if (p[i].modp->seen) { - p[i].exception = 1; + p[i].exception = am_duplicated; exceptions++; } p[i].modp->seen = 1; @@ -419,9 +419,9 @@ finish_loading_1(BIF_ALIST_1) exceptions = 0; for (i = 0; i < n; i++) { - p[i].exception = 0; + p[i].exception = THE_NON_VALUE; if (p[i].modp->curr.code_hdr && p[i].modp->old.code_hdr) { - p[i].exception = 1; + p[i].exception = am_not_purged; exceptions++; } } @@ -442,7 +442,7 @@ finish_loading_1(BIF_ALIST_1) retval = erts_finish_loading(p[i].code, BIF_P, 0, &mod); ASSERT(retval == NIL || retval == am_on_load); if (retval == am_on_load) { - p[i].exception = 1; + p[i].exception = am_on_load; exceptions++; } } @@ -475,7 +475,8 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking, erts_commit_staging_code_ix(); for (i=0; i < nmods; i++) { - if (mods[i].modp->curr.code_hdr) { + if (mods[i].modp->curr.code_hdr + && mods[i].exception != am_on_load) { set_default_trace_pattern(mods[i].module); } #ifdef HIPE @@ -700,6 +701,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1) Eterm retval; mod.module = BIF_ARG_1; mod.modp = modp; + mod.exception = THE_NON_VALUE; retval = staging_epilogue(BIF_P, success, res, is_blocking, &mod, 1, 0); return retval; } diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 6f8e949aac..612f77149d 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -35,6 +35,7 @@ purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, on_load_embedded/1, on_load_errors/1, on_load_update/1, + on_load_trace_on_load/1, on_load_purge/1, on_load_self_call/1, on_load_pending/1, on_load_deleted/1, big_boot_embedded/1, @@ -66,14 +67,16 @@ all() -> ext_mod_dep, clash, where_is_file, purge_stacktrace, mult_lib_roots, bad_erl_libs, code_archive, code_archive2, on_load, - on_load_binary, on_load_embedded, on_load_errors, on_load_update, + on_load_binary, on_load_embedded, on_load_errors, + {group, sequence}, on_load_purge, on_load_self_call, on_load_pending, on_load_deleted, module_status, big_boot_embedded, native_early_modules, get_mode, normalized_paths]. -groups() -> - []. +%% These need to run in order +groups() -> [{sequence, [sequence], [on_load_update, + on_load_trace_on_load]}]. init_per_group(_GroupName, Config) -> Config. @@ -1493,7 +1496,7 @@ do_on_load_error(ReturnValue) -> {undef,[{on_load_error,main,[],_}|_]} = Exit end. -on_load_update(_Config) -> +on_load_update(Config) -> {Mod,Code1} = on_load_update_code(1), {module,Mod} = code:load_binary(Mod, "", Code1), 42 = Mod:a(), @@ -1503,7 +1506,7 @@ on_load_update(_Config) -> {Mod,Code2} = on_load_update_code(2), {error,on_load_failure} = code:load_binary(Mod, "", Code2), 42 = Mod:a(), - 100 = Mod:b(99), + 78 = Mod:b(77), {'EXIT',{undef,_}} = (catch Mod:never()), 4 = erlang:trace_pattern({Mod,'_','_'}, false), @@ -1514,6 +1517,9 @@ on_load_update(_Config) -> {'EXIT',{undef,_}} = (catch Mod:b(10)), {'EXIT',{undef,_}} = (catch Mod:never()), + code:purge(Mod), + code:delete(Mod), + code:purge(Mod), ok. on_load_update_code(Version) -> @@ -1545,6 +1551,40 @@ on_load_update_code_1(3, Mod) -> "f() -> ok.\n", "c() -> 100.\n"]). +%% Test -on_load while trace feature 'on_load' is enabled (OTP-14612) +on_load_trace_on_load(Config) -> + Papa = self(), + Tracer = spawn_link(fun F() -> receive M -> Papa ! M end, F() end), + {tracer,[]} = erlang:trace_info(self(),tracer), + erlang:trace(self(), true, [call, {tracer, Tracer}]), + erlang:trace_pattern(on_load, true, []), + on_load_update(Config), + erlang:trace_pattern(on_load, false, []), + erlang:trace(self(), false, [call]), + + %% WE GET TRACES FOR CALLS TO UNDEFINED FUNCTIONS ??? + %% Remove filter when that is fixed. + Ms = lists:filter(fun({trace,Papa,call, + {error_handler,undefined_function, + [on_load_update_code,_,_]}}) + -> false; + (_) -> true + end, + flush()), + + [{trace, Papa, call, {on_load_update_code, a, []}}, + {trace, Papa, call, {on_load_update_code, b, [99]}}, + {trace, Papa, call, {on_load_update_code, c, []}}] = Ms, + + exit(Tracer, normal), + ok. + +flush() -> + receive M -> [M | flush()] + after 100 -> [] + end. + + on_load_purge(_Config) -> Mod = ?FUNCTION_NAME, register(Mod, self()), |