From 2cd7cf62e9b1e456c0ccc963d92a9170c3af8251 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Tue, 22 Sep 2015 18:08:02 -0400 Subject: [PATCH] fix: handling 'undefined' from erlang:process_info/2 Process could die between the time we get its PID from erlang:processes() and when we start calling erlang:process_info/2 on it; or even somewhere between the process_info calls. The choice is between returning partial info (that we were able to collect before process died) and just skipping the process. For now, I'm choosing to skip the process (throwing away any partial info collected). --- src/beam_stats.app.src | 2 +- src/beam_stats_process.erl | 45 +++++++++++++++++++++--------------- src/beam_stats_processes.erl | 3 ++- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/beam_stats.app.src b/src/beam_stats.app.src index 1597668..2dbb0cf 100644 --- a/src/beam_stats.app.src +++ b/src/beam_stats.app.src @@ -1,7 +1,7 @@ {application, beam_stats, [ {description, "Periodic VM stats production and consumption."}, - {vsn, "0.8.1"}, + {vsn, "0.8.2"}, {registered, []}, {applications, [ kernel diff --git a/src/beam_stats_process.erl b/src/beam_stats_process.erl index e2751ea..b0b7da4 100644 --- a/src/beam_stats_process.erl +++ b/src/beam_stats_process.erl @@ -43,25 +43,33 @@ %% ============================================================================ -spec of_pid(pid()) -> - t(). + none % when process is dead + | {some, t()} % when process is alive + . of_pid(Pid) -> - Dict = pid_info_exn(Pid, dictionary), - Ancestry = - #beam_stats_process_ancestry - { raw_initial_call = pid_info_exn(Pid, initial_call) - , otp_initial_call = hope_kv_list:get(Dict, '$initial_call') - , otp_ancestors = hope_kv_list:get(Dict, '$ancestors') - }, - ?T - { pid = Pid - , registered_name = pid_info_opt(Pid, registered_name) - , ancestry = Ancestry - , status = pid_info_exn(Pid, status) - , memory = pid_info_exn(Pid, memory) - , total_heap_size = pid_info_exn(Pid, total_heap_size) - , stack_size = pid_info_exn(Pid, stack_size) - , message_queue_len = pid_info_exn(Pid, message_queue_len) - }. + try + Dict = pid_info_exn(Pid, dictionary), + Ancestry = + #beam_stats_process_ancestry + { raw_initial_call = pid_info_exn(Pid, initial_call) + , otp_initial_call = hope_kv_list:get(Dict, '$initial_call') + , otp_ancestors = hope_kv_list:get(Dict, '$ancestors') + }, + T = + ?T + { pid = Pid + , registered_name = pid_info_opt(Pid, registered_name) + , ancestry = Ancestry + , status = pid_info_exn(Pid, status) + , memory = pid_info_exn(Pid, memory) + , total_heap_size = pid_info_exn(Pid, total_heap_size) + , stack_size = pid_info_exn(Pid, stack_size) + , message_queue_len = pid_info_exn(Pid, message_queue_len) + }, + {some, T} + catch throw:{process_dead, _} -> + none + end. -spec print(t()) -> ok. @@ -122,6 +130,7 @@ pid_info_opt(Pid, Key) -> case {Key, beam_stats_source:erlang_process_info(Pid, Key)} of {registered_name, []} -> none ; {_ , {Key, Value}} -> {some, Value} + ; {_ , undefined} -> throw({process_dead, Pid}) end. %% ============================================================================ diff --git a/src/beam_stats_processes.erl b/src/beam_stats_processes.erl index 90c3886..1b3fcb2 100644 --- a/src/beam_stats_processes.erl +++ b/src/beam_stats_processes.erl @@ -22,7 +22,8 @@ t(). collect() -> Pids = beam_stats_source:erlang_processes(), - Ps = [beam_stats_process:of_pid(P) || P <- Pids], + PsOpts = [beam_stats_process:of_pid(P) || P <- Pids], + Ps = [P || {some, P} <- PsOpts], ?T { individual_stats = Ps -- 2.20.1