Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reference implementation for EEP 56 #4638

Merged
merged 13 commits into from Apr 16, 2021
Merged
@@ -1,2 +1,2 @@

supervisor_incorrect_return.erl:14:1: The inferred return type of init/1 ({'ok',{{'one_against_one',0,1},[{_,_,_,_,_,_},...]}}) has nothing in common with 'ignore' | {'ok',{{'one_for_all',non_neg_integer(),pos_integer()} | {'one_for_one',non_neg_integer(),pos_integer()} | {'rest_for_one',non_neg_integer(),pos_integer()} | {'simple_one_for_one',non_neg_integer(),pos_integer()} | #{'intensity'=>non_neg_integer(), 'period'=>pos_integer(), 'strategy'=>'one_for_all' | 'one_for_one' | 'rest_for_one' | 'simple_one_for_one'},[{_,{atom(),atom(),'undefined' | [any()]},'permanent' | 'temporary' | 'transient','brutal_kill' | 'infinity' | non_neg_integer(),'supervisor' | 'worker','dynamic' | [atom()]} | #{'id':=_, 'start':={atom(),atom(),'undefined' | [any()]}, 'modules'=>'dynamic' | [atom()], 'restart'=>'permanent' | 'temporary' | 'transient', 'shutdown'=>'brutal_kill' | 'infinity' | non_neg_integer(), 'type'=>'supervisor' | 'worker'}]}}, which is the expected return type for the callback of the supervisor behaviour
supervisor_incorrect_return.erl:14:1: The inferred return type of init/1 ({'ok',{{'one_against_one',0,1},[{_,_,_,_,_,_},...]}}) has nothing in common with 'ignore' | {'ok',{{'one_for_all',non_neg_integer(),pos_integer()} | {'one_for_one',non_neg_integer(),pos_integer()} | {'rest_for_one',non_neg_integer(),pos_integer()} | {'simple_one_for_one',non_neg_integer(),pos_integer()} | #{'auto_shutdown'=>'all_significant' | 'any_significant' | 'never', 'intensity'=>non_neg_integer(), 'period'=>pos_integer(), 'strategy'=>'one_for_all' | 'one_for_one' | 'rest_for_one' | 'simple_one_for_one'},[{_,{atom(),atom(),'undefined' | [any()]},'permanent' | 'temporary' | 'transient','brutal_kill' | 'infinity' | non_neg_integer(),'supervisor' | 'worker','dynamic' | [atom()]} | #{'id':=_, 'start':={atom(),atom(),'undefined' | [any()]}, 'modules'=>'dynamic' | [atom()], 'restart'=>'permanent' | 'temporary' | 'transient', 'shutdown'=>'brutal_kill' | 'infinity' | non_neg_integer(), 'significant'=>boolean(), 'type'=>'supervisor' | 'worker'}]}}, which is the expected return type for the callback of the supervisor behaviour
2 changes: 1 addition & 1 deletion lib/erl_docgen/src/docgen_xml_to_chunk.erl
Expand Up @@ -179,7 +179,7 @@ build_dom({endElement, _Uri, LocalName, _QName},
MappedCName =
case CName of
title ->
lists:nth(SectionDepth+1,[h1,h2,h3]);
lists:nth(SectionDepth+1,[h1,h2,h3,h4,h5,h6]);
section when SectionDepth > 0 ->
'div';
CName -> CName
Expand Down
4 changes: 2 additions & 2 deletions lib/sasl/test/release_handler_SUITE.erl
Expand Up @@ -1396,9 +1396,9 @@ upgrade_supervisor(Conf) when is_list(Conf) ->
%% Check that the restart strategy and child spec is updated
{status, _, {module, _}, [_, _, _, _, [_,_,{data,[{"State",State}]}|_]]} =
rpc:call(Node,sys,get_status,[a_sup]),
{state,_,RestartStrategy,{[a],Db},_,_,_,_,_,_,_} = State,
{state,_,RestartStrategy,{[a],Db},_,_,_,_,_,_,_,_} = State,
one_for_all = RestartStrategy, % changed from one_for_one
{child,_,_,_,_,brutal_kill,_,_} = maps:get(a,Db), % changed from timeout 2000
{child,_,_,_,_,_,brutal_kill,_,_} = maps:get(a,Db), % changed from timeout 2000

ok.

Expand Down
107 changes: 96 additions & 11 deletions lib/stdlib/doc/src/supervisor.xml
Expand Up @@ -69,15 +69,20 @@
this list. When the supervisor terminates, it first terminates
its child processes in reversed start order, from right to left.</p>

<section>
<title>Supervisor flags</title>
<marker id="sup_flags"/>
<p>The supervisor properties are defined by the supervisor flags.
The type definition for the supervisor flags is as follows:</p>

<pre>
sup_flags() = #{strategy => strategy(), % optional
intensity => non_neg_integer(), % optional
period => pos_integer()} % optional</pre>
sup_flags() = #{strategy => strategy(), % optional
intensity => non_neg_integer(), % optional
period => pos_integer(), % optional
auto_shutdown => auto_shutdown()} % optional</pre>

<section>
<title>Restart Stratagies</title>
<p>A supervisor can have one of the following <em>restart strategies</em>
specified with the <c>strategy</c> key in the above map:</p>

Expand Down Expand Up @@ -124,7 +129,9 @@ sup_flags() = #{strategy => strategy(), % optional
defined.</p>
</item>
</list>

</section>
<section>
<title>Restart intensity and period</title>
<p>To prevent a supervisor from getting into an infinite loop of
child process terminations and restarts, a <em>maximum restart
intensity</em> is defined using two integer values specified
Expand All @@ -136,17 +143,69 @@ sup_flags() = #{strategy => strategy(), % optional
reason for the supervisor itself in that case will be <c>shutdown</c>.
<c>intensity</c> defaults to <c>1</c> and <c>period</c> defaults to
<c>5</c>.</p>
</section>
<section>
<title>Automatic Shutdown</title>
<marker id="auto_shutdown"/>
garazdawi marked this conversation as resolved.
Show resolved Hide resolved
<p>A supervisor can be configured to automatically shut itself down
garazdawi marked this conversation as resolved.
Show resolved Hide resolved
with exit reason <c>shutdown</c> when
<seeerl marker="#significant_child">significant children</seeerl>
terminate with the <c>auto_shutdown</c> key in the above map:</p>

<list type="bulleted">
<item>
<p><c>never</c> - Automic shutdown is disabled. This is the default
setting.</p>
<p>With <c>auto_shutdown</c> set to <c>never</c>, child specs
with the <c>significant</c> flag set to <c>true</c> are
considered invalid and will be rejected.</p>
</item>
<item>
<p><c>any_significant</c> - The supervisor will shut itself down
when <em>any</em> significant child terminates, that is, when
a <c>transient</c> significant child terminates normally or
when a <c> temporary</c> significant child terminates
normally or abnormally.</p>
</item>
<item>
<p><c>all_significant</c> - The supervisor will shut itself down
when <em>all</em> significant children have terminated, that is,
when the <em>last active</em> significant child terminates.
The same rules as for <c>any_significant</c> apply.</p>
</item>
</list>
garazdawi marked this conversation as resolved.
Show resolved Hide resolved

<p>For more information, see the section
<seeguide marker="system/design_principles:sup_princ#automatic-shutdown">Automatic
Shutdown</seeguide> in Supervisor Behavior in OTP Design Principles.</p>

<warning>
<p>The automatic shutdown feature appeared in OTP 24.0, but
applications using this feature will also compile and
run with older OTP versions.</p>
<p>However, such applications, when compiled with an OTP version
that predates the appearance of the automatic shutdown feature,
will leak processes because the automatic shutdowns they rely
on will not happen.</p>
<p>It is up to implementors to take proper precautions if they
expect that their applications may be compiled with older OTP
versions.</p>
</warning>
</section>
</section>
<section>
<title>Child specification</title>
<marker id="child_spec"/>
<p>The type definition of a child specification is as follows:</p>

<pre>
child_spec() = #{id => child_id(), % mandatory
start => mfargs(), % mandatory
restart => restart(), % optional
shutdown => shutdown(), % optional
type => worker(), % optional
modules => modules()} % optional</pre>
child_spec() = #{id => child_id(), % mandatory
start => mfargs(), % mandatory
restart => restart(), % optional
significant => significant(), % optional
shutdown => shutdown(), % optional
type => worker(), % optional
modules => modules()} % optional</pre>

<p>The old tuple format is kept for backwards compatibility,
see <seetype marker="#child_spec">child_spec()</seetype>,
Expand Down Expand Up @@ -184,6 +243,7 @@ child_spec() = #{id => child_id(), % mandatory
<p>The <c>start</c> key is mandatory.</p>
</item>
<item>
<marker id="restart"/>
<p><c>restart</c> defines when a terminated child process
must be restarted. A <c>permanent</c> child process is
always restarted. A <c>temporary</c> child process is
Expand All @@ -196,6 +256,20 @@ child_spec() = #{id => child_id(), % mandatory
<p>The <c>restart</c> key is optional. If it is not specified,
it defaults to <c>permanent</c>.</p>
</item>
<item>
<marker id="significant_child"/>
<p><c>significant</c> defines if a child is considered significant
for <seeerl marker="#auto_shutdown">automatic self-shutdown</seeerl>
of the supervisor.</p>
<p>Setting this option to <c>true</c> when the
<seeerl marker="#restart">restart type</seeerl> is <c>permanent</c> is
invalid. Also, it is considered invalid to
start children with this option set to <c>true</c> in a supervisor
when the <seeerl marker="#auto_shutdown"><c>auto_shutdown</c></seeerl>
supervisor flag is set to <c>never</c>.</p>
<p>The <c>significant</c> key is optional. If it is not specified,
it defaults to <c>false</c>.</p>
</item>
<item>
<p><c>shutdown</c> defines how a child process must be
terminated. <c>brutal_kill</c> means that the child process
Expand Down Expand Up @@ -265,8 +339,12 @@ child_spec() = #{id => child_id(), % mandatory
</item>
</list>
</section>
</section>

<datatypes>
<datatype>
<name name="auto_shutdown"/>
</datatype>
<datatype>
<name name="child"/>
</datatype>
Expand Down Expand Up @@ -299,6 +377,9 @@ child_spec() = #{id => child_id(), % mandatory
<datatype>
<name name="shutdown"/>
</datatype>
<datatype>
<name name="significant"/>
</datatype>
<datatype>
<name name="startchild_err"/>
</datatype>
Expand Down Expand Up @@ -331,12 +412,17 @@ child_spec() = #{id => child_id(), % mandatory
<funcs>
<func>
<name name="check_childspecs" arity="1" since=""/>
<name name="check_childspecs" arity="2" since="OTP 24.0"/>
<fsummary>Check if children specifications are syntactically correct.
</fsummary>
<desc>
<p>Takes a list of child specification as argument
and returns <c>ok</c> if all of them are syntactically
correct, otherwise <c>{error,<anno>Error</anno>}</c>.</p>
<p>If the optional <c><anno>AutoShutdown</anno></c> argument
is given and not <c>undefined</c>, also checks if the child
specifications are allowed for the given
<seeerl marker="#auto_shutdown">auto_shutdown</seeerl> option.</p>
</desc>
</func>

Expand Down Expand Up @@ -731,4 +817,3 @@ child_spec() = #{id => child_id(), % mandatory
<seeerl marker="sys"><c>sys(3)</c></seeerl></p>
</section>
</erlref>