diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /system/doc/design_principles/sup_princ.xml | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'system/doc/design_principles/sup_princ.xml')
-rw-r--r-- | system/doc/design_principles/sup_princ.xml | 349 |
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() >=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> + |