From ebb280b7c02165cf819131cc0026d9b509560fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 17 Nov 2011 11:24:21 +0100 Subject: beam_load.c: Eliminate memory leak in code:make_stub_module/3 code:make_stub_module/3 leaked memory if given either a corrupt BEAM file, or a compressed BEAM file and an error occurred, or a binary not aligned on byte boundaries. --- erts/emulator/beam/beam_load.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 4427defe0c..93eae4dee8 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -5993,6 +5993,10 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) } error: + erts_free_aligned_binary_bytes(temp_alloc); + if (bin) { + driver_free_binary(bin); + } free_state(stp); BIF_ERROR(p, BADARG); } -- cgit v1.2.3 From 4b51282bb73cfab7c5bddf10964851917fd70dc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 18 Nov 2011 11:00:07 +0100 Subject: beam_load.c: Optimize code:get_chunk/2 The undocumented code:get_chunk/2 BIF is supposed to be a fast way to extract a chunk from a BEAM file when loading native code. In practice, it might not have been faster because it happened to calculate an MD5 checksum for the chunk it extracted because it shared the scan_iff_file() function with the erlang:load_module/2 BIF. Split scan_iff_file() into scan_iff_file() and verify_chunks(), so that the unnecessary MD5 calculation can be avoided. --- erts/emulator/beam/beam_load.c | 105 ++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 43 deletions(-) diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 93eae4dee8..65a200d75d 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -501,6 +501,7 @@ static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, BeamInstr* code, Uint size); static int scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory); +static int verify_chunks(LoaderState* stp); static int load_atom_table(LoaderState* stp); static int load_import_table(LoaderState* stp); static int read_export_table(LoaderState* stp); @@ -663,7 +664,8 @@ erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader, stp->file_name = "IFF header for Beam file"; stp->file_p = code; stp->file_left = unloaded_size; - if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { + if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(stp)) { goto load_error; } @@ -1013,7 +1015,6 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, static int scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory) { - MD5_CTX context; Uint id; Uint count; int i; @@ -1104,17 +1105,25 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand stp->file_p += count; stp->file_left -= count; } + return 1; - /* - * At this point, we have read the entire IFF file, and we - * know that it is syntactically correct. - * - * Now check that it contains all mandatory chunks. At the - * same time calculate the MD5 for the module. - */ + load_error: + return 0; +} + +/* + * Verify that all mandatory chunks are present and calculate + * MD5 for the module. + */ + +static int +verify_chunks(LoaderState* stp) +{ + int i; + MD5_CTX context; MD5Init(&context); - for (i = 0; i < num_mandatory; i++) { + for (i = 0; i < NUM_MANDATORY; i++) { if (stp->chunks[i].start != NULL) { MD5Update(&context, stp->chunks[i].start, stp->chunks[i].size); } else { @@ -1124,41 +1133,49 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand LoadError1(stp, "mandatory chunk of type '%s' not found\n", sbuf); } } - if (LITERAL_CHUNK < num_types) { - if (stp->chunks[LAMBDA_CHUNK].start != 0) { - byte* start = stp->chunks[LAMBDA_CHUNK].start; - Uint left = stp->chunks[LAMBDA_CHUNK].size; - /* - * The idea here is to ignore the OldUniq field for the fun; it is - * based on the old broken hash function, which can be different - * on little endian and big endian machines. - */ - if (left >= 4) { - static byte zero[4]; - MD5Update(&context, start, 4); - start += 4; - left -= 4; + /* + * If there is a lambda chunk, include parts of it in the MD5. + */ + if (stp->chunks[LAMBDA_CHUNK].start != 0) { + byte* start = stp->chunks[LAMBDA_CHUNK].start; + Uint left = stp->chunks[LAMBDA_CHUNK].size; + + /* + * The idea here is to ignore the OldUniq field for the fun; it is + * based on the old broken hash function, which can be different + * on little endian and big endian machines. + */ + if (left >= 4) { + static byte zero[4]; + MD5Update(&context, start, 4); + start += 4; + left -= 4; - while (left >= 24) { - /* Include: Function Arity Index NumFree */ - MD5Update(&context, start, 20); - /* Set to zero: OldUniq */ - MD5Update(&context, zero, 4); - start += 24; - left -= 24; - } - } - /* Can't happen for a correct 'FunT' chunk */ - if (left > 0) { - MD5Update(&context, start, left); + while (left >= 24) { + /* Include: Function Arity Index NumFree */ + MD5Update(&context, start, 20); + /* Set to zero: OldUniq */ + MD5Update(&context, zero, 4); + start += 24; + left -= 24; } } - if (stp->chunks[LITERAL_CHUNK].start != 0) { - MD5Update(&context, stp->chunks[LITERAL_CHUNK].start, - stp->chunks[LITERAL_CHUNK].size); + /* Can't happen for a correct 'FunT' chunk */ + if (left > 0) { + MD5Update(&context, start, left); } } + + + /* + * If there is a literal chunk, include it in the MD5. + */ + if (stp->chunks[LITERAL_CHUNK].start != 0) { + MD5Update(&context, stp->chunks[LITERAL_CHUNK].start, + stp->chunks[LITERAL_CHUNK].size); + } + MD5Final(stp->mod_md5, &context); return 1; @@ -5445,7 +5462,8 @@ code_get_chunk_2(BIF_ALIST_2) if (is_not_nil(Chunk)) { goto error; } - if (!scan_iff_file(&state, &chunk, 1, 1)) { + if (!scan_iff_file(&state, &chunk, 1, 1) || + state.chunks[0].start == NULL) { erts_free_aligned_binary_bytes(temp_alloc); return am_undefined; } @@ -5485,8 +5503,8 @@ code_module_md5_1(BIF_ALIST_1) state.module = THE_NON_VALUE; /* Suppress diagnostiscs */ state.file_name = "IFF header for Beam file"; state.file_left = binary_size(Bin); - - if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { + if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(&state)) { return am_undefined; } erts_free_aligned_binary_bytes(temp_alloc); @@ -5831,7 +5849,8 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) stp->module = Mod; stp->group_leader = p->group_leader; stp->num_functions = n; - if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { + if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(stp)) { goto error; } define_file(stp, "code chunk header", CODE_CHUNK); -- cgit v1.2.3 From d397e917375718e6f6a72a6a53496e810f775435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 18 Nov 2011 11:34:00 +0100 Subject: beam_code.c: Don't reinvent state initialization and deallocation --- erts/emulator/beam/beam_load.c | 57 ++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 65a200d75d..aa6c2ef959 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -5424,7 +5424,7 @@ code_get_chunk_2(BIF_ALIST_2) Process* p = BIF_P; Eterm Bin = BIF_ARG_1; Eterm Chunk = BIF_ARG_2; - LoaderState state; + LoaderState* stp; Uint chunk = 0; ErlSubBin* sb; Uint offset; @@ -5436,15 +5436,19 @@ code_get_chunk_2(BIF_ALIST_2) Eterm real_bin; byte* temp_alloc = NULL; + stp = erts_alloc_loader_state(); if ((start = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { error: erts_free_aligned_binary_bytes(temp_alloc); + if (stp) { + free_state(stp); + } BIF_ERROR(p, BADARG); } - state.module = THE_NON_VALUE; /* Suppress diagnostiscs */ - state.file_name = "IFF header for Beam file"; - state.file_p = start; - state.file_left = binary_size(Bin); + stp->module = THE_NON_VALUE; /* Suppress diagnostics */ + stp->file_name = "IFF header for Beam file"; + stp->file_p = start; + stp->file_left = binary_size(Bin); for (i = 0; i < 4; i++) { Eterm* chunkp; Eterm num; @@ -5462,26 +5466,29 @@ code_get_chunk_2(BIF_ALIST_2) if (is_not_nil(Chunk)) { goto error; } - if (!scan_iff_file(&state, &chunk, 1, 1) || - state.chunks[0].start == NULL) { - erts_free_aligned_binary_bytes(temp_alloc); - return am_undefined; + if (!scan_iff_file(stp, &chunk, 1, 1) || + stp->chunks[0].start == NULL) { + res = am_undefined; + goto done; } ERTS_GET_REAL_BIN(Bin, real_bin, offset, bitoffs, bitsize); if (bitoffs) { - res = new_binary(p, state.chunks[0].start, state.chunks[0].size); + res = new_binary(p, stp->chunks[0].start, stp->chunks[0].size); } else { sb = (ErlSubBin *) HAlloc(p, ERL_SUB_BIN_SIZE); sb->thing_word = HEADER_SUB_BIN; sb->orig = real_bin; - sb->size = state.chunks[0].size; + sb->size = stp->chunks[0].size; sb->bitsize = 0; sb->bitoffs = 0; - sb->offs = offset + (state.chunks[0].start - start); + sb->offs = offset + (stp->chunks[0].start - start); sb->is_writable = 0; res = make_binary(sb); } + + done: erts_free_aligned_binary_bytes(temp_alloc); + free_state(stp); return res; } @@ -5494,21 +5501,29 @@ code_module_md5_1(BIF_ALIST_1) { Process* p = BIF_P; Eterm Bin = BIF_ARG_1; - LoaderState state; + LoaderState* stp; byte* temp_alloc = NULL; + Eterm res; - if ((state.file_p = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { + stp = erts_alloc_loader_state(); + if ((stp->file_p = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { + free_state(stp); BIF_ERROR(p, BADARG); } - state.module = THE_NON_VALUE; /* Suppress diagnostiscs */ - state.file_name = "IFF header for Beam file"; - state.file_left = binary_size(Bin); - if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || - !verify_chunks(&state)) { - return am_undefined; + stp->module = THE_NON_VALUE; /* Suppress diagnostiscs */ + stp->file_name = "IFF header for Beam file"; + stp->file_left = binary_size(Bin); + if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + !verify_chunks(stp)) { + res = am_undefined; + goto done; } + res = new_binary(p, stp->mod_md5, sizeof(stp->mod_md5)); + + done: erts_free_aligned_binary_bytes(temp_alloc); - return new_binary(p, state.mod_md5, sizeof(state.mod_md5)); + free_state(stp); + return res; } #define WORDS_PER_FUNCTION 6 -- cgit v1.2.3 From caf21d16b1495f474aa1109dff5695768d35ae20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 18 Nov 2011 12:17:06 +0100 Subject: beam_load.c: Add init_iff_file() for verifying the IFF header Add init_iff_file() for verifying the IFF header. Also let it handle compressed BEAM files so that it will be done in one place. That means that code:get_chunk/2 and code:module_md5/1 will now support compressed BEAM files. --- erts/emulator/beam/beam_load.c | 128 +++++++++++++++++++++-------------------- 1 file changed, 66 insertions(+), 62 deletions(-) diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index aa6c2ef959..d8434c098e 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -254,6 +254,7 @@ typedef struct LoaderState { char* file_name; /* Name of file we are reading (usually chunk name). */ byte* file_p; /* Current pointer within file. */ unsigned file_left; /* Number of bytes left in file. */ + ErlDrvBinary* bin; /* Binary holding BEAM file (or NULL) */ /* * The following are used mainly for diagnostics. @@ -499,6 +500,7 @@ static void free_state(LoaderState* stp); static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm module, BeamInstr* code, Uint size); +static int init_iff_file(LoaderState* stp, byte* code, Uint size); static int scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory); static int verify_chunks(LoaderState* stp); @@ -631,40 +633,22 @@ erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader, Eterm* modp, byte* code, Uint unloaded_size) { Eterm retval = am_badfile; - ErlDrvBinary* bin = NULL; stp->module = *modp; stp->group_leader = group_leader; - /* - * Check if the module is compressed (or possibly invalid/corrupted). - */ - if ( !(unloaded_size >= 4 && - code[0] == 'F' && code[1] == 'O' && - code[2] == 'R' && code[3] == '1') ) { - bin = (ErlDrvBinary *) - erts_gzinflate_buffer((char*)code, unloaded_size); - if (bin == NULL) { - goto load_error; - } - code = (byte*)bin->orig_bytes; - unloaded_size = bin->orig_size; - } +#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) + erts_fprintf(stderr,"Loading a module\n"); +#endif /* * Scan the IFF file. */ -#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) - erts_fprintf(stderr,"Loading a module\n"); -#endif - CHKALLOC(); CHKBLK(ERTS_ALC_T_CODE,stp->code); - stp->file_name = "IFF header for Beam file"; - stp->file_p = code; - stp->file_left = unloaded_size; - if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + if (!init_iff_file(stp, code, unloaded_size) || + !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || !verify_chunks(stp)) { goto load_error; } @@ -789,9 +773,6 @@ erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader, retval = NIL; load_error: - if (bin) { - driver_free_binary(bin); - } if (retval != NIL) { free_state(stp); } @@ -866,6 +847,7 @@ erts_alloc_loader_state(void) LoaderState* stp; stp = erts_alloc(ERTS_ALC_T_LOADER_TMP, sizeof(LoaderState)); + stp->bin = NULL; stp->function = THE_NON_VALUE; /* Function not known yet */ stp->arity = 0; stp->specific_op = -1; @@ -899,6 +881,9 @@ erts_alloc_loader_state(void) static void free_state(LoaderState* stp) { + if (stp->bin != 0) { + driver_free_binary(stp->bin); + } if (stp->code != 0) { erts_free(ERTS_ALC_T_CODE, stp->code); } @@ -958,6 +943,7 @@ free_state(LoaderState* stp) if (stp->fname != 0) { erts_free(ERTS_ALC_T_LOADER_TMP, stp->fname); } + erts_free(ERTS_ALC_T_LOADER_TMP, stp); } @@ -1013,21 +999,46 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, } static int -scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory) +init_iff_file(LoaderState* stp, byte* code, Uint size) { + Uint form_id = MakeIffId('F', 'O', 'R', '1'); Uint id; Uint count; - int i; + + if (size < 4) { + goto load_error; + } /* - * The binary must start with an IFF 'FOR1' chunk. + * Check if the module is compressed (or possibly invalid/corrupted). */ + if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) { + stp->bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)code, size); + if (stp->bin == NULL) { + goto load_error; + } + code = (byte*)stp->bin->orig_bytes; + size = stp->bin->orig_size; + if (size < 4) { + goto load_error; + } + } - GetInt(stp, 4, id); - if (id != MakeIffId('F', 'O', 'R', '1')) { + /* + * The binary must start with an IFF 'FOR1' chunk. + */ + if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) { LoadError0(stp, "not a BEAM file: no IFF 'FOR1' chunk"); } + /* + * Initialize our "virtual file system". + */ + + stp->file_name = "IFF header for Beam file"; + stp->file_p = code + 4; + stp->file_left = size - 4; + /* * Retrieve the chunk size and verify it. If the size is equal to * or less than the size of the binary, it is ok and we will use it @@ -1049,6 +1060,21 @@ scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mand if (id != MakeIffId('B', 'E', 'A', 'M')) { LoadError0(stp, "not a BEAM file: IFF form type is not 'BEAM'"); } + return 1; + + load_error: + return 0; +} + +/* + * Scan the IFF file. The header should have been verified by init_iff_file(). + */ +static int +scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory) +{ + Uint count; + Uint id; + int i; /* * Initialize the chunks[] array in the state. @@ -5446,9 +5472,6 @@ code_get_chunk_2(BIF_ALIST_2) BIF_ERROR(p, BADARG); } stp->module = THE_NON_VALUE; /* Suppress diagnostics */ - stp->file_name = "IFF header for Beam file"; - stp->file_p = start; - stp->file_left = binary_size(Bin); for (i = 0; i < 4; i++) { Eterm* chunkp; Eterm num; @@ -5466,7 +5489,8 @@ code_get_chunk_2(BIF_ALIST_2) if (is_not_nil(Chunk)) { goto error; } - if (!scan_iff_file(stp, &chunk, 1, 1) || + if (!init_iff_file(stp, start, binary_size(Bin)) || + !scan_iff_file(stp, &chunk, 1, 1) || stp->chunks[0].start == NULL) { res = am_undefined; goto done; @@ -5502,18 +5526,18 @@ code_module_md5_1(BIF_ALIST_1) Process* p = BIF_P; Eterm Bin = BIF_ARG_1; LoaderState* stp; + byte* bytes; byte* temp_alloc = NULL; Eterm res; stp = erts_alloc_loader_state(); - if ((stp->file_p = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { + if ((bytes = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) { free_state(stp); BIF_ERROR(p, BADARG); } stp->module = THE_NON_VALUE; /* Suppress diagnostiscs */ - stp->file_name = "IFF header for Beam file"; - stp->file_left = binary_size(Bin); - if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || + if (!init_iff_file(stp, bytes, binary_size(Bin)) || + !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || !verify_chunks(stp)) { res = am_undefined; goto done; @@ -5809,7 +5833,6 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) int code_size; int rval; int i; - ErlDrvBinary* bin = NULL; byte* temp_alloc = NULL; byte* bytes; Uint size; @@ -5841,29 +5864,16 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) } size = binary_size(Beam); - /* - * Uncompressed if needed. - */ - if (!(size >= 4 && bytes[0] == 'F' && bytes[1] == 'O' && - bytes[2] == 'R' && bytes[3] == '1')) { - bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)bytes, size); - if (bin == NULL) { - goto error; - } - bytes = (byte*)bin->orig_bytes; - size = bin->orig_size; - } - /* * Scan the Beam binary and read the interesting sections. */ - stp->file_name = "IFF header for Beam file"; - stp->file_p = bytes; - stp->file_left = size; stp->module = Mod; stp->group_leader = p->group_leader; stp->num_functions = n; + if (!init_iff_file(stp, bytes, size)) { + goto error; + } if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY) || !verify_chunks(stp)) { goto error; @@ -6020,17 +6030,11 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) if (patch_funentries(Patchlist)) { erts_free_aligned_binary_bytes(temp_alloc); free_state(stp); - if (bin != NULL) { - driver_free_binary(bin); - } return Mod; } error: erts_free_aligned_binary_bytes(temp_alloc); - if (bin) { - driver_free_binary(bin); - } free_state(stp); BIF_ERROR(p, BADARG); } -- cgit v1.2.3 From 541c5040ceb8822b423f4362d7a8efad7d70a4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 18 Nov 2011 09:46:51 +0100 Subject: code: Clean up loading of code_server prerequisites Reorganize in a systematic way the code that loads the modules needed by the code_server process. While at it, remove the useless hipe_unified_loader:load_hipe_modules/0 function. --- lib/kernel/src/code.erl | 29 ++++++++++++++++++++--------- lib/kernel/src/hipe_unified_loader.erl | 11 ----------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 882e9625fe..b7fda69ce0 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -324,15 +324,7 @@ start_link(Flags) -> %%----------------------------------------------------------------- do_start(Flags) -> - %% The following module_info/1 calls are here to ensure - %% that these modules are loaded prior to their use elsewhere in - %% the code_server. - %% Otherwise a deadlock may occur when the code_server is starting. - code_server = code_server:module_info(module), - packages = packages:module_info(module), - catch hipe_unified_loader:load_hipe_modules(), - Modules2 = [gb_sets, gb_trees, ets, os, binary, unicode, filename, lists], - lists:foreach(fun (M) -> M = M:module_info(module) end, Modules2), + load_code_server_prerequisites(), Mode = get_mode(Flags), case init:get_argument(root) of @@ -360,6 +352,25 @@ do_start(Flags) -> {error, crash} end. +%% Make sure that all modules that the code_server process calls +%% (directly or indirectly) are loaded. Otherwise the code_server +%% process will deadlock. + +load_code_server_prerequisites() -> + %% Please keep the alphabetical order. + Needed = [binary, + ets, + filename, + gb_sets, + gb_trees, + hipe_unified_loader, + lists, + os, + packages, + unicode], + [M = M:module_info(module) || M <- Needed], + ok. + do_stick_dirs() -> do_s(compiler), do_s(stdlib), diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 1d3eb926ca..8b3aa0286d 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -36,7 +36,6 @@ -export([chunk_name/1, %% Only the code and code_server modules may call the entries below! - load_hipe_modules/0, load_native_code/2, post_beam_load/1, load_module/3, @@ -78,16 +77,6 @@ chunk_name(Architecture) -> %%======================================================================== --spec load_hipe_modules() -> 'ok'. -%% @doc -%% Ensures HiPE's loader modules are loaded. -%% Called from code.erl at start-up. - -load_hipe_modules() -> - ok. - -%%======================================================================== - -spec load_native_code(Mod, binary()) -> 'no_native' | {'module', Mod} when is_subtype(Mod, atom()). %% @doc -- cgit v1.2.3