File 0353-erts-Fix-bug-in-system_profile.patch of Package erlang

From 7c485575e78b6537586bb0902658b890b22a2186 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Wed, 16 May 2018 16:35:23 +0200
Subject: [PATCH] erts: Fix bug in system_profile

seen to cause redundant {profile,_,active,_,_} messages
when process is terminating.
---
 erts/emulator/beam/erl_process.c            | 14 ++---
 erts/emulator/test/system_profile_SUITE.erl | 86 +++++++++++++++++------------
 2 files changed, 57 insertions(+), 43 deletions(-)

diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 54724fd62d..b0178c3fc1 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -6674,13 +6674,13 @@ change_proc_schedule_state(Process *p,
 
 	if (((n & (ERTS_PSFLG_SUSPENDED
 		   | ERTS_PSFLG_ACTIVE)) == ERTS_PSFLG_ACTIVE)
-	    && (!(a & (ERTS_PSFLG_ACTIVE_SYS
-		       | ERTS_PSFLG_RUNNING
-		       | ERTS_PSFLG_RUNNING_SYS
-		       | ERTS_PSFLG_DIRTY_RUNNING
-		       | ERTS_PSFLG_DIRTY_RUNNING_SYS)
-		  && (!(a & ERTS_PSFLG_ACTIVE)
-		      || (a & ERTS_PSFLG_SUSPENDED))))) {
+            & ((a & (ERTS_PSFLG_SUSPENDED
+                     | ERTS_PSFLG_ACTIVE)) != ERTS_PSFLG_ACTIVE)
+	    & !(a & (ERTS_PSFLG_ACTIVE_SYS
+                     | ERTS_PSFLG_RUNNING
+                     | ERTS_PSFLG_RUNNING_SYS
+                     | ERTS_PSFLG_DIRTY_RUNNING
+                     | ERTS_PSFLG_DIRTY_RUNNING_SYS))) {
 	    /* We activated a prevously inactive process */
 	    profile_runnable_proc(p, am_active);
 	}
diff --git a/erts/emulator/test/system_profile_SUITE.erl b/erts/emulator/test/system_profile_SUITE.erl
index 2e359b11ce..73d466fe28 100644
--- a/erts/emulator/test/system_profile_SUITE.erl
+++ b/erts/emulator/test/system_profile_SUITE.erl
@@ -95,18 +95,20 @@ do_runnable_procs({TsType, TsTypeFlag}) ->
     % FIXME: Set #laps and #nodes in config file
     Nodes = 10,
     Laps = 10,
-    Master = ring(Nodes),
+    All = ring(Nodes, [link,monitor]),
+    [Master | _] = All,
     undefined = erlang:system_profile(Pid, [runnable_procs]++TsTypeFlag),
     % loop a message
     ok = ring_message(Master, message, Laps),
+    ok = kill_ring(Master),
+    [receive {'DOWN', _, process, P, _} -> ok end || P <- All],
     Events = get_profiler_events(),
-    kill_em_all = kill_ring(Master),
     erlang:system_profile(undefined, []),
     put(master, Master),
     put(laps, Laps),
     true = has_runnable_event(TsType, Events),
     Pids = sort_events_by_pid(Events),
-    ok = check_events(TsType, Pids),
+    ok = check_events(TsType, Pids, (Laps+1)*2+2, (Laps+1)*2),
     erase(),
     exit(Pid,kill),
     ok.
@@ -139,7 +141,7 @@ do_runnable_ports({TsType, TsTypeFlag}, Config) ->
     erlang:system_profile(undefined, []),
     true = has_runnable_event(TsType, Events),
     Pids = sort_events_by_pid(Events),
-    ok = check_events(TsType, Pids),
+    ok = check_events(TsType, Pids, Laps*2+2, Laps*2),
     erase(),
     exit(Pid,kill),
     ok.
@@ -172,12 +174,12 @@ dont_profile_profiler(Config) when is_list(Config) ->
 
     Nodes = 10,
     Laps = 10,
-    Master = ring(Nodes),
+    [Master|_] = ring(Nodes, [link]),
     undefined = erlang:system_profile(Pid, [runnable_procs]),
     % loop a message
     ok = ring_message(Master, message, Laps),
     erlang:system_profile(undefined, []),
-    kill_em_all = kill_ring(Master),
+    ok = kill_ring(Master),
     Events = get_profiler_events(),
     false  = has_profiler_pid_event(Events, Pid),
 
@@ -249,27 +251,28 @@ check_block_system({TsType, TsTypeFlag}, Nodes) ->
 
 %%% Check events
 
-check_events(_TsType, []) -> ok;
-check_events(TsType, [Pid | Pids]) ->
+check_events(_TsType, [], _, _) -> ok;
+check_events(TsType, [Pid | Pids], ExpMaster, ExpMember) ->
     Master = get(master),
-    Laps = get(laps),
     CheckPids = get(pids),
     {Events, N} = get_pid_events(Pid),
     ok = check_event_flow(Events),
     ok = check_event_ts(TsType, Events),
     IsMember = lists:member(Pid, CheckPids),
-    case Pid of
-    	Master ->
-	    io:format("Expected ~p and got ~p profile events from ~p: ok~n", [Laps*2+2, N, Pid]),
-	    N = Laps*2 + 2,
-    	    check_events(TsType, Pids);
-	Pid when IsMember == true ->
-	    io:format("Expected ~p and got ~p profile events from ~p: ok~n", [Laps*2, N, Pid]),
-	    N = Laps*2,
-    	    check_events(TsType, Pids);
-	Pid ->
-	    check_events(TsType, Pids)
-    end.
+    {Title,Exp} = case Pid of
+                      Master -> {master,ExpMaster};
+                      Pid when IsMember == true -> {member,ExpMember};
+                      _ -> {other,N}
+                  end,
+    ok = case N of
+             Exp -> ok;
+             _ ->
+                 io:format("Expected ~p and got ~p profile events from ~p ~p:~n~p~n",
+                           [Exp, N, Title, Pid, Events]),
+                 error
+         end,
+    check_events(TsType, Pids, ExpMaster, ExpMember).
+
 
 %% timestamp consistency check for descending timestamps
 
@@ -297,7 +300,13 @@ check_event_ts(TsType, [{Pid, _, _, TS1}=Event | Events], {Pid,_,_,TS0}) ->
 %% consistency check for active vs. inactive activity (runnable)
 
 check_event_flow(Events) ->
-    check_event_flow(Events, undefined).
+    case check_event_flow(Events, undefined) of
+        ok -> ok;
+        Error ->
+            io:format("Events = ~p\n", [Events]),
+            Error
+    end.
+
 check_event_flow([], _) -> ok;
 check_event_flow([Event | PidEvents], undefined) ->
     check_event_flow(PidEvents, Event);
@@ -337,10 +346,11 @@ sort_events_by_pid([Event | Events],Pids) ->
 %% API
 
 % Returns master pid
-ring(N) -> 
-    Pids = build_ring(N, []),
+ring(N, SpawnOpt) -> 
+    Pids = build_ring(N, [], SpawnOpt),
     put(pids, Pids),
-    setup_ring(Pids).
+    setup_ring(Pids),
+    Pids.
 
 ring_message(Master, Message, Laps) ->
     Master ! {message, Master, Laps, Message},
@@ -348,13 +358,19 @@ ring_message(Master, Message, Laps) ->
     	{laps_complete, Master} -> ok
     end.
 
-kill_ring(Master) -> Master ! kill_em_all.
+kill_ring(Master) ->
+    Master ! kill_em_all,
+    ok.
 
 %% Process ring helpers
 
-build_ring(0, Pids) -> Pids;
-build_ring(N, Pids) ->
-    build_ring(N - 1, [spawn_link(?MODULE, ring_loop, [undefined]) | Pids]).
+build_ring(0, Pids, _) -> Pids;
+build_ring(N, Pids, SpawnOpt) ->
+    Pid = case spawn_opt(?MODULE, ring_loop, [undefined], SpawnOpt) of
+              {P,_} -> P;
+              P -> P
+          end,
+    build_ring(N-1, [Pid | Pids], SpawnOpt).
 
 setup_ring([Master | Relayers]) ->
     % Relayers may not include the master pid
@@ -383,15 +399,13 @@ ring_loop(RelayTo) ->
         {message, Master, Lap, Msg}=Message ->
             case {self(), Lap} of
                 {Master, 0} ->
-                    get(supervisor) ! {laps_complete, self()},
-                    ring_loop(RelayTo);
+                    get(supervisor) ! {laps_complete, self()};
                 {Master, Lap} ->
-                    RelayTo ! {message, Master, Lap - 1, Msg},
-                    ring_loop(RelayTo);
+                    RelayTo ! {message, Master, Lap - 1, Msg};
                 _ ->
-                    RelayTo ! Message,
-                    ring_loop(RelayTo)
-            end
+                    RelayTo ! Message
+            end,
+            ring_loop(RelayTo)
     end.
 
 %%%
-- 
2.16.3

openSUSE Build Service is sponsored by