aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/beam/erl_trace.c16
-rw-r--r--erts/emulator/test/system_profile_SUITE.erl32
2 files changed, 42 insertions, 6 deletions
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index fb3f0d4e62..1654ea58d9 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -3020,6 +3020,7 @@ profile_runnable_proc(Process *p, Eterm status){
Eterm *hp, msg;
Eterm where = am_undefined;
ErlHeapFragment *bp = NULL;
+ int use_current = 1;
#ifndef ERTS_SMP
#define LOCAL_HEAP_SIZE (4 + 6 + ERTS_TRACE_PATCH_TS_MAX_SIZE)
@@ -3032,12 +3033,19 @@ profile_runnable_proc(Process *p, Eterm status){
Uint hsz = 4 + 6 + patch_ts_size(erts_system_profile_ts_type)-1;
#endif
- if (!p->current) {
- p->current = find_function_from_pc(p->i);
+ if (ERTS_PROC_IS_EXITING(p)) {
+ use_current = 0;
+ /* could probably set 'where' to 'exiting' here,
+ * though it's not documented as such */
+ } else {
+ if (!p->current) {
+ p->current = find_function_from_pc(p->i);
+ }
+ use_current = p->current != NULL;
}
#ifdef ERTS_SMP
- if (!p->current) {
+ if (!use_current) {
hsz -= 4;
}
@@ -3045,7 +3053,7 @@ profile_runnable_proc(Process *p, Eterm status){
hp = bp->mem;
#endif
- if (p->current) {
+ if (use_current) {
where = TUPLE3(hp, p->current[0], p->current[1], make_small(p->current[2])); hp += 4;
} else {
where = make_small(0);
diff --git a/erts/emulator/test/system_profile_SUITE.erl b/erts/emulator/test/system_profile_SUITE.erl
index a56b394765..2e359b11ce 100644
--- a/erts/emulator/test/system_profile_SUITE.erl
+++ b/erts/emulator/test/system_profile_SUITE.erl
@@ -27,7 +27,7 @@
system_profile_on_and_off/1,
runnable_procs/1, runnable_ports/1,
dont_profile_profiler/1,
- scheduler/1]).
+ scheduler/1, sane_location/1]).
-export([profiler_process/1, ring_loop/1, port_echo_start/0,
list_load/0, run_load/2]).
@@ -40,7 +40,8 @@ suite() ->
all() ->
[system_profile_on_and_off, runnable_procs,
- runnable_ports, scheduler, dont_profile_profiler].
+ runnable_ports, scheduler, dont_profile_profiler,
+ sane_location].
%% No specification clause needed for an init function in a conf case!!!
@@ -183,6 +184,33 @@ dont_profile_profiler(Config) when is_list(Config) ->
exit(Pid,kill),
ok.
+%% Check sane location (of exits)
+sane_location(Config) when is_list(Config) ->
+ Check = spawn_link(fun() -> flush_sane_location() end),
+ erlang:system_profile(Check, [runnable_procs]),
+ Me = self(),
+ Pids = [spawn_link(fun() -> wat(Me) end) || _ <- lists:seq(1,100)],
+ [receive {Pid,ok} -> ok end || Pid <- Pids],
+ Check ! {Me, done},
+ receive {Check,ok} -> ok end,
+ ok.
+
+wat(Pid) ->
+ Pid ! {self(), ok}.
+
+flush_sane_location() ->
+ receive
+ {profile,_,_,{M,F,A},_} when is_atom(M), is_atom(F),
+ is_integer(A) ->
+ flush_sane_location();
+ {profile,_,_,0,_} ->
+ flush_sane_location();
+ {Pid,done} when is_pid(Pid) ->
+ Pid ! {self(), ok};
+ M ->
+ ct:fail({badness,M})
+ end.
+
%%% Check scheduler profiling