diff options
Diffstat (limited to 'lib/observer/test/crashdump_viewer_SUITE.erl')
-rw-r--r-- | lib/observer/test/crashdump_viewer_SUITE.erl | 109 |
1 files changed, 90 insertions, 19 deletions
diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl index 7a582436b4..03ab0c20e1 100644 --- a/lib/observer/test/crashdump_viewer_SUITE.erl +++ b/lib/observer/test/crashdump_viewer_SUITE.erl @@ -120,27 +120,63 @@ start_stop(Config) when is_list(Config) -> Dump = hd(?config(dumps,Config)), timer:sleep(1000), - ProcsBefore = length(processes()), + ProcsBefore = processes(), + NumProcsBefore = length(ProcsBefore), ok = crashdump_viewer:start(Dump), - true = is_pid(whereis(crashdump_viewer_server)), - true = is_pid(whereis(cdv_wx)), - true = is_pid(whereis(cdv_proc_cb)), - true = is_pid(whereis(cdv_port_cb)), - true = is_pid(whereis(cdv_ets_cb)), - true = is_pid(whereis(cdv_timer_cb)), - true = is_pid(whereis(cdv_fun_cb)), - true = is_pid(whereis(cdv_atom_cb)), - true = is_pid(whereis(cdv_dist_cb)), - true = is_pid(whereis(cdv_mod_cb)), + ExpectedRegistered = [crashdump_viewer_server, + cdv_wx, + cdv_proc_cb, + cdv_proc_cb__holder, + cdv_port_cb, + cdv_port_cb__holder, + cdv_ets_cb, + cdv_ets_cb__holder, + cdv_timer_cb, + cdv_timer_cb__holder, + cdv_fun_cb, + cdv_fun_cb__holder, + cdv_atom_cb, + cdv_atom_cb__holder, + cdv_dist_cb, + cdv_dist_cb__holder, + cdv_mod_cb, + cdv_mod_cb__holder], + Regs=[begin + P=whereis(N), + {P,N,erlang:monitor(process,P)} + end || N <- ExpectedRegistered], + ct:log("CDV procs: ~n~p~n",[Regs]), + [true=is_pid(P) || {P,_,_} <- Regs], timer:sleep(5000), % give some time to live ok = crashdump_viewer:stop(), - timer:sleep(1000), % give some time to stop - undefined = whereis(crashdump_viewer_server), - undefined = whereis(cdv_wx), - ProcsAfter=length(processes()), - ProcsAfter=ProcsBefore, + recv_downs(Regs), + timer:sleep(2000), + ProcsAfter = processes(), + NumProcsAfter = length(ProcsAfter), + if NumProcsAfter=/=NumProcsBefore -> + ct:log("Before but not after:~n~p~n", + [[{P,process_info(P)} || P <- ProcsBefore -- ProcsAfter]]), + ct:log("After but not before:~n~p~n", + [[{P,process_info(P)} || P <- ProcsAfter -- ProcsBefore]]), + ct:fail("leaking processes"); + true -> + ok + end, ok. +recv_downs([]) -> + ok; +recv_downs(Regs) -> + receive + {'DOWN',Ref,process,_Pid,_} -> + ct:log("Got 'DOWN' for process ~n~p~n",[_Pid]), + recv_downs(lists:keydelete(Ref,3,Regs)) + after 30000 -> + ct:log("Timeout waiting for down:~n~p~n", + [[{Reg,process_info(P)} || {P,_,_}=Reg <- Regs]]), + ct:log("Message queue:~n~p~n",[process_info(self(),messages)]) + end. + %% Try to load nonexisting file non_existing(Config) when is_list(Config) -> ExpectedReason = "non-existing-file is not an Erlang crash dump\n", @@ -265,10 +301,12 @@ wait_for_progress_done() -> %%%----------------------------------------------------------------- %%% General check of what is displayed for a dump browse_file(File) -> - io:format("Browsing file: ~s~n",[File]), + io:format("~nBrowsing file: ~s",[File]), ok = start_backend(File), + io:format(" backend started",[]), + {ok,_GI=#general_info{},_GenTW} = crashdump_viewer:general_info(), {ok,Procs,_ProcsTW} = crashdump_viewer:processes(), {ok,Ports,_PortsTW} = crashdump_viewer:ports(), @@ -285,10 +323,16 @@ browse_file(File) -> {ok,_HashTabs,_HashTabsTW} = crashdump_viewer:hash_tables(), {ok,_IndexTabs,_IndexTabsTW} = crashdump_viewer:index_tables(), + io:format(" info read",[]), + lookat_all_pids(Procs), + io:format(" pids ok",[]), lookat_all_ports(Ports), + io:format(" ports ok",[]), lookat_all_mods(Mods), + io:format(" mods ok",[]), lookat_all_nodes(Nodes), + io:format(" nodes ok",[]), Procs. % used as second arg to special/2 @@ -303,6 +347,7 @@ special(File,Procs) -> [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), Pid = pid_to_list(Pid0), {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), #proc{dict=Dict} = ProcDetails, @@ -314,6 +359,7 @@ special(File,Procs) -> ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict), {ok,<<_:SSize/binary>>} = crashdump_viewer:expand_binary({SOffset,SSize,SPos}), + io:format(" expand binary ok",[]), ['#CDVPid',X1,Y1,Z1] = proplists:get_value(ext_pid,Dict), ChannelStr1 = integer_to_list(X1), @@ -323,22 +369,34 @@ special(File,Procs) -> integer_to_list(Z1) ++ ">", {error,{other_node,ChannelStr1}} = crashdump_viewer:proc_details(ExtPid), + io:format(" process details external ok",[]), ['#CDVPort',X2,Y2] = proplists:get_value(port,Dict), ChannelStr2 = integer_to_list(X2), Port = "#Port<"++ChannelStr2++"."++integer_to_list(Y2)++">", {ok,_PortDetails=#port{},[]} = crashdump_viewer:port(Port), + io:format(" port details ok",[]), ['#CDVPort',X3,Y3] = proplists:get_value(ext_port,Dict), ChannelStr3 = integer_to_list(X3), ExtPort = "#Port<"++ChannelStr3++"."++integer_to_list(Y3)++">", {error,{other_node,ChannelStr3}} = crashdump_viewer:port(ExtPort), + io:format(" port details external ok",[]), {ok,[_Ets=#ets_table{}],[]} = crashdump_viewer:ets_tables(Pid), - {ok,[_Timer=#timer{}],[]} = crashdump_viewer:timers(Pid), + io:format(" ets tables ok",[]), + + {ok,[#timer{pid=Pid0,name=undefined}, + #timer{pid=Pid0,name="aaaaaaaa"}],[]} = + crashdump_viewer:timers(Pid), + {ok,AllTimers,_TimersTW} = crashdump_viewer:timers(all), + #timer{name="noexistproc"} = + lists:keyfind(undefined,#timer.pid,AllTimers), + io:format(" timers ok:",[]), {ok,Mod1=#loaded_mod{},[]} = crashdump_viewer:loaded_mod_details(atom_to_list(?helper_mod)), + io:format(" modules ok",[]), #loaded_mod{current_size=CS, old_size=OS, old_attrib=A,old_comp_info=C}=Mod1, true = is_integer(CS), @@ -347,6 +405,7 @@ special(File,Procs) -> true = (C=/=undefined), {ok,Mod2=#loaded_mod{},[]} = crashdump_viewer:loaded_mod_details("application"), + io:format(" module details ok",[]), #loaded_mod{old_size="No old code exists", old_attrib=undefined, old_comp_info=undefined}=Mod2, @@ -428,8 +487,10 @@ do_create_dumps(DataDir,Rel) -> end. -%% Create a dump which has two visible nodes, one hidden and one +%% Create a dump which has three visible nodes, one hidden and one %% not connected node, and with monitors and links between nodes. +%% One of the visible nodes is stopped and started again in order to +%% get multiple creations. full_dist_dump(DataDir,Rel) -> Opt = rel_opt(Rel), Pz = "-pz \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"", @@ -450,6 +511,15 @@ full_dist_dump(DataDir,Rel) -> get_response(P4), get_response(P1), + %% start, stop and start a node in order to get multiple 'creations' + {ok,N5} = ?t:start_node(n5,peer,Opt ++ PzOpt), + P51 = rpc:call(N5,?helper_mod,remote_proc,[P1,Creator]), + get_response(P51), + ?t:stop_node(N5), + {ok,N5} = ?t:start_node(n5,peer,Opt ++ PzOpt), + P52 = rpc:call(N5,?helper_mod,remote_proc,[P1,Creator]), + get_response(P52), + {aaaaaaaa,N1} ! {hello,from,other,node}, % distribution message ?t:stop_node(N3), @@ -458,6 +528,7 @@ full_dist_dump(DataDir,Rel) -> ?t:stop_node(N2), ?t:stop_node(N4), + ?t:stop_node(N5), CD. get_response(P) -> |