diff options
Diffstat (limited to 'erts/emulator/test')
-rw-r--r-- | erts/emulator/test/code_SUITE.erl | 135 | ||||
-rw-r--r-- | erts/emulator/test/code_SUITE_data/literals.erl | 21 | ||||
-rw-r--r-- | erts/emulator/test/float_SUITE.erl | 27 |
3 files changed, 178 insertions, 5 deletions
diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 61eeec5ffd..2f9b01cc92 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -24,9 +24,10 @@ t_check_process_code/1,t_check_old_code/1, t_check_process_code_ets/1, external_fun/1,get_chunk/1,module_md5/1,make_stub/1, - make_stub_many_funs/1,constant_pools/1, + make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1, false_dependency/1,coverage/1,fun_confusion/1]). +-define(line_trace, 1). -include_lib("test_server/include/test_server.hrl"). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -35,15 +36,18 @@ all() -> [new_binary_types, t_check_process_code, t_check_process_code_ets, t_check_old_code, external_fun, get_chunk, module_md5, make_stub, make_stub_many_funs, - constant_pools, false_dependency, coverage, fun_confusion]. + constant_pools, constant_refc_binaries, false_dependency, + coverage, fun_confusion]. groups() -> []. init_per_suite(Config) -> + erts_debug:set_internal_state(available_internal_state, true), Config. end_per_suite(_Config) -> + catch erts_debug:set_internal_state(available_internal_state, false), ok. init_per_group(_GroupName, Config) -> @@ -404,7 +408,7 @@ make_stub_many_funs(Config) when is_list(Config) -> constant_pools(Config) when is_list(Config) -> ?line Data = ?config(data_dir, Config), ?line File = filename:join(Data, "literals"), - ?line {ok,literals,Code} = compile:file(File, [report,binary,constant_pool]), + ?line {ok,literals,Code} = compile:file(File, [report,binary]), ?line {module,literals} = erlang:load_module(literals, make_sub_binary(Code)), @@ -475,6 +479,131 @@ create_old_heap() -> create_old_heap() end. +constant_refc_binaries(Config) when is_list(Config) -> + wait_for_memory_deallocations(), + Bef = memory_binary(), + io:format("Binary data (bytes) before test: ~p\n", [Bef]), + + %% Compile the the literals module. + Data = ?config(data_dir, Config), + File = filename:join(Data, "literals"), + {ok,literals,Code} = compile:file(File, [report,binary]), + + %% Load the code and make sure that the binary is a refc binary. + {module,literals} = erlang:load_module(literals, Code), + Bin = literals:binary(), + Sz = byte_size(Bin), + Check = erlang:md5(Bin), + io:format("Size of literal refc binary: ~p\n", [Sz]), + {refc_binary,Sz,_,_} = erts_debug:get_internal_state({binary_info,Bin}), + true = erlang:delete_module(literals), + false = erlang:check_process_code(self(), literals), + true = erlang:purge_module(literals), + + %% Now try to provoke a memory leak. + provoke_mem_leak(10, Code, Check), + + %% Calculate the change in allocated binary data. + erlang:garbage_collect(), + wait_for_memory_deallocations(), + Aft = memory_binary(), + io:format("Binary data (bytes) after test: ~p", [Aft]), + Diff = Aft - Bef, + if + Diff < 0 -> + io:format("~p less bytes", [abs(Diff)]); + Diff > 0 -> + io:format("~p more bytes", [Diff]); + true -> + ok + end, + + %% Test for leaks. We must accept some natural variations in + %% the size of allocated binaries. + if + Diff > 64*1024 -> + ?t:fail(binary_leak); + true -> + ok + end. + +memory_binary() -> + try + erlang:memory(binary) + catch + error:notsup -> + 0 + end. + +provoke_mem_leak(0, _, _) -> ok; +provoke_mem_leak(N, Code, Check) -> + {module,literals} = erlang:load_module(literals, Code), + + %% Create several processes with references to the literal binary. + Self = self(), + Pids = [spawn_link(fun() -> + create_binaries(Self, NumRefs, Check) + end) || NumRefs <- lists:seq(1, 10)], + [receive {started,Pid} -> ok end || Pid <- Pids], + + %% Make the code old and remove references to the constant pool + %% in all processes. + true = erlang:delete_module(literals), + Ms = [spawn_monitor(fun() -> + false = erlang:check_process_code(Pid, literals) + end) || Pid <- Pids], + [receive + {'DOWN',R,process,P,normal} -> + ok + end || {P,R} <- Ms], + + %% Purge the code. + true = erlang:purge_module(literals), + + %% Tell the processes that the code has been purged. + [begin + monitor(process, Pid), + Pid ! purged + end || Pid <- Pids], + + %% Wait for all processes to terminate. + [receive + {'DOWN',_,process,Pid,normal} -> + ok + end || Pid <- Pids], + + %% We now expect that the binary has been deallocated. + provoke_mem_leak(N-1, Code, Check). + +create_binaries(Parent, NumRefs, Check) -> + Bin = literals:binary(), + Bins = lists:duplicate(NumRefs, Bin), + {bits,Bits} = literals:bits(), + Parent ! {started,self()}, + receive + purged -> + %% The code has been purged. Now make sure that + %% the binaries haven't been corrupted. + Check = erlang:md5(Bin), + [Bin = B || B <- Bins], + <<42:13,Bin/binary>> = Bits, + + %% Remove all references to the binaries + %% Doing it explicitly like this ensures that + %% the binaries are gone when the parent process + %% receives the 'DOWN' message. + erlang:garbage_collect() + end. + +wait_for_memory_deallocations() -> + try + erts_debug:set_internal_state(wait, deallocations) + catch + error:undef -> + erts_debug:set_internal_state(available_internal_state, true), + wait_for_memory_deallocations() + end. + %% OTP-7559: c_p->cp could contain garbage and create a false dependency %% to a module in a process. (Thanks to Richard Carlsson.) false_dependency(Config) when is_list(Config) -> diff --git a/erts/emulator/test/code_SUITE_data/literals.erl b/erts/emulator/test/code_SUITE_data/literals.erl index 9f99b1a780..d9cb8938db 100644 --- a/erts/emulator/test/code_SUITE_data/literals.erl +++ b/erts/emulator/test/code_SUITE_data/literals.erl @@ -18,7 +18,7 @@ %% -module(literals). --export([a/0,b/0,huge_bignum/0]). +-export([a/0,b/0,huge_bignum/0,binary/0,unused_binaries/0,bits/0]). a() -> {a,42.0,[7,38877938333399637266518333334747]}. @@ -81,3 +81,22 @@ b() -> huge_bignum() -> 36#9987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987779JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR073737676679877. + +-define(TIMES_FOUR(X), X,X,X,X). +-define(BYTES_256, 0:256,1:256,2:256,3:256, 4:256,5:256,6:256,7:256). +-define(KB_1, ?TIMES_FOUR(?BYTES_256)). +-define(KB_4, ?TIMES_FOUR(?KB_1)). +-define(KB_16, ?TIMES_FOUR(?KB_4)). +-define(KB_64, ?TIMES_FOUR(?KB_16)). +-define(KB_128, ?TIMES_FOUR(?KB_64)). +-define(MB_1, ?TIMES_FOUR(?KB_128)). + +binary() -> + %% Too big to be a heap binary. + <<?MB_1>>. + +unused_binaries() -> + {<<?KB_128>>,<<?BYTES_256>>}. + +bits() -> + {bits,<<42:13,?MB_1>>}. diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl index 46466427c5..8e6923ce9f 100644 --- a/erts/emulator/test/float_SUITE.erl +++ b/erts/emulator/test/float_SUITE.erl @@ -27,6 +27,7 @@ fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1, bad_float_unpack/1,cmp_zero/1, cmp_integer/1, cmp_bignum/1]). -export([otp_7178/1]). +-export([hidden_inf/1]). init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> @@ -41,7 +42,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [fpe, fp_drv, fp_drv_thread, otp_7178, denormalized, - match, bad_float_unpack, {group, comparison}]. + match, bad_float_unpack, {group, comparison} + ,hidden_inf + ]. groups() -> [{comparison, [parallel], [cmp_zero, cmp_integer, cmp_bignum]}]. @@ -300,3 +303,25 @@ start_node(Config) when is_list(Config) -> stop_node(Node) -> ?t:stop_node(Node). + + +%% Test that operations that might hide infinite intermediate results +%% do not supress the badarith. +hidden_inf(Config) when is_list(Config) -> + ZeroP = 0.0, + ZeroN = id(ZeroP) * (-1), + [hidden_inf_1(A, B, Z, 9.23e307) + || A <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN], + B <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN], + Z <- [ZeroP, ZeroN]], + ok. + +hidden_inf_1(A, B, Zero, Huge) -> + {'EXIT',{badarith,_}} = (catch (B / (A / Zero))), + {'EXIT',{badarith,_}} = (catch (B * (A / Zero))), + {'EXIT',{badarith,_}} = (catch (B / (Huge * Huge))), + {'EXIT',{badarith,_}} = (catch (B * (Huge * Huge))), + {'EXIT',{badarith,_}} = (catch (B / (Huge + Huge))), + {'EXIT',{badarith,_}} = (catch (B * (Huge + Huge))), + {'EXIT',{badarith,_}} = (catch (B / (-Huge - Huge))), + {'EXIT',{badarith,_}} = (catch (B * (-Huge - Huge))). |