From 6c298a7bfa332e5b7d153648d741740abc3bcdf8 Mon Sep 17 00:00:00 2001
From: Steve Vinoski <vinoski@ieee.org>
Date: Wed, 19 Mar 2014 11:45:11 -0400
Subject: fix sys:get_state/1,2 and sys:replace_state/2,3 when sys suspended

Add two new system callbacks Module:system_get_state/1 and
Module:system_replace_state/2 to allow sys:get_state/1,2 and
sys:replace_state/2,3 to operate correctly even if a process is sys
suspended. Modify gen_server, gen_fsm, and gen_event to support the new
callbacks.

If a callback module does not export these functions, then by default the
Misc value (the same as that passed as the final argument to
sys:handle_system_msg/6, and returned as part of the return value of
sys:get_status/1,2) is treated as the callback module's state.

The previous behaviour of intercepting the system message and passing a
tuple of size 2 as the last argument to sys:handle_system_msg/6 is no
longer supported.

Add tests to verify the correctness of sys:get_state/1,2 and
sys:replace_state/2,3 when processes are sys suspended. Add two tests for
modules that implement special processes, one that exports
system_get_state/1 and system_replace_state/2 and one that doesn't.

Much of the credit for this patch goes to James Fish, who reported the
initial problem and implemented much of the fix.
---
 system/doc/design_principles/spec_proc.xml | 40 +++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 4 deletions(-)

(limited to 'system/doc')

diff --git a/system/doc/design_principles/spec_proc.xml b/system/doc/design_principles/spec_proc.xml
index 8de7a5fe03..d55427aa10 100644
--- a/system/doc/design_principles/spec_proc.xml
+++ b/system/doc/design_principles/spec_proc.xml
@@ -130,7 +130,8 @@ ok
 -export([alloc/0, free/1]).
 -export([init/1]).
 -export([system_continue/3, system_terminate/4,
-         write_debug/3]).
+         write_debug/3,
+         system_get_state/1, system_replace_state/2]).
 
 start_link() ->
     proc_lib:start_link(ch4, init, [self()]).
@@ -177,9 +178,21 @@ loop(Chs, Parent, Deb) ->
 system_continue(Parent, Deb, Chs) ->
     loop(Chs, Parent, Deb).
 
-system_terminate(Reason, Parent, Deb, Chs) ->
+system_terminate(Reason, _Parent, _Deb, _Chs) ->
     exit(Reason).
 
+system_get_state(Chs) ->
+    {ok, Chs}.
+
+system_replace_state(StateFun, Chs) ->
+    try
+        NChs = StateFun(Chs),
+        {ok, NChs, NChs}
+    catch
+        _:_ ->
+            {ok, Chs, Chs}
+    end.
+
 write_debug(Dev, Event, Name) ->
     io:format(Dev, "~p event = ~p~n", [Name, Event]).</pre>
       <p>Example on how the simple debugging functions in <c>sys</c> can
@@ -366,8 +379,15 @@ Module:system_terminate(Reason, Parent, Deb, State)</code>
         <item><c>Module</c> is the name of the module.</item>
         <item><c>Deb</c> is the debug structure.</item>
         <item><c>State</c> is a term describing the internal state and
-         is passed to <c>system_continue</c>/<c>system_terminate</c>.</item>
+         is passed to <c>system_continue</c>/<c>system_terminate</c>/
+         <c>system_get_state</c>/<c>system_replace_state</c>.</item>
       </list>
+      <p>If the process should return its state <c>handle_system_msg</c> will call:</p>
+      <code type="none">
+Module:system_get_state(State)</code>
+      <p>or if the process should replace its state using the fun <c>StateFun</c>:</p>
+      <code type="none">
+Module:system_replace_state(StateFun, State)</code>
       <p>In the example:</p>
       <code type="none">
 loop(Chs, Parent, Deb) ->
@@ -383,7 +403,19 @@ system_continue(Parent, Deb, Chs) ->
     loop(Chs, Parent, Deb).
 
 system_terminate(Reason, Parent, Deb, Chs) ->
-    exit(Reason).</code>
+    exit(Reason).
+
+system_get_state(Chs) ->
+    {ok, Chs, Chs}.
+
+system_replace_state(StateFun, Chs) ->
+    try
+        NChs = StateFun(Chs),
+        {ok, NChs, NChs}
+    catch
+        _:_ ->
+            {ok, Chs, Chs}
+    end.</code>
       <p>If the special process is set to trap exits, note that if
         the parent process terminates, the expected behavior is to
         terminate with the same reason:</p>
-- 
cgit v1.2.3


