aboutsummaryrefslogtreecommitdiffstats
path: root/system/doc/design_principles/sup_princ.xml
diff options
context:
space:
mode:
Diffstat (limited to 'system/doc/design_principles/sup_princ.xml')
-rw-r--r--system/doc/design_principles/sup_princ.xml349
1 files changed, 349 insertions, 0 deletions
diff --git a/system/doc/design_principles/sup_princ.xml b/system/doc/design_principles/sup_princ.xml
new file mode 100644
index 0000000000..067fd31961
--- /dev/null
+++ b/system/doc/design_principles/sup_princ.xml
@@ -0,0 +1,349 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ 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.
+
+ </legalnotice>
+
+ <title>Supervisor Behaviour</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>sup_princ.xml</file>
+ </header>
+ <p>This section should be read in conjunction with
+ <c>supervisor(3)</c>, where all details about the supervisor
+ behaviour is given.</p>
+
+ <section>
+ <title>Supervision Principles</title>
+ <p>A supervisor is responsible for starting, stopping and
+ monitoring its child processes. The basic idea of a supervisor is
+ that it should keep its child processes alive by restarting them
+ when necessary.</p>
+ <p>Which child processes to start and monitor is specified by a
+ list of <seealso marker="#spec">child specifications</seealso>.
+ The child processes are started in the order specified by this
+ list, and terminated in the reversed order.</p>
+ </section>
+
+ <section>
+ <title>Example</title>
+ <p>The callback module for a supervisor starting the server from
+ the <seealso marker="gen_server_concepts#ex">gen_server chapter</seealso>
+ could look like this:</p>
+ <marker id="ex"></marker>
+ <code type="none">
+-module(ch_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link(ch_sup, []).
+
+init(_Args) ->
+ {ok, {{one_for_one, 1, 60},
+ [{ch3, {ch3, start_link, []},
+ permanent, brutal_kill, worker, [ch3]}]}}.</code>
+ <p><c>one_for_one</c> is the <seealso marker="#strategy">restart strategy</seealso>.</p>
+ <p>1 and 60 defines the <seealso marker="#frequency">maximum restart frequency</seealso>.</p>
+ <p>The tuple <c>{ch3, ...}</c> is a <seealso marker="#spec">child specification</seealso>.</p>
+ </section>
+
+ <section>
+ <marker id="strategy"></marker>
+ <title>Restart Strategy</title>
+
+ <section>
+ <title>one_for_one</title>
+ <p>If a child process terminates, only that process is restarted.</p>
+ <marker id="sup4"></marker>
+ <image file="../design_principles/sup4.gif">
+ <icaption>One_For_One Supervision</icaption>
+ </image>
+ </section>
+
+ <section>
+ <title>one_for_all</title>
+ <p>If a child process terminates, all other child processes are
+ terminated and then all child processes, including
+ the terminated one, are restarted.</p>
+ <marker id="sup5"></marker>
+ <image file="../design_principles/sup5.gif">
+ <icaption>One_For_All Supervision</icaption>
+ </image>
+ </section>
+
+ <section>
+ <title>rest_for_one</title>
+ <p>If a child process terminates, the 'rest' of the child
+ processes -- i.e. the child processes after the terminated
+ process in start order -- are terminated. Then the terminated
+ child process and the rest of the child processes are restarted.</p>
+ </section>
+ </section>
+
+ <section>
+ <marker id="frequency"></marker>
+ <title>Maximum Restart Frequency</title>
+ <p>The supervisors have a built-in mechanism to limit the number of
+ restarts which can occur in a given time interval. This is
+ determined by the values of the two parameters <c>MaxR</c> and
+ <c>MaxT</c> in the start specification returned by the callback
+ function <c>init</c>:</p>
+ <code type="none">
+init(...) ->
+ {ok, {{RestartStrategy, MaxR, MaxT},
+ [ChildSpec, ...]}}.</code>
+ <p>If more than <c>MaxR</c> number of restarts occur in the last
+ <c>MaxT</c> seconds, then the supervisor terminates all the child
+ processes and then itself.</p>
+ <p>When the supervisor terminates, then the next higher level
+ supervisor takes some action. It either restarts the terminated
+ supervisor, or terminates itself.</p>
+ <p>The intention of the restart mechanism is to prevent a situation
+ where a process repeatedly dies for the same reason, only to be
+ restarted again.</p>
+ </section>
+
+ <section>
+ <marker id="spec"></marker>
+ <title>Child Specification</title>
+ <p>This is the type definition for a child specification:</p>
+ <code type="none"><![CDATA[
+{Id, StartFunc, Restart, Shutdown, Type, Modules}
+ Id = term()
+ StartFunc = {M, F, A}
+ M = F = atom()
+ A = [term()]
+ Restart = permanent | transient | temporary
+ Shutdown = brutal_kill | integer() &gt;=0 | infinity
+ Type = worker | supervisor
+ Modules = [Module] | dynamic
+ Module = atom()]]></code>
+ <list type="bulleted">
+ <item>
+ <p><c>Id</c> is a name that is used to identify the child
+ specification internally by the supervisor.</p>
+ </item>
+ <item>
+ <p><c>StartFunc</c> defines the function call used to start
+ the child process. It is a module-function-arguments tuple
+ used as <c>apply(M, F, A)</c>.</p>
+ <p>It should be (or result in) a call to
+ <c>supervisor:start_link</c>, <c>gen_server:start_link</c>,
+ <c>gen_fsm:start_link</c> or <c>gen_event:start_link</c>.
+ (Or a function compliant with these functions, see
+ <c>supervisor(3)</c> for details.</p>
+ </item>
+ <item>
+ <p><c>Restart</c> defines when a terminated child process should
+ be restarted.</p>
+ <list type="bulleted">
+ <item>A <c>permanent</c> child process is always restarted.</item>
+ <item>A <c>temporary</c> child process is never restarted.</item>
+ <item>A <c>transient</c> child process is restarted only if it
+ terminates abnormally, i.e. with another exit reason than
+ <c>normal</c>.</item>
+ </list>
+ </item>
+ <item>
+ <marker id="shutdown"></marker>
+ <p><c>Shutdown</c> defines how a child process should be
+ terminated.</p>
+ <list type="bulleted">
+ <item><c>brutal_kill</c> means the child process is
+ unconditionally terminated using <c>exit(Child, kill)</c>.</item>
+ <item>An integer timeout value means that the supervisor tells
+ the child process to terminate by calling
+ <c>exit(Child, shutdown)</c> and then waits for an exit
+ signal back. If no exit signal is received within
+ the specified time, the child process is unconditionally
+ terminated using <c>exit(Child, kill)</c>.</item>
+ <item>If the child process is another supervisor, it should be
+ set to <c>infinity</c> to give the subtree enough time to
+ shutdown.</item>
+ </list>
+ </item>
+ <item>
+ <p><c>Type</c> specifies if the child process is a supervisor or
+ a worker.</p>
+ </item>
+ <item>
+ <p><c>Modules</c> should be a list with one element
+ <c>[Module]</c>, where <c>Module</c> is the name of
+ the callback module, if the child process is a supervisor,
+ gen_server or gen_fsm. If the child process is a gen_event,
+ <c>Modules</c> should be <c>dynamic</c>.</p>
+ <p>This information is used by the release handler during
+ upgrades and downgrades, see
+ <seealso marker="release_handling">Release Handling</seealso>.</p>
+ </item>
+ </list>
+ <p>Example: The child specification to start the server <c>ch3</c>
+ in the example above looks like:</p>
+ <code type="none">
+{ch3,
+ {ch3, start_link, []},
+ permanent, brutal_kill, worker, [ch3]}</code>
+ <p>Example: A child specification to start the event manager from
+ the chapter about
+ <seealso marker="events#mgr">gen_event</seealso>:</p>
+ <code type="none">
+{error_man,
+ {gen_event, start_link, [{local, error_man}]},
+ permanent, 5000, worker, dynamic}</code>
+ <p>Both the server and event manager are registered processes which
+ can be expected to be accessible at all times, thus they are
+ specified to be <c>permanent</c>.</p>
+ <p><c>ch3</c> does not need to do any cleaning up before
+ termination, thus no shutdown time is needed but
+ <c>brutal_kill</c> should be sufficient. <c>error_man</c> may
+ need some time for the event handlers to clean up, thus
+ <c>Shutdown</c> is set to 5000 ms.</p>
+ <p>Example: A child specification to start another supervisor:</p>
+ <code type="none">
+{sup,
+ {sup, start_link, []},
+ transient, infinity, supervisor, [sup]}</code>
+ </section>
+
+ <section>
+ <marker id="super_tree"></marker>
+ <title>Starting a Supervisor</title>
+ <p>In the example above, the supervisor is started by calling
+ <c>ch_sup:start_link()</c>:</p>
+ <code type="none">
+start_link() ->
+ supervisor:start_link(ch_sup, []).</code>
+ <p><c>ch_sup:start_link</c> calls the function
+ <c>supervisor:start_link/2</c>. This function spawns and links to
+ a new process, a supervisor.</p>
+ <list type="bulleted">
+ <item>The first argument, <c>ch_sup</c>, is the name of
+ the callback module, that is the module where the <c>init</c>
+ callback function is located.</item>
+ <item>The second argument, [], is a term which is passed as-is to
+ the callback function <c>init</c>. Here, <c>init</c> does not
+ need any indata and ignores the argument.</item>
+ </list>
+ <p>In this case, the supervisor is not registered. Instead its pid
+ must be used. A name can be specified by calling
+ <c>supervisor:start_link({local, Name}, Module, Args)</c> or
+ <c>supervisor:start_link({global, Name}, Module, Args)</c>.</p>
+ <p>The new supervisor process calls the callback function
+ <c>ch_sup:init([])</c>. <c>init</c> is expected to return
+ <c>{ok, StartSpec}</c>:</p>
+ <code type="none">
+init(_Args) ->
+ {ok, {{one_for_one, 1, 60},
+ [{ch3, {ch3, start_link, []},
+ permanent, brutal_kill, worker, [ch3]}]}}.</code>
+ <p>The supervisor then starts all its child processes according to
+ the child specifications in the start specification. In this case
+ there is one child process, <c>ch3</c>.</p>
+ <p>Note that <c>supervisor:start_link</c> is synchronous. It does
+ not return until all child processes have been started.</p>
+ </section>
+
+ <section>
+ <title>Adding a Child Process</title>
+ <p>In addition to the static supervision tree, we can also add
+ dynamic child processes to an existing supervisor with
+ the following call:</p>
+ <code type="none">
+supervisor:start_child(Sup, ChildSpec)</code>
+ <p><c>Sup</c> is the pid, or name, of the supervisor.
+ <c>ChildSpec</c> is a <seealso marker="#spec">child specification</seealso>.</p>
+ <p>Child processes added using <c>start_child/2</c> behave in
+ the same manner as the other child processes, with the following
+ important exception: If a supervisor dies and is re-created, then
+ all child processes which were dynamically added to the supervisor
+ will be lost.</p>
+ </section>
+
+ <section>
+ <title>Stopping a Child Process</title>
+ <p>Any child process, static or dynamic, can be stopped in
+ accordance with the shutdown specification:</p>
+ <code type="none">
+supervisor:terminate_child(Sup, Id)</code>
+ <p>The child specification for a stopped child process is deleted
+ with the following call:</p>
+ <code type="none">
+supervisor:delete_child(Sup, Id)</code>
+ <p><c>Sup</c> is the pid, or name, of the supervisor.
+ <c>Id</c> is the id specified in the <seealso marker="#spec">child specification</seealso>.</p>
+ <p>As with dynamically added child processes, the effects of
+ deleting a static child process is lost if the supervisor itself
+ restarts.</p>
+ </section>
+
+ <section>
+ <title>Simple-One-For-One Supervisors</title>
+ <p>A supervisor with restart strategy <c>simple_one_for_one</c> is
+ a simplified one_for_one supervisor, where all child processes are
+ dynamically added instances of the same process.</p>
+ <p>Example of a callback module for a simple_one_for_one supervisor:</p>
+ <code type="none">
+-module(simple_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link(simple_sup, []).
+
+init(_Args) ->
+ {ok, {{simple_one_for_one, 0, 1},
+ [{call, {call, start_link, []},
+ temporary, brutal_kill, worker, [call]}]}}.</code>
+ <p>When started, the supervisor will not start any child processes.
+ Instead, all child processes are added dynamically by calling:</p>
+ <code type="none">
+supervisor:start_child(Sup, List)</code>
+ <p><c>Sup</c> is the pid, or name, of the supervisor.
+ <c>List</c> is an arbitrary list of terms which will be added to
+ the list of arguments specified in the child specification. If
+ the start function is specified as <c>{M, F, A}</c>, then
+ the child process is started by calling
+ <c>apply(M, F, A++List)</c>.</p>
+ <p>For example, adding a child to <c>simple_sup</c> above:</p>
+ <code type="none">
+supervisor:start_child(Pid, [id1])</code>
+ <p>results in the child process being started by calling
+ <c>apply(call, start_link, []++[id1])</c>, or actually:</p>
+ <code type="none">
+call:start_link(id1)</code>
+ </section>
+
+ <section>
+ <title>Stopping</title>
+ <p>Since the supervisor is part of a supervision tree, it will
+ automatically be terminated by its supervisor. When asked to
+ shutdown, it will terminate all child processes in reversed start
+ order according to the respective shutdown specifications, and
+ then terminate itself.</p>
+ </section>
+</chapter>
+