diff options
Diffstat (limited to 'lib/pman/src/pman_process.erl')
-rw-r--r-- | lib/pman/src/pman_process.erl | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/lib/pman/src/pman_process.erl b/lib/pman/src/pman_process.erl new file mode 100644 index 0000000000..276407a0f1 --- /dev/null +++ b/lib/pman/src/pman_process.erl @@ -0,0 +1,317 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%---------------------------------------------------------------------- +%% Purpose : A front-end to the erlang:process_info() functions, that +%% can handle processes on different nodes in a transparent +%% way. +%% Also some convenience functions for process info, as well +%% as some application specific functions for process +%% classification. +%%---------------------------------------------------------------------- + +-module(pman_process). + +-export([pinfo/1, pinfo/2, + r_processes/1, + function_info/1, + get_name/1, msg/1, reds/1, psize/1, + is_running/1, + is_pid_or_shell/1, + get_pid/1, + is_system_process/1, + is_hidden_by_module/2 + ]). + +%% List of registered name that will make a prodcess a "SYSTEM"-process +-define(SYSTEM_REG_NAMES, + [ + %% kernel + application_controller, + erl_reply, + auth, + boot_server, + code_server, + disk_log_server, + disk_log_sup, + erl_prim_loader, + error_logger, + file_server_2, + fixtable_server, + global_group, + global_name_server, + heart, + inet_gethost_native, + inet_gethost_native_sup, + init, + kernel_config, + kernel_safe_sup, + kernel_sup, + net_kernel, + net_sup, + rex, + user, + os_server, + ddll_server, + erl_epmd, + inet_db, + pg2, + + %% stdlib + timer_server, + rsh_starter, + take_over_monitor, + pool_master, + dets, + + %% sasl + sasl_safe_sup, sasl_sup, alarm_handler, overload, + release_handler, + + %% gs + gs_frontend + ]). + +%% List of module:function/arity calls that will make the caller a +%% "SYSTEM"-process. +%% +-define(SYSTEM_INIT_CALLS, + [{application_master,init,4}, + {application_master,start_it,4}, + {inet_tcp_dist,accept_loop,2}, + {net_kernel,ticker,2}, + {supervisor_bridge,user_sup,1}, + {user_drv,server,2}, + {group,server,3}, + {kernel_config,init,1}, + {inet_tcp_dist,do_accept,6}, + {inet_tcp_dist,do_setup,6}, + {pman_main,init,2}, + {pman_buf_printer,init,2}, + {pman_buf_converter,init,2}, + {pman_buf_buffer,init,1}, + {gstk,init,1}, + {gstk_port_handler,init,2}, + {gstk,worker_init,1} + ]). + +%% List of module:function/arity calls that will make the executing +%% process a "SYSTEM"-process. +-define(SYSTEM_RUNNING_CALLS, + [{file_io_server,server_loop,1}, + {global,loop_the_locker,1}, + {global,collect_deletions,2}, + {global,loop_the_registrar,0}, + {gs_frontend,request,2}, + {shell,get_command1,5}, + {shell,eval_loop,3}, + {io,wait_io_mon_reply,2}, + {pman_module_info,loop,1}, + {pman_options,dialog,3}, + {pman_options,loop,1}, + {pman_relay_server,loop,1}, + {pman_shell,monitor_loop,1}, + {pman_shell,safe_loop,2} + ]). + +%% pinfo(Pid) -> [{Item, Info}] | undefined +%% pinfo(Pid, Item) -> Info | undefined +%% A version of process_info/1 that handles pid on remote nodes as well. +pinfo({_, Pid}) -> % Handle internal process format + pinfo(Pid); +pinfo(Pid) when node(Pid)==node() -> + process_info(Pid); +pinfo(Pid) -> + case rpc:call(node(Pid), erlang, process_info, [Pid]) of + {badrpc, _} -> undefined; + Res -> Res + end. + +pinfo({_, Pid}, Item) -> % Handle internal process format + pinfo(Pid, Item); +pinfo(Pid, Item) when node(Pid)==node() -> + case process_info(Pid, Item) of + {Item, Info} -> Info; + "" -> ""; % Item == registered_name + undefined -> undefined + end; +pinfo(Pid, Item) -> + case rpc:call(node(Pid), erlang, process_info, [Pid, Item]) of + {badrpc, _} -> undefined; + {Item, Info} -> Info; + "" -> ""; % Item == registered_name + undefined -> undefined + end. + +%% function_info(Pid) -> {M, F, A} +%% Returns the initial function for the specified process. +function_info(Pid) -> + case pinfo(Pid, current_function) of + {Module, Function, Arity} -> + {Module, Function, Arity}; + undefined -> + {unknown, unknown, 0} + end. + +%% r_processes(Node) -> Pids +%% Return a list of all processes at Node. +%% +%% If there is a problem with getting information from a remote +%% node, an empty list is returned. +r_processes(Node) -> + ordsets:from_list(r_processes1(Node)). + +r_processes1(Node) -> + if + Node==node() -> + processes(); + true -> + case rpc:block_call(Node, erlang, processes, []) of + {badrpc, _} -> + []; + Pids -> Pids + end + end. + +%% is_running(Object) -> {true, {shell,Pid}} | {true, Pid} | false +%% Object = {shell, Pid} | {link, Pid, ?} | Pid +is_running({shell,Pid}) -> + case is_running(Pid) of + {true,Pid} -> + {true,{shell,Pid}}; + false -> + false + end; +is_running({link,Pid,_}) -> + is_running(Pid); +is_running(Pid) -> + case is_pid_or_shell(Pid) of + true -> + case pinfo(Pid) of + undefined -> false; + _PInfo -> {true, Pid} + end; + false -> + false + end. + +%% is_pid_or_shell(Object) -> bool() +%% Checks if the argument is an pid or a tuple {shell, Pid}. +is_pid_or_shell({shell,Pid}) when is_pid(Pid) -> + true; +is_pid_or_shell(Pid) when is_pid(Pid) -> + true; +is_pid_or_shell(_) -> + false. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% get_pid/1 - returns the Pid of the object provided that +%% it is a proper process specifier. +%% +%% Arguments: +%% Object A process specifier +%% +%% Returns: +%% The Pid. + +get_pid({shell,Pid}) -> + Pid; +get_pid(Pid) when is_pid(Pid) -> + Pid. + +%% is_system_process(Pid) -> bool() +%% Returns true if Pid is a "system process". +%% This is a prototype version, use file configuration later. +is_system_process(Pid) -> + catch is_system_process2(Pid). + +is_system_process2(Pid) -> + + %% Test if the registered name is a system registered name + case pinfo(Pid, registered_name) of + undefined -> ignore; + "" -> ignore; + Name -> + case lists:member(Name, ?SYSTEM_REG_NAMES) of + true -> throw(true); + false -> ignore + end + end, + + %% Test if the start specification is a "system start function" + MFAi = case pinfo(Pid, initial_call) of + {proc_lib, init_p, 5} -> + proc_lib:translate_initial_call(Pid); % {M,F,A} | Fun + Res -> Res % {M,F,A} | undefined + end, + case lists:member(MFAi, ?SYSTEM_INIT_CALLS) of + true -> throw(true); + false -> ignore + end, + + %% Test if the running specification is a "system running function" + case pinfo(Pid, current_function) of + undefined -> false; + MFAc -> + lists:member(MFAc, ?SYSTEM_RUNNING_CALLS) + end. + +%% is_hidden_by_module(Pid, Modules) -> bool() +%% Checks if Pid is to be hidden because it executes code from one +%% of Modules +is_hidden_by_module(Pid, Modules) -> + case pinfo(Pid, current_function) of + {Module, _Function, _Arity} -> + lists:member(Module, Modules); + undefined -> false + end. + +%% get_name(Pid) -> Name | " " +%% Returns the registered name of a process, if any, or " " otherwise. +get_name(Pid) -> + case pinfo(Pid, registered_name) of + undefined -> " "; + "" -> " "; + Name -> Name + end. + +%% msg(Pid) -> int() +msg(Pid) -> + case pinfo(Pid, messages) of + undefined -> 0; + Msgs -> length(Msgs) + end. + +%% reds(Pid) -> int() +reds(Pid) -> + case pinfo(Pid, reductions) of + undefined -> 0; + Reds -> Reds + end. + +%% psize(Pid) -> int() +%% Returns the total process size (stack + heap). +psize(Pid) -> + Stack = pinfo(Pid, stack_size), + Heap = pinfo(Pid, heap_size), + case {Heap, Stack} of + {undefined, undefined} -> 0; + {undefined, Sz} -> Sz; + {Sz, undefined} -> Sz; + {Sz0, Sz1} -> Sz0 + Sz1 + end. |