From cbcac6f0d55907dda2e0c385eba44eac2e7923d2 Mon Sep 17 00:00:00 2001
From: Steve Vinoski <vinoski@ieee.org>
Date: Wed, 19 Mar 2014 11:49:12 -0400
Subject: remove tuple funs from special process documentation

Support for tuple funs was removed in R16B but the documentation for
special processes, sys, and proc_lib in the OTP Design Principles still
showed examples using them, and those examples no longer worked. Fix the
examples to use regular functions instead and fix the documentation to
reflect the changes.
---
 system/doc/design_principles/spec_proc.xml | 37 +++++++++++-------------------
 1 file changed, 14 insertions(+), 23 deletions(-)

(limited to 'system/doc')

diff --git a/system/doc/design_principles/spec_proc.xml b/system/doc/design_principles/spec_proc.xml
index d55427aa10..69bf2e0448 100644
--- a/system/doc/design_principles/spec_proc.xml
+++ b/system/doc/design_principles/spec_proc.xml
@@ -157,15 +157,15 @@ init(Parent) ->
 loop(Chs, Parent, Deb) ->
     receive
         {From, alloc} ->
-            Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
+            Deb2 = sys:handle_debug(Deb, fun ch4:write_debug/3,
                                     ch4, {in, alloc, From}),
             {Ch, Chs2} = alloc(Chs),
             From ! {ch4, Ch},
-            Deb3 = sys:handle_debug(Deb2, {ch4, write_debug},
+            Deb3 = sys:handle_debug(Deb2, fun ch4:write_debug/3,
                                     ch4, {out, {ch4, Ch}, From}),
             loop(Chs2, Parent, Deb3);
         {free, Ch} ->
-            Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
+            Deb2 = sys:handle_debug(Deb, fun ch4:write_debug/3,
                                     ch4, {in, {free, Ch}}),
             Chs2 = free(Ch, Chs),
             loop(Chs2, Parent, Deb2);
@@ -185,13 +185,8 @@ system_get_state(Chs) ->
     {ok, Chs}.
 
 system_replace_state(StateFun, Chs) ->
-    try
-        NChs = StateFun(Chs),
-        {ok, NChs, NChs}
-    catch
-        _:_ ->
-            {ok, Chs, Chs}
-    end.
+    NChs = StateFun(Chs),
+    {ok, NChs, NChs}.
 
 write_debug(Dev, Event, Name) ->
     io:format(Dev, "~p event = ~p~n", [Name, Event]).</pre>
@@ -294,10 +289,10 @@ sys:handle_debug(Deb, Func, Info, Event) => Deb1</code>
           <p><c>Deb</c> is the debug structure.</p>
         </item>
         <item>
-          <p><c>Func</c> is a tuple <c>{Module, Name}</c> (or a fun) and
-            should specify a (user defined) function used to format
+          <p><c>Func</c> is a fun specifying
+            a (user defined) function used to format
             trace output. For each system event, the format function is
-            called as <c>Module:Name(Dev, Event, Info)</c>, where:</p>
+            called as <c>Func(Dev, Event, Info)</c>, where:</p>
           <list type="bulleted">
             <item>
               <p><c>Dev</c> is the IO device to which the output should
@@ -332,15 +327,15 @@ sys:handle_debug(Deb, Func, Info, Event) => Deb1</code>
 loop(Chs, Parent, Deb) ->
     receive
         {From, alloc} ->
-            Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
+            Deb2 = sys:handle_debug(Deb, fun ch4:write_debug/3,
                                     ch4, {in, alloc, From}),
             {Ch, Chs2} = alloc(Chs),
             From ! {ch4, Ch},
-            Deb3 = sys:handle_debug(Deb2, {ch4, write_debug},
+            Deb3 = sys:handle_debug(Deb2, fun ch4:write_debug/3,
                                     ch4, {out, {ch4, Ch}, From}),
             loop(Chs2, Parent, Deb3);
         {free, Ch} ->
-            Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
+            Deb2 = sys:handle_debug(Deb, fun ch4:write_debug/3,
                                     ch4, {in, {free, Ch}}),
             Chs2 = free(Ch, Chs),
             loop(Chs2, Parent, Deb2);
@@ -409,13 +404,9 @@ system_get_state(Chs) ->
     {ok, Chs, Chs}.
 
 system_replace_state(StateFun, Chs) ->
-    try
-        NChs = StateFun(Chs),
-        {ok, NChs, NChs}
-    catch
-        _:_ ->
-            {ok, Chs, Chs}
-    end.</code>
+    NChs = StateFun(Chs),
+    {ok, NChs, NChs}.
+</code>
       <p>If the special process is set to trap exits, note that if
         the parent process terminates, the expected behavior is to
         terminate with the same reason:</p>
-- 
cgit v1.2.3