aboutsummaryrefslogtreecommitdiffstats
path: root/lib/pman/src/pman_process.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/pman/src/pman_process.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/pman/src/pman_process.erl')
-rw-r--r--lib/pman/src/pman_process.erl317
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.