diff options
author | Dan Gudmundsson <[email protected]> | 2012-05-09 14:42:09 +0200 |
---|---|---|
committer | Dan Gudmundsson <[email protected]> | 2012-05-09 14:42:09 +0200 |
commit | 04745e3fbb5fe194bc7561f96300d821e7f9e2aa (patch) | |
tree | d0108a23fda15d664f85b0dd7eb307a0c9400d2b | |
parent | 75dbcf3ce8cb63dea0d674b67cb5d3d64d250e2a (diff) | |
parent | 5628fb8d88f91b3ef8e140e2658a6f61b4e42adb (diff) | |
download | otp-04745e3fbb5fe194bc7561f96300d821e7f9e2aa.tar.gz otp-04745e3fbb5fe194bc7561f96300d821e7f9e2aa.tar.bz2 otp-04745e3fbb5fe194bc7561f96300d821e7f9e2aa.zip |
Merge branch 'dgud/observer/bug-fixes/OTP-10075' into maint
* dgud/observer/bug-fixes/OTP-10075:
[observer] Add more popup menus and info selected pid
[observer] Fix scrollbars in app-viewer
[observer] Allow bifs when selecting functions for trace
[observer] Fix gui-crash when table_copies couldn't be spawned
[observer] Fix dead processes
[observer] Ask epmd for local nodes
[observer] Remove appmon ref when node goes down
-rw-r--r-- | lib/observer/src/observer_app_wx.erl | 30 | ||||
-rw-r--r-- | lib/observer/src/observer_pro_wx.erl | 21 | ||||
-rw-r--r-- | lib/observer/src/observer_procinfo.erl | 26 | ||||
-rw-r--r-- | lib/observer/src/observer_traceoptions_wx.erl | 8 | ||||
-rw-r--r-- | lib/observer/src/observer_tv_table.erl | 2 | ||||
-rw-r--r-- | lib/observer/src/observer_wx.erl | 40 |
6 files changed, 82 insertions, 45 deletions
diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl index 7eac2b8fab..f9be11e05a 100644 --- a/lib/observer/src/observer_app_wx.erl +++ b/lib/observer/src/observer_app_wx.erl @@ -147,11 +147,11 @@ setup_scrollbar({CW, CH}, AppWin, #app{dim={W0,H0}}) -> H = max(H0,CH), PPC = 20, if W0 =< CW, H0 =< CH -> - wxScrolledWindow:setScrollbars(AppWin, W, H, 1, 1); + wxScrolledWindow:setScrollbars(AppWin, W, H, 0, 0); H0 =< CH -> - wxScrolledWindow:setScrollbars(AppWin, PPC, H, W div PPC+1, 1); + wxScrolledWindow:setScrollbars(AppWin, PPC, H, W div PPC+1, 0); W0 =< CW -> - wxScrolledWindow:setScrollbars(AppWin, W, PPC, 1, H div PPC+1); + wxScrolledWindow:setScrollbars(AppWin, W, PPC, 0, H div PPC+1); true -> wxScrolledWindow:setScrollbars(AppWin, PPC, PPC, W div PPC+1, H div PPC+1) end; @@ -204,7 +204,7 @@ handle_event(#wx{id=?ID_PROC_MSG, event=#wxCommand{type=command_menu_selected}}, handle_event(#wx{id=?ID_PROC_KILL, event=#wxCommand{type=command_menu_selected}}, State = #state{panel=Panel, sel={#box{s1=#str{pid=Pid}},_}}) -> - case observer_lib:user_term(Panel, "Enter Exit Reason", "") of + case observer_lib:user_term(Panel, "Enter Exit Reason", "kill") of cancel -> ok; {ok, Term} -> exit(Pid, Term); {error, Error} -> observer_lib:display_info_dialog(Error) @@ -267,24 +267,17 @@ handle_call(Event, From, _State) -> handle_cast(Event, _State) -> error({unhandled_cast, Event}). %%%%%%%%%% -handle_info({active, Node}, State = #state{parent=Parent, current=Curr, appmon=Appmon}) -> +handle_info({active, Node}, State = #state{parent=Parent, current=Curr}) -> create_menus(Parent, []), {ok, Pid} = appmon_info:start_link(Node, self(), []), - case Appmon of - undefined -> ok; - Pid -> ok; - _ -> %% Deregister me as client (and stop appmon if last) - exit(Appmon, normal) - end, appmon_info:app_ctrl(Pid, Node, true, []), (Curr =/= undefined) andalso appmon_info:app(Pid, Curr, true, []), {noreply, State#state{appmon=Pid}}; - -handle_info(not_active, State = #state{appmon=AppMon, current=Prev}) -> +handle_info(not_active, State = #state{appmon=AppMon}) -> appmon_info:app_ctrl(AppMon, node(AppMon), false, []), - (Prev =/= undefined) andalso appmon_info:app(AppMon, Prev, false, []), - {noreply, State}; - + lists:member(node(AppMon), nodes()) andalso exit(AppMon, normal), + observer_wx:set_status(""), + {noreply, State#state{appmon=undefined}}; handle_info({delivery, Pid, app_ctrl, _, Apps0}, State = #state{appmon=Pid, apps_w=LBox, current=Curr0}) -> Apps = [atom_to_list(App) || {_, App, {_, _, _}} <- Apps0], @@ -341,6 +334,7 @@ handle_mouse_click(Node = {#box{s1=#str{pid=Pid}},_}, Type, right_down -> popup_menu(Panel); _ -> ok end, + observer_wx:set_status(io_lib:format("Pid: ~p", [Pid])), wxWindow:refresh(AppWin), State#state{sel=Node}; handle_mouse_click(_, _, State = #state{sel=undefined}) -> @@ -349,6 +343,7 @@ handle_mouse_click(_, right_down, State=#state{panel=Panel}) -> popup_menu(Panel), State; handle_mouse_click(_, _, State=#state{app_w=AppWin}) -> + observer_wx:set_status(""), wxWindow:refresh(AppWin), State#state{sel=undefined}. @@ -376,10 +371,11 @@ popup_menu(Panel) -> wxMenu:append(Menu, ?ID_TRACE_NAME, "Trace named process"), wxMenu:append(Menu, ?ID_TRACE_TREE_PIDS, "Trace process tree"), wxMenu:append(Menu, ?ID_TRACE_TREE_NAMES, "Trace named process tree"), + wxMenu:append(Menu, ?ID_PROC_MSG, "Send Msg"), + wxMenu:append(Menu, ?ID_PROC_KILL, "Kill process"), wxWindow:popupMenu(Panel, Menu), wxMenu:destroy(Menu). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% locate_node(X, _Y, [{Box=#box{x=BX}, _Chs}|_Rest]) when X < BX -> diff --git a/lib/observer/src/observer_pro_wx.erl b/lib/observer/src/observer_pro_wx.erl index 7578215ff9..e2f3ddb02b 100644 --- a/lib/observer/src/observer_pro_wx.erl +++ b/lib/observer/src/observer_pro_wx.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011. All Rights Reserved. +%% Copyright Ericsson AB 2011-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -191,13 +191,20 @@ dump_to_file(Parent, FileName, Holder) -> start_procinfo(undefined, _Frame, Opened) -> Opened; start_procinfo(Pid, Frame, Opened) -> - case lists:member(Pid, Opened) of - true -> - Opened; - false -> - observer_procinfo:start(Pid, Frame, self()), - [Pid | Opened] + %% This code doesn't work until we collect which windows have been + %% closed maybe it should moved to observer_wx.erl + %% and add a global menu which remembers windows. + %% case lists:keyfind(Pid, 1, Opened) of + %% false -> + case observer_procinfo:start(Pid, Frame, self()) of + {error, _} -> Opened; + PI -> [{Pid, PI} | Opened] end. + %%; + %% {_, PI} -> + %% wxFrame:raise(PI), + %% Opened + %% end. call(Holder, What) -> Ref = erlang:monitor(process, Holder), diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl index ec08d3aff1..13e41cfe33 100644 --- a/lib/observer/src/observer_procinfo.erl +++ b/lib/observer/src/observer_procinfo.erl @@ -49,7 +49,8 @@ init([Pid, ParentFrame, Parent]) -> try Title=case observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, registered_name]) of [] -> io_lib:format("~p",[Pid]); - {registered_name, Registered} -> atom_to_list(Registered) + {registered_name, Registered} -> io_lib:format("~p (~p)",[Registered, Pid]); + undefined -> throw(process_undefined) end, Frame=wxFrame:new(ParentFrame, ?wxID_ANY, [atom_to_list(node(Pid)), $:, Title], [{style, ?wxDEFAULT_FRAME_STYLE}, {size, {850,600}}]), @@ -75,7 +76,10 @@ init([Pid, ParentFrame, Parent]) -> }} catch error:{badrpc, _} -> observer_wx:return_to_localnode(ParentFrame, node(Pid)), - {stop, badrpc, #state{parent=Parent, pid=Pid}} + {stop, badrpc}; + process_undefined -> + observer_lib:display_info_dialog("No such alive process"), + {stop, normal} end. init_panel(Notebook, Str, Pid, Fun) -> @@ -94,8 +98,11 @@ handle_event(#wx{event=#wxClose{type=close_window}}, State) -> handle_event(#wx{id=?wxID_CLOSE, event=#wxCommand{type=command_menu_selected}}, State) -> {stop, normal, State}; -handle_event(#wx{id=?REFRESH}, #state{pages=Pages}=State) -> - [(W#worker.callback)() || W <- Pages], +handle_event(#wx{id=?REFRESH}, #state{frame=Frame, pid=Pid, pages=Pages}=State) -> + try [(W#worker.callback)() || W <- Pages] + catch process_undefined -> + wxFrame:setTitle(Frame, io_lib:format("*DEAD* ~p",[Pid])) + end, {noreply, State}; handle_event(Event, _State) -> @@ -162,7 +169,8 @@ init_message_page(Parent, Pid) -> false -> wxTextCtrl:writeText(Text, Messages) end; - _ -> ok + _ -> + throw(process_undefined) end end, Update(), @@ -178,7 +186,8 @@ init_dict_page(Parent, Pid) -> Last = wxTextCtrl:getLastPosition(Text), wxTextCtrl:remove(Text, 0, Last), wxTextCtrl:writeText(Text, Dict); - _ -> ok + _ -> + throw(process_undefined) end end, Update(), @@ -216,7 +225,8 @@ init_stack_page(Parent, Pid) -> wxListCtrl:setItem(LCtrl, Row, 1, FileLine), Row+1 end, 0, RawBt); - _ -> ok + _ -> + throw(process_undefined) end end, Resize = fun(#wx{event=#wxSize{size={W,_}}},Ev) -> @@ -266,7 +276,7 @@ process_info_fields(Pid) -> RawInfo when is_list(RawInfo) -> observer_lib:fill_info(Struct, RawInfo); _ -> - ok + throw(process_undefined) end. item_list() -> diff --git a/lib/observer/src/observer_traceoptions_wx.erl b/lib/observer/src/observer_traceoptions_wx.erl index 6a634e06f0..e27f565abc 100644 --- a/lib/observer/src/observer_traceoptions_wx.erl +++ b/lib/observer/src/observer_traceoptions_wx.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011. All Rights Reserved. +%% Copyright Ericsson AB 2011-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -167,8 +167,10 @@ module_selector(Parent, Node) -> function_selector(Parent, Node, Module) -> Functions = observer_wx:try_rpc(Node, Module, module_info, [functions]), - Choices = lists:sort([{Name, Arity} || {Name, Arity} <- Functions, - not(erl_internal:guard_bif(Name, Arity))]), + Externals = observer_wx:try_rpc(Node, Module, module_info, [exports]), + + Choices = lists:usort([{Name, Arity} || {Name, Arity} <- Externals ++ Functions, + not(erl_internal:guard_bif(Name, Arity))]), ParsedChoices = parse_function_names(Choices), case check_selector(Parent, ParsedChoices) of [] -> [{Module, '_', '_'}]; diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl index f432173f57..3930f9ee26 100644 --- a/lib/observer/src/observer_tv_table.erl +++ b/lib/observer/src/observer_tv_table.erl @@ -453,7 +453,7 @@ get_attr(Table, Item) -> Ref = erlang:monitor(process, Table), Table ! {get_attr, self(), Item}, receive - {'DOWN', Ref, _, _, _} -> ""; + {'DOWN', Ref, _, _, _} -> wx:null(); {Table, Res} -> erlang:demonitor(Ref), Res diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl index e2b256d768..ce3f48a05d 100644 --- a/lib/observer/src/observer_wx.erl +++ b/lib/observer/src/observer_wx.erl @@ -20,7 +20,7 @@ -behaviour(wx_object). -export([start/0]). --export([create_menus/2, get_attrib/1, get_tracer/0, +-export([create_menus/2, get_attrib/1, get_tracer/0, set_status/1, create_txt_dialog/4, try_rpc/4, return_to_localnode/2]). -export([init/1, handle_event/2, handle_cast/2, terminate/2, code_change/3, @@ -58,7 +58,8 @@ perf_panel, active_tab, node, - nodes + nodes, + prev_node="" }). start() -> @@ -73,6 +74,9 @@ create_menus(Object, Menus) when is_list(Menus) -> get_attrib(What) -> wx_object:call(observer, {get_attrib, What}). +set_status(What) -> + wx_object:cast(observer, {status_bar, What}). + get_tracer() -> wx_object:call(observer, get_tracer). @@ -258,20 +262,21 @@ handle_event(#wx{id = ?ID_CONNECT, event = #wxCommand{type = command_menu_select handle_event(#wx{id = ?ID_PING, event = #wxCommand{type = command_menu_selected}}, #state{frame = Frame} = State) -> UpdState = case create_connect_dialog(ping, State) of - cancel -> State; + cancel -> State; {value, Value} when is_list(Value) -> try Node = list_to_atom(Value), case net_adm:ping(Node) of pang -> create_txt_dialog(Frame, "Connect failed", "Pang", ?wxICON_EXCLAMATION), - State; + State#state{prev_node=Value}; pong -> - change_node_view(Node, State) + State1 = change_node_view(Node, State), + State1#state{prev_node=Value} end catch _:_ -> create_txt_dialog(Frame, "Connect failed", "Pang", ?wxICON_EXCLAMATION), - State + State#state{prev_node=Value} end end, {noreply, UpdState}; @@ -288,6 +293,10 @@ handle_event(Event, State) -> Pid ! Event, {noreply, State}. +handle_cast({status_bar, Msg}, State=#state{status_bar=SB}) -> + wxStatusBar:setStatusText(SB, Msg), + {noreply, State}; + handle_cast(_Cast, State) -> {noreply, State}. @@ -439,8 +448,8 @@ pid2panel(Pid, #state{pro_panel=Pro, sys_panel=Sys, end. -create_connect_dialog(ping, #state{frame = Frame}) -> - Dialog = wxTextEntryDialog:new(Frame, "Connect to node"), +create_connect_dialog(ping, #state{frame = Frame, prev_node=Prev}) -> + Dialog = wxTextEntryDialog:new(Frame, "Connect to node", [{value, Prev}]), case wxDialog:showModal(Dialog) of ?wxID_OK -> Value = wxTextEntryDialog:getValue(Dialog), @@ -560,7 +569,16 @@ remove_menu_items([], _MB) -> ok. get_nodes() -> - Nodes = [node()| nodes()], + Nodes0 = case erlang:is_alive() of + false -> []; + true -> + case net_adm:names() of + {error, _} -> nodes(); + {ok, Names} -> + epmd_nodes(Names) ++ nodes() + end + end, + Nodes = lists:usort(Nodes0), {_, Menues} = lists:foldl(fun(Node, {Id, Acc}) when Id < ?LAST_NODES_MENU_ID -> {Id + 1, [#create_menu{id=Id + ?FIRST_NODES_MENU_ID, @@ -568,6 +586,10 @@ get_nodes() -> end, {1, []}, Nodes), {Nodes, lists:reverse(Menues)}. +epmd_nodes(Names) -> + [_, Host] = string:tokens(atom_to_list(node()),"@"), + [list_to_atom(Name ++ [$@|Host]) || {Name, _} <- Names]. + update_node_list(State = #state{menubar=MenuBar}) -> {Nodes, NodesMenuItems} = get_nodes(), NodeMenuId = wxMenuBar:findMenu(MenuBar, "Nodes"), |