From 77d6845c94e75b6da1f7f995e39a6ce455e86de6 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 11 May 2012 16:58:38 +0200 Subject: kernel: Disable hipe compilation for hipe_unified_loader Workaround for crash in code_server. --- lib/kernel/src/hipe_unified_loader.erl | 7 +++++++ lib/kernel/test/code_SUITE.erl | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 8b3aa0286d..514c002d87 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -34,6 +34,13 @@ -module(hipe_unified_loader). +-compile(no_native). +% 'no_native' is a workaround to avoid "The code server called unloaded module" +% caused by Mod:module_info(exports) in patch_to_emu_step1() called by post_beam_load. +% Reproducable with hipelibs and asn1_SUITE. +% I think the real solution would be to let BIF erlang:load_module/2 redirect all +% hipe calls to the module and thereby remove post_beam_load. + -export([chunk_name/1, %% Only the code and code_server modules may call the entries below! load_native_code/2, diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 3e8bdaf1ff..827208b048 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -1550,7 +1550,8 @@ native_early_modules_1(Architecture) -> true -> ?line true = lists:all(fun code:is_module_native/1, [ets,file,filename,gb_sets,gb_trees, - hipe_unified_loader,lists,os,packages]), + %%hipe_unified_loader, no_native as workaround + lists,os,packages]), ok end. -- cgit v1.2.3 From 439fe7b93743528782fbe1ff00dc65d08cb25a56 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 16 Aug 2012 15:51:01 +0200 Subject: Fix init:restart with hipelibs This is a workaround for init:restart. The root problem is that delete/purge_module does not clean up internal hipe bookkeeping (hipe_mfa_info's) properly. Symptom: Execution of deallocated beam code. --- erts/emulator/hipe/hipe_bif0.c | 41 +++++++++++++++++++++++++++++++++++++++++ erts/preloaded/ebin/init.beam | Bin 48292 -> 48604 bytes erts/preloaded/src/init.erl | 8 ++++++++ lib/kernel/src/heart.erl | 4 ++++ 4 files changed, 53 insertions(+) diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c index af593229c0..23ced284bf 100644 --- a/erts/emulator/hipe/hipe_bif0.c +++ b/erts/emulator/hipe/hipe_bif0.c @@ -1755,6 +1755,41 @@ BIF_RETTYPE hipe_bifs_mark_referred_from_1(BIF_ALIST_1) /* get_refs_from */ BIF_RET(NIL); } +/* Called by init:restart after unloading all hipe compiled modules + * to work around bug causing execution of deallocated beam code. + * Can be removed when delete/purge of native modules works better. + * Test: Do init:restart in debug compiled vm with hipe compiled kernel. + */ +static void hipe_purge_all_refs(void) +{ + struct hipe_mfa_info **bucket; + unsigned int i, nrbuckets; + + hipe_mfa_info_table_lock(); + + bucket = hipe_mfa_info_table.bucket; + nrbuckets = 1 << hipe_mfa_info_table.log2size; + for (i = 0; i < nrbuckets; ++i) { + while (bucket[i] != NULL) { + struct hipe_mfa_info* mfa = bucket[i]; + bucket[i] = mfa->bucket.next; + + while (mfa->refers_to) { + struct hipe_mfa_info_list *to = mfa->refers_to; + mfa->refers_to = to->next; + erts_free(ERTS_ALC_T_HIPE, to); + } + while (mfa->referred_from) { + struct ref* from = mfa->referred_from; + mfa->referred_from = from->next; + erts_free(ERTS_ALC_T_HIPE, from); + } + erts_free(ERTS_ALC_T_HIPE, mfa); + } + } + hipe_mfa_info_table_unlock(); +} + BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1) { struct mfa mfa; @@ -1762,6 +1797,11 @@ BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1) struct hipe_mfa_info_list *refers_to, *tmp_refers_to; struct ref **prev, *ref; + if (BIF_ARG_1 == am_all) { + hipe_purge_all_refs(); + BIF_RET(NIL); + } + if (!term_to_mfa(BIF_ARG_1, &mfa)) BIF_ERROR(BIF_P, BADARG); hipe_mfa_info_table_lock(); @@ -1799,6 +1839,7 @@ BIF_RETTYPE hipe_bifs_remove_refs_from_1(BIF_ALIST_1) BIF_RET(NIL); } + /* redirect_referred_from(CalleeMFA) * Redirect all pending-redirect refs in CalleeMFA's referred_from. * Then remove any pending-redirect && pending-remove refs from CalleeMFA's referred_from. diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam index 9f2d369af2..b588b450c9 100644 Binary files a/erts/preloaded/ebin/init.beam and b/erts/preloaded/ebin/init.beam differ diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 708991e261..185b62a899 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -635,8 +635,16 @@ do_unload([M|Mods]) -> catch erlang:purge_module(M), do_unload(Mods); do_unload([]) -> + purge_all_hipe_refs(), ok. +purge_all_hipe_refs() -> + case erlang:system_info(hipe_architecture) of + undefined -> ok; + _ -> hipe_bifs:remove_refs_from(all) + end. + + sub([H|T],L) -> sub(T,del(H,L)); sub([],L) -> L. diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl index 255ae4e51b..218be964a0 100644 --- a/lib/kernel/src/heart.erl +++ b/lib/kernel/src/heart.erl @@ -18,6 +18,10 @@ %% -module(heart). +-compile(no_native). +% 'no_native' as part of a crude fix to make init:restart/0 work by clearing +% all hipe inter-module information (hipe_mfa_info's in hipe_bif0.c). + %%%-------------------------------------------------------------------- %%% This is a rewrite of pre_heart from BS.3. %%% -- cgit v1.2.3