From 11ee8c813ac824015a85d51fb455b31bab6f648c Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 28 Aug 2017 18:40:43 +0200 Subject: erts: Fix harmless use of uninitialised value Conditional jump or move depends on uninitialised value(s): erts_msgq_update_internal_pointers:487 (-> 0x5A7AF9) [erl_message.h] erts_msgq_replace_msg_ref:496 (-> 0x5A7B4C) [erl_message.h] move_msgq_to_heap:2487 (-> 0x5AED4F) [erl_gc.c] minor_collection:1380 (-> 0x5AB3F4) [erl_gc.c] --- erts/emulator/beam/erl_process.c | 1 + 1 file changed, 1 insertion(+) diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 63c838a91d..6ad686dab2 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -12512,6 +12512,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->msg.first = NULL; p->msg.last = &p->msg.first; p->msg.save = &p->msg.first; + p->msg.saved_last = &p->msg.first; p->msg.len = 0; #ifdef ERTS_SMP p->msg_inq.first = NULL; -- cgit v1.2.3 From 7c5fcd3f2701cbb614930682ac52ff75b9c26e6c Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 28 Aug 2017 20:19:43 +0200 Subject: erts: Fix memory leak when sending to terminating port Error: Leak_DefinitelyLost erts_alloc:230 (-> 0x52E54D) [erl_alloc.h] port_task_alloc:154 (-> 0x52F3CA) [erl_port_task.c] erts_port_task_alloc_p2p_sig_data:212 (-> 0x52F5D3) [erl_port_task.c] erts_port_output:2147 (-> 0x4F6057) [io.c] erts_port_command:4126 (-> 0x4FA10E) [io.c] do_send:2200 (-> 0x4E4C64) [bif.c] erl_send:2494 (-> 0x4E5E09) [bif.c] process_main:1730 (-> 0x43ADA5) [beam_emu.c] --- erts/emulator/beam/erl_port_task.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index 1ab1e47254..4d7a86398a 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -1474,10 +1474,10 @@ erts_port_task_schedule(Eterm id, } #endif - if (!pp) - goto fail; - if (type != ERTS_PORT_TASK_PROC_SIG) { + if (!pp) + goto fail; + ptp = port_task_alloc(); ptp->type = type; @@ -1515,6 +1515,9 @@ erts_port_task_schedule(Eterm id, ptp->u.alive.td.psig.callback = va_arg(argp, ErtsProc2PortSigCallback); ptp->u.alive.flags |= va_arg(argp, int); va_end(argp); + if (!pp) + goto fail; + if (!(ptp->u.alive.flags & ERTS_PT_FLG_NOSUSPEND)) set_tmp_handle(ptp, pthp); else { -- cgit v1.2.3 From d83975178956dbaed84c315ba249a571ce796cb3 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 29 Aug 2017 16:16:33 +0200 Subject: Revert "remove unused purify functions" This reverts commit d8c8e0c66d6faf5402682f3a8568362eedebdfee. --- erts/emulator/test/process_SUITE.erl | 6 ++- lib/common_test/src/test_server.erl | 67 +++++++++++++++++++++++++++++++- lib/common_test/src/test_server_ctrl.erl | 9 +++-- lib/stdlib/test/id_transform_SUITE.erl | 9 ++++- 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 6ded7ff1c9..bcf459e4fb 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -152,7 +152,11 @@ spawn_with_binaries(Config) when is_list(Config) -> TwoMeg = lists:duplicate(1024, L), Fun = fun() -> spawn(?MODULE, binary_owner, [list_to_binary(TwoMeg)]), receive after 1 -> ok end end, - test_server:do_times(150, Fun), + Iter = case test_server:purify_is_running() of + true -> 10; + false -> 150 + end, + test_server:do_times(Iter, Fun), ok. binary_owner(Bin) when is_binary(Bin) -> diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl index ee3a5e4bba..a47b3f824f 100644 --- a/lib/common_test/src/test_server.erl +++ b/lib/common_test/src/test_server.erl @@ -21,7 +21,7 @@ -define(DEFAULT_TIMETRAP_SECS, 60). %%% TEST_SERVER_CTRL INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export([run_test_case_apply/1,init_target_info/0]). +-export([run_test_case_apply/1,init_target_info/0,init_purify/0]). -export([cover_compile/1,cover_analyse/2]). %%% TEST_SERVER_SUP INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -49,6 +49,10 @@ -export([break/1,break/2,break/3,continue/0,continue/1]). +%%% DEBUGGER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-export([purify_new_leaks/0, purify_format/2, purify_new_fds_inuse/0, + purify_is_running/0]). + %%% PRIVATE EXPORTED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export([]). @@ -69,6 +73,10 @@ init_target_info() -> username=test_server_sup:get_username(), cookie=atom_to_list(erlang:get_cookie())}. +init_purify() -> + purify_new_leaks(). + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% cover_compile(#cover{app=App,incl=Include,excl=Exclude,cross=Cross}) -> %% {ok,#cover{mods=AnalyseModules}} | {error,Reason} @@ -358,7 +366,8 @@ stick_all_sticky(Node,Sticky) -> %% compensate timetraps for runtime delays introduced by e.g. tools like %% cover. -run_test_case_apply({Mod,Func,Args,Name,RunInit,TimetrapData}) -> +run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,TimetrapData}) -> + purify_format("Test case #~w ~w:~w/1", [CaseNum, Mod, Func]), case is_valgrind() of false -> ok; @@ -370,6 +379,7 @@ run_test_case_apply({Mod,Func,Args,Name,RunInit,TimetrapData}) -> Result = run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData), ProcAft = erlang:system_info(process_count), + purify_new_leaks(), DetFail = get(test_server_detected_fail), {Result,DetFail,ProcBef,ProcAft}. @@ -1826,6 +1836,7 @@ timetrap_scale_factor() -> timetrap_scale_factor([ { 2, fun() -> has_lock_checking() end}, { 3, fun() -> has_superfluous_schedulers() end}, + { 5, fun() -> purify_is_running() end}, { 6, fun() -> is_debug() end}, {10, fun() -> is_cover() end}, {10, fun() -> is_valgrind() end} @@ -2740,6 +2751,58 @@ is_valgrind() -> _ -> true end. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% DEBUGGER INTERFACE %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% purify_is_running() -> false|true +%% +%% Tests if Purify is currently running. + +purify_is_running() -> + case catch erlang:system_info({error_checker, running}) of + {'EXIT', _} -> false; + Res -> Res + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% purify_new_leaks() -> false|BytesLeaked +%% BytesLeaked = integer() +%% +%% Checks for new memory leaks if Purify is active. +%% Returns the number of bytes leaked, or false if Purify +%% is not running. +purify_new_leaks() -> + case catch erlang:system_info({error_checker, memory}) of + {'EXIT', _} -> false; + Leaked when is_integer(Leaked) -> Leaked + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% purify_new_fds_inuse() -> false|FdsInuse +%% FdsInuse = integer() +%% +%% Checks for new file descriptors in use. +%% Returns the number of new file descriptors in use, or false +%% if Purify is not running. +purify_new_fds_inuse() -> + case catch erlang:system_info({error_checker, fd}) of + {'EXIT', _} -> false; + Inuse when is_integer(Inuse) -> Inuse + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% purify_format(Format, Args) -> ok +%% Format = string() +%% Args = lists() +%% +%% Outputs the formatted string to Purify's logfile,if Purify is active. +purify_format(Format, Args) -> + (catch erlang:system_info({error_checker, io_lib:format(Format, Args)})), + ok. + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% Apply given function and reply to caller or proxy. diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl index 9412c43187..48fe90a4d5 100644 --- a/lib/common_test/src/test_server_ctrl.erl +++ b/lib/common_test/src/test_server_ctrl.erl @@ -2163,6 +2163,7 @@ do_add_end_per_suite_and_skip(LastMod, LastRef, Mod, FwMod) -> %% Runs the specified tests, then displays/logs the summary. run_test_cases(TestSpec, Config, TimetrapData) -> + test_server:init_purify(), case lists:member(no_src, get(test_server_logopts)) of true -> ok; @@ -3796,7 +3797,7 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, %% run the test case {Result,DetectedFail,ProcsBefore,ProcsAfter} = - run_test_case_apply(Mod, Func, [UpdatedArgs], GrName, + run_test_case_apply(Num, Mod, Func, [UpdatedArgs], GrName, RunInit, TimetrapData), {Time,RetVal,Loc,Opts,Comment} = case Result of @@ -4366,7 +4367,7 @@ do_format_exception(Reason={Error,Stack}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% run_test_case_apply(Mod, Func, Args, Name, RunInit, +%% run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit, %% TimetrapData) -> %% {{Time,RetVal,Loc,Opts,Comment},DetectedFail,ProcessesBefore,ProcessesAfter} | %% {{died,Reason,unknown,Comment},DetectedFail,ProcessesBefore,ProcessesAfter} @@ -4380,9 +4381,9 @@ do_format_exception(Reason={Error,Stack}) -> %% ProcessesBefore = ProcessesAfter = integer() %% -run_test_case_apply(Mod, Func, Args, Name, RunInit, +run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit, TimetrapData) -> - test_server:run_test_case_apply({Mod,Func,Args,Name,RunInit, + test_server:run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit, TimetrapData}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl index 3d4ae1a189..54f452825f 100644 --- a/lib/stdlib/test/id_transform_SUITE.erl +++ b/lib/stdlib/test/id_transform_SUITE.erl @@ -61,8 +61,13 @@ id_transform(Config) when is_list(Config) -> "erl_id_trans.erl"]), {ok,erl_id_trans,Bin} = compile:file(File,[binary]), {module,erl_id_trans} = code:load_binary(erl_id_trans, File, Bin), - ct:timetrap({hours,1}), - run_in_test_suite(). + case test_server:purify_is_running() of + false -> + ct:timetrap({hours,1}), + run_in_test_suite(); + true -> + {skip,"Valgrind (too slow)"} + end. run_in_test_suite() -> SuperDir = filename:dirname(filename:dirname(code:which(?MODULE))), -- cgit v1.2.3 From 214d71f577e8e21ea2e27da60b1e3bd0494a6627 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 29 Aug 2017 16:42:14 +0200 Subject: [ct] Cleanup and rename purify related functions as valgrind --- erts/emulator/test/process_SUITE.erl | 2 +- lib/common_test/src/test_server.erl | 68 ++++++++++---------------------- lib/common_test/src/test_server_ctrl.erl | 2 +- lib/stdlib/test/id_transform_SUITE.erl | 2 +- 4 files changed, 23 insertions(+), 51 deletions(-) diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index bcf459e4fb..a9f20f9928 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -152,7 +152,7 @@ spawn_with_binaries(Config) when is_list(Config) -> TwoMeg = lists:duplicate(1024, L), Fun = fun() -> spawn(?MODULE, binary_owner, [list_to_binary(TwoMeg)]), receive after 1 -> ok end end, - Iter = case test_server:purify_is_running() of + Iter = case test_server:is_valgrind() of true -> 10; false -> 150 end, diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl index a47b3f824f..dc6b7a536c 100644 --- a/lib/common_test/src/test_server.erl +++ b/lib/common_test/src/test_server.erl @@ -21,7 +21,7 @@ -define(DEFAULT_TIMETRAP_SECS, 60). %%% TEST_SERVER_CTRL INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export([run_test_case_apply/1,init_target_info/0,init_purify/0]). +-export([run_test_case_apply/1,init_target_info/0,init_valgrind/0]). -export([cover_compile/1,cover_analyse/2]). %%% TEST_SERVER_SUP INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -50,8 +50,8 @@ -export([break/1,break/2,break/3,continue/0,continue/1]). %%% DEBUGGER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --export([purify_new_leaks/0, purify_format/2, purify_new_fds_inuse/0, - purify_is_running/0]). +-export([valgrind_new_leaks/0, valgrind_format/2, + is_valgrind/0]). %%% PRIVATE EXPORTED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -export([]). @@ -73,8 +73,8 @@ init_target_info() -> username=test_server_sup:get_username(), cookie=atom_to_list(erlang:get_cookie())}. -init_purify() -> - purify_new_leaks(). +init_valgrind() -> + valgrind_new_leaks(). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -367,11 +367,11 @@ stick_all_sticky(Node,Sticky) -> %% cover. run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,TimetrapData}) -> - purify_format("Test case #~w ~w:~w/1", [CaseNum, Mod, Func]), case is_valgrind() of false -> ok; true -> + valgrind_format("Test case #~w ~w:~w/1", [CaseNum, Mod, Func]), os:putenv("VALGRIND_LOGFILE_INFIX",atom_to_list(Mod)++"."++ atom_to_list(Func)++"-") end, @@ -379,7 +379,7 @@ run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,TimetrapData}) -> Result = run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData), ProcAft = erlang:system_info(process_count), - purify_new_leaks(), + valgrind_new_leaks(), DetFail = get(test_server_detected_fail), {Result,DetFail,ProcBef,ProcAft}. @@ -1836,7 +1836,6 @@ timetrap_scale_factor() -> timetrap_scale_factor([ { 2, fun() -> has_lock_checking() end}, { 3, fun() -> has_superfluous_schedulers() end}, - { 5, fun() -> purify_is_running() end}, { 6, fun() -> is_debug() end}, {10, fun() -> is_cover() end}, {10, fun() -> is_valgrind() end} @@ -2746,59 +2745,32 @@ is_commercial() -> %% %% Returns true if valgrind is running, else false is_valgrind() -> - case os:getenv("TS_RUN_VALGRIND") of - false -> false; - _ -> true + case catch erlang:system_info({valgrind, running}) of + {'EXIT', _} -> false; + Res -> Res end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% DEBUGGER INTERFACE %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% purify_is_running() -> false|true -%% -%% Tests if Purify is currently running. - -purify_is_running() -> - case catch erlang:system_info({error_checker, running}) of - {'EXIT', _} -> false; - Res -> Res - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% purify_new_leaks() -> false|BytesLeaked -%% BytesLeaked = integer() -%% -%% Checks for new memory leaks if Purify is active. -%% Returns the number of bytes leaked, or false if Purify -%% is not running. -purify_new_leaks() -> - case catch erlang:system_info({error_checker, memory}) of - {'EXIT', _} -> false; - Leaked when is_integer(Leaked) -> Leaked - end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% purify_new_fds_inuse() -> false|FdsInuse -%% FdsInuse = integer() -%% -%% Checks for new file descriptors in use. -%% Returns the number of new file descriptors in use, or false -%% if Purify is not running. -purify_new_fds_inuse() -> - case catch erlang:system_info({error_checker, fd}) of - {'EXIT', _} -> false; - Inuse when is_integer(Inuse) -> Inuse - end. +%% valgrind_new_leaks() -> ok +%% +%% Checks for new memory leaks if Valgrind is active. +valgrind_new_leaks() -> + catch erlang:system_info({valgrind, memory}), + ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% purify_format(Format, Args) -> ok +%% valgrind_format(Format, Args) -> ok %% Format = string() %% Args = lists() %% -%% Outputs the formatted string to Purify's logfile,if Purify is active. -purify_format(Format, Args) -> - (catch erlang:system_info({error_checker, io_lib:format(Format, Args)})), +%% Outputs the formatted string to Valgrind's logfile,if Valgrind is active. +valgrind_format(Format, Args) -> + (catch erlang:system_info({valgrind, io_lib:format(Format, Args)})), ok. diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl index 48fe90a4d5..71978c7267 100644 --- a/lib/common_test/src/test_server_ctrl.erl +++ b/lib/common_test/src/test_server_ctrl.erl @@ -2163,7 +2163,7 @@ do_add_end_per_suite_and_skip(LastMod, LastRef, Mod, FwMod) -> %% Runs the specified tests, then displays/logs the summary. run_test_cases(TestSpec, Config, TimetrapData) -> - test_server:init_purify(), + test_server:init_valgrind(), case lists:member(no_src, get(test_server_logopts)) of true -> ok; diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl index 54f452825f..186df41d3f 100644 --- a/lib/stdlib/test/id_transform_SUITE.erl +++ b/lib/stdlib/test/id_transform_SUITE.erl @@ -61,7 +61,7 @@ id_transform(Config) when is_list(Config) -> "erl_id_trans.erl"]), {ok,erl_id_trans,Bin} = compile:file(File,[binary]), {module,erl_id_trans} = code:load_binary(erl_id_trans, File, Bin), - case test_server:purify_is_running() of + case test_server:is_valgrind() of false -> ct:timetrap({hours,1}), run_in_test_suite(); -- cgit v1.2.3 From f388cb3d4c3c442220b75c9d1626601791fea4bc Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 31 Aug 2017 16:43:48 +0200 Subject: erts: Suppress false memory leak for dlerror --- erts/emulator/valgrind/suppress.patched.3.6.0 | 7 +++++++ erts/emulator/valgrind/suppress.standard | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/erts/emulator/valgrind/suppress.patched.3.6.0 b/erts/emulator/valgrind/suppress.patched.3.6.0 index fcde4a0123..29f2d3d62d 100644 --- a/erts/emulator/valgrind/suppress.patched.3.6.0 +++ b/erts/emulator/valgrind/suppress.patched.3.6.0 @@ -374,3 +374,10 @@ fun:erts_debug_set_internal_state_2 fun:process_main } +{ +Thread specific dlerror buffer. Either bug in libc or valgrind. +Memcheck:Leak +... +fun:_dlerror_run +... +} diff --git a/erts/emulator/valgrind/suppress.standard b/erts/emulator/valgrind/suppress.standard index bb07c92fc1..99a3ee4048 100644 --- a/erts/emulator/valgrind/suppress.standard +++ b/erts/emulator/valgrind/suppress.standard @@ -342,3 +342,11 @@ fun:erts_debug_set_internal_state_2 fun:process_main } +{ +Thread specific dlerror buffer. Either bug in libc or valgrind. +Memcheck:Leak +... +fun:_dlerror_run +... +} + -- cgit v1.2.3