summaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/doc/design_principles/events.xml3
-rw-r--r--system/doc/design_principles/release_handling.xml4
-rw-r--r--system/doc/design_principles/spec_proc.xml2
-rw-r--r--system/doc/design_principles/statem.xml4
-rw-r--r--system/doc/design_principles/sup_princ.xml6
-rw-r--r--system/doc/efficiency_guide/advanced.xml6
-rw-r--r--system/doc/efficiency_guide/bench.erl4
-rw-r--r--system/doc/efficiency_guide/commoncaveats.xmlsrc19
-rw-r--r--system/doc/efficiency_guide/functions.xml40
-rw-r--r--system/doc/efficiency_guide/retired_myths.xml4
-rw-r--r--system/doc/efficiency_guide/tablesDatabases.xml4
-rw-r--r--system/doc/embedded/intro.xml4
-rw-r--r--system/doc/general_info/DEPRECATIONS24
-rw-r--r--system/doc/general_info/deprecations_23.inc4
-rw-r--r--system/doc/general_info/upcoming_incompatibilities.xml15
-rw-r--r--system/doc/programming_examples/bit_syntax.xml8
-rw-r--r--system/doc/reference_manual/data_types.xml16
-rw-r--r--system/doc/reference_manual/distributed.xml17
-rw-r--r--system/doc/reference_manual/expressions.xml161
-rw-r--r--system/doc/reference_manual/features.xml217
-rw-r--r--system/doc/reference_manual/macros.xml37
-rw-r--r--system/doc/reference_manual/modules.xml56
-rw-r--r--system/doc/reference_manual/opaques.xml141
-rw-r--r--system/doc/reference_manual/part.xml4
-rw-r--r--system/doc/reference_manual/processes.xml11
-rw-r--r--system/doc/reference_manual/typespec.xml16
-rw-r--r--system/doc/reference_manual/xmlfiles.mk6
-rw-r--r--system/doc/system_principles/system_principles.xml4
-rw-r--r--system/doc/top/src/erl_html_tools.erl2
-rw-r--r--system/doc/tutorial/c_port.xmlsrc2
-rw-r--r--system/doc/tutorial/complex6.erl1
-rw-r--r--system/doc/tutorial/debugging.xml348
-rw-r--r--system/doc/tutorial/nif.xmlsrc9
-rw-r--r--system/doc/tutorial/part.xml3
-rw-r--r--system/doc/tutorial/xmlfiles.mk6
35 files changed, 1098 insertions, 110 deletions
diff --git a/system/doc/design_principles/events.xml b/system/doc/design_principles/events.xml
index acd051d411..4d7b34bc70 100644
--- a/system/doc/design_principles/events.xml
+++ b/system/doc/design_principles/events.xml
@@ -227,7 +227,8 @@ ok</pre>
<c>handle_info(Info, State)</c>
must be implemented to handle them. Examples of other
messages are exit messages, if the <c>gen_event</c> is linked to
- other processes (than the supervisor) and trapping exit signals.</p>
+ other processes (than the supervisor, for example via
+ <c>add_sup_handler</c>) and trapping exit signals.</p>
<code type="none">
handle_info({'EXIT', Pid, Reason}, State) ->
..code to handle exits here..
diff --git a/system/doc/design_principles/release_handling.xml b/system/doc/design_principles/release_handling.xml
index d23e9732fc..167d92d52f 100644
--- a/system/doc/design_principles/release_handling.xml
+++ b/system/doc/design_principles/release_handling.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2020</year>
+ <year>2003</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -311,7 +311,7 @@
the following instruction is used:</p>
<code type="none">
{apply, {M, F, A}}</code>
- <p>The release handler evalutes <c>apply(M, F, A)</c>.</p>
+ <p>The release handler evaluates <c>apply(M, F, A)</c>.</p>
</section>
<section>
diff --git a/system/doc/design_principles/spec_proc.xml b/system/doc/design_principles/spec_proc.xml
index 0610a15a8a..51a1228183 100644
--- a/system/doc/design_principles/spec_proc.xml
+++ b/system/doc/design_principles/spec_proc.xml
@@ -274,7 +274,7 @@ init(Parent) ->
<section>
<marker id="debug"></marker>
<title>Debugging</title>
- <p>To support the debug facilites in <c>sys</c>, a
+ <p>To support the debug facilities in <c>sys</c>, a
<em>debug structure</em> is needed. The <c>Deb</c> term is
initialized using <c>sys:debug_options/1</c>:</p>
<code type="none">
diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml
index 2d6ea27635..c53d569c99 100644
--- a/system/doc/design_principles/statem.xml
+++ b/system/doc/design_principles/statem.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2016</year><year>2020</year>
+ <year>2016</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1947,7 +1947,7 @@ do_unlock() ->
<p>
Say you have a state machine specification
that uses state enter actions.
- Allthough you can code this using inserted events
+ Although you can code this using inserted events
(described in the next section), especially if just
one or a few states has got state enter actions,
this is a perfect use case for the built in
diff --git a/system/doc/design_principles/sup_princ.xml b/system/doc/design_principles/sup_princ.xml
index 4d1b593c92..c9aa52669b 100644
--- a/system/doc/design_principles/sup_princ.xml
+++ b/system/doc/design_principles/sup_princ.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2021</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -69,7 +69,7 @@ init(_Args) ->
restart => permanent,
shutdown => brutal_kill,
type => worker,
- modules => [cg3]}],
+ modules => [ch3]}],
{ok, {SupFlags, ChildSpecs}}.</code>
<p>The <c>SupFlags</c> variable in the return value
from <c>init/1</c> represents
@@ -374,7 +374,7 @@ child_spec() = #{id => child_id(), % mandatory
<p>Note that this identifier occasionally has been called
"name". As far as possible, the terms "identifier" or "id"
are now used but in order to keep backwards compatibility,
- some occurences of "name" can still be found, for example
+ some occurrences of "name" can still be found, for example
in error messages.</p>
</item>
<item>
diff --git a/system/doc/efficiency_guide/advanced.xml b/system/doc/efficiency_guide/advanced.xml
index c545d22a8a..25899f6821 100644
--- a/system/doc/efficiency_guide/advanced.xml
+++ b/system/doc/efficiency_guide/advanced.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2021</year>
+ <year>2001</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -39,7 +39,9 @@
<p>The unit of measurement is memory words. There exists both a
32-bit and a 64-bit implementation. A word is therefore 4 bytes or
- 8 bytes, respectively.</p>
+ 8 bytes, respectively. The value for a running system can be
+ determined by calling <seeerl marker="erts:erlang#system_info_wordsize">
+ <c>erlang:system_info(wordsize)</c></seeerl>.</p>
<table>
<row>
<cell><em>Data Type</em></cell>
diff --git a/system/doc/efficiency_guide/bench.erl b/system/doc/efficiency_guide/bench.erl
index a1be24b051..a1e9a71084 100644
--- a/system/doc/efficiency_guide/bench.erl
+++ b/system/doc/efficiency_guide/bench.erl
@@ -424,7 +424,7 @@ create_html_table(File, {Bm, Res}) ->
create_html_row(File, Name, ResultDict)
end, Order),
- %% Tabel end-tags
+ %% Table end-tags
io:put_chars(File, "</table></td></tr></table>\n"),
%% Create link to benchmark source code
@@ -435,7 +435,7 @@ create_html_table(File, {Bm, Res}) ->
%% create_html_row(File, Name, Dict) -> _
%% File = file() - html file to write data to.
%% Name = atom() - Name of benchmark test
-%% Dict = dict() - Dictonary where the relative time measures for
+%% Dict = dict() - Dictionary where the relative time measures for
%% the test can be found.
%%
%% Creates an actual html table-row.
diff --git a/system/doc/efficiency_guide/commoncaveats.xmlsrc b/system/doc/efficiency_guide/commoncaveats.xmlsrc
index 47ce3a014f..6ea8599e94 100644
--- a/system/doc/efficiency_guide/commoncaveats.xmlsrc
+++ b/system/doc/efficiency_guide/commoncaveats.xmlsrc
@@ -39,11 +39,16 @@
marker="erts:erlang#send_after/3">erlang:send_after/3</seemfa>
and
<seemfa marker="erts:erlang#start_timer/3">erlang:start_timer/3</seemfa>,
- is much more efficient than using the timers provided by the
- <seeerl marker="stdlib:timer">timer</seeerl> module in STDLIB.
- The <c>timer</c> module uses a separate process to manage the timers.
- That process can easily become overloaded if many processes
- create and cancel timers frequently.</p>
+ is more efficient than using the timers provided by the
+ <seeerl marker="stdlib:timer">timer</seeerl> module in STDLIB.</p>
+ <p>The <c>timer</c> module uses a separate process to manage the timers.
+ Before OTP 25, this management overhead was substantial and increasing
+ with the number of timers, especially when they were short-lived, so the
+ timer server process could easily become overloaded and unresponsive.
+ In OTP 25, the timer module was improved by removing most of the management
+ overhead and the resulting performance penalty. Still, the timer server
+ remains a single process, and it may at some point become a bottleneck
+ of an application.</p>
<p>The functions in the <c>timer</c> module that do not manage timers
(such as <c>timer:tc/3</c> or <c>timer:sleep/1</c>), do not call the
@@ -85,7 +90,7 @@
<p>a list with 10000 elements (or about 20000 heap words) will be
copied to the newly created process.</p>
- <p>An unncessary copy of 10000 element list can be bad enough, but it
+ <p>An unnecessary copy of 10000 element list can be bad enough, but it
can get even worse if the <c>state</c> record contains <em>shared subterms</em>.
Here is a simple example of a term with a shared subterm:</p>
@@ -192,7 +197,7 @@ multiple_setelement(T0) ->
<p>The two following <c>setelement/3</c> calls modify
the tuple in place.</p>
- <p>For the optimization to be applied, <em>all</em> the followings conditions
+ <p>For the optimization to be applied, <em>all</em> the following conditions
must be true:</p>
<list type="bulleted">
diff --git a/system/doc/efficiency_guide/functions.xml b/system/doc/efficiency_guide/functions.xml
index 0a8ee7eb34..f3d6b59e49 100644
--- a/system/doc/efficiency_guide/functions.xml
+++ b/system/doc/efficiency_guide/functions.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2017</year>
+ <year>2001</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -158,22 +158,23 @@ explicit_map_pairs(Map, Xs0, Ys0) ->
<section>
<title>Function Calls</title>
- <p>This is an intentionally rough guide to the relative costs of
- different calls. It is based on benchmark figures run on
- Solaris/Sparc:</p>
+ <p>This is a rough hierarchy of the performance of the
+ different types of function calls:</p>
<list type="bulleted">
<item>Calls to local or external functions (<c>foo()</c>, <c>m:foo()</c>)
are the fastest calls.</item>
<item>Calling or applying a fun (<c>Fun()</c>, <c>apply(Fun, [])</c>)
- is about <em>three times</em> as expensive as calling a local
- function.</item>
+ is just a little slower than external calls.</item>
<item>Applying an exported function (<c>Mod:Name()</c>,
- <c>apply(Mod, Name, [])</c>) is about twice as expensive as calling
- a fun or about <em>six times</em> as expensive as calling a local
- function.</item>
+ <c>apply(Mod, Name, [])</c>) where the number of arguments is known
+ at compile time is next.</item>
+
+ <item>Applying an exported function (<c>apply(Mod, Name, Args)</c>)
+ where the number of arguments is not known at compile time is the
+ least efficient.</item>
</list>
<section>
@@ -187,25 +188,8 @@ explicit_map_pairs(Map, Xs0, Ys0) ->
in a hash table. It is therefore always slower than a
direct call or a fun call.</p>
- <p>It no longer matters (from a performance point of view)
- whether you write:</p>
-
- <code type="erl">
-Module:Function(Arg1, Arg2)</code>
-
- <p>or:</p>
-
- <code type="erl">
-apply(Module, Function, [Arg1,Arg2])</code>
-
- <p>The compiler internally rewrites the latter code into the
- former.</p>
-
- <p>The following code is slightly slower because the shape of the
- list of arguments is unknown at compile time.</p>
-
- <code type="erl">
-apply(Module, Function, Arguments)</code>
+ <p>Caching callback functions into funs may be more efficient
+ in the long run than apply calls for frequently-used callbacks.</p>
</section>
</section>
diff --git a/system/doc/efficiency_guide/retired_myths.xml b/system/doc/efficiency_guide/retired_myths.xml
index a763770e5a..593e8f5492 100644
--- a/system/doc/efficiency_guide/retired_myths.xml
+++ b/system/doc/efficiency_guide/retired_myths.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2016</year>
- <year>2020</year>
+ <year>2021</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -31,7 +31,7 @@
<file>retired_myths.xml</file>
</header>
- <p>We belive that the truth finally has caught with the following,
+ <p>We believe that the truth finally has caught with the following,
retired myths.</p>
<section>
diff --git a/system/doc/efficiency_guide/tablesDatabases.xml b/system/doc/efficiency_guide/tablesDatabases.xml
index 3f77151e55..ba0d5e2e40 100644
--- a/system/doc/efficiency_guide/tablesDatabases.xml
+++ b/system/doc/efficiency_guide/tablesDatabases.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2016</year>
+ <year>2001</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -137,7 +137,7 @@ print_person(PersonId) ->
io:format("No person with ID = ~p~n", [PersonID])
end.
-%%% Internal functionss
+%%% Internal functions
print_name(PersonID) ->
[Person] = ets:lookup(person, PersonId),
io:format("No person ~p~n", [Person#person.name]).
diff --git a/system/doc/embedded/intro.xml b/system/doc/embedded/intro.xml
index 2b9d35d24c..cec3212481 100644
--- a/system/doc/embedded/intro.xml
+++ b/system/doc/embedded/intro.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1997</year>
- <year>2016</year>
+ <year>2021</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -37,7 +37,7 @@
<p>This manual is a complement to the other manuals and describes how
to install, run and maintain Erlang on an embedded system.
</p>
- <p>For more informaton about how to install and start Erlang read
+ <p>For more information about how to install and start Erlang read
XXXXXXXX.
</p>
diff --git a/system/doc/general_info/DEPRECATIONS b/system/doc/general_info/DEPRECATIONS
index ab304db2a8..2f83cbb9d3 100644
--- a/system/doc/general_info/DEPRECATIONS
+++ b/system/doc/general_info/DEPRECATIONS
@@ -18,13 +18,25 @@
#
#
+# Added in OTP 25.
+#
+slave:_/_ since=25 remove=27
+ct_slave:_/_ since=25 remove=27
+httpd_util:encode_hex/1 since=25 remove=26
+httpd_util:decode_hex/1 since=25 remove=26
+
+crypto:crypto_dyn_iv_init/3 since=25 remove=27
+crypto:crypto_dyn_iv_update/3 since=25 remove=27
+erts_alloc_config:_/_ since=25 remove=26
+
+#
# Added in OTP 24.
#
-public_key:ssh_hostkey_fingerprint/1 since=24 remove=26
-public_key:ssh_hostkey_fingerprint/2 since=24 remove=26
-public_key:ssh_decode/2 since=24 remove=26
-public_key:ssh_encode/2 since=24 remove=26
+public_key:ssh_hostkey_fingerprint/1 since=24 remove=25
+public_key:ssh_hostkey_fingerprint/2 since=24 remove=25
+public_key:ssh_decode/2 since=24 remove=25
+public_key:ssh_encode/2 since=24 remove=25
ftp:start_service/1 since=24 remove=26
ftp:stop_service/1 since=24 remove=26
httpd_util:flatlength/1 since=24 remove=26
@@ -57,8 +69,8 @@ ssl:cipher_suites/0 since=21 remove=24
http_uri:parse/1 since=23 remove=25
http_uri:parse/2 since=23 remove=25
-http_uri:encode/1 since=23 remove=25
-http_uri:decode/1 since=23 remove=25
+http_uri:encode/1 since=23 remove=26
+http_uri:decode/1 since=23 remove=26
http_uri:scheme_defaults/0 since=23 remove=25
httpd:parse_query/1 since=23
pg2:_/_ since=23 remove=24
diff --git a/system/doc/general_info/deprecations_23.inc b/system/doc/general_info/deprecations_23.inc
index ef1c6ff12f..1eb8f3dd5e 100644
--- a/system/doc/general_info/deprecations_23.inc
+++ b/system/doc/general_info/deprecations_23.inc
@@ -18,12 +18,12 @@
<section>
<title>ssh</title>
<p>The public key algorithm <c>'ssh-rsa</c> is regarded as insecure due
- to its usage of SHA1, and is therfore deprecated.
+ to its usage of SHA1, and is therefore deprecated.
It will not be available by default from OTP-24.
</p>
<p>The public key algorithm <c>'ssh-dss</c> is regarded as insecure due
- to its usage of SHA1 and its short key length, and is therfore deprecated.
+ to its usage of SHA1 and its short key length, and is therefore deprecated.
It is not available by default from OTP-23.
</p>
</section>
diff --git a/system/doc/general_info/upcoming_incompatibilities.xml b/system/doc/general_info/upcoming_incompatibilities.xml
index 69a0f6de16..59003d2243 100644
--- a/system/doc/general_info/upcoming_incompatibilities.xml
+++ b/system/doc/general_info/upcoming_incompatibilities.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2021</year>
+ <year>2021</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -132,5 +132,18 @@
</list>
</section>
+ <section>
+ <title>The default timewarp mode will change to multi-time warp mode</title>
+ <p>
+ The default <seeguide marker="erts:time_correction#Time_Warp_Modes">
+ Time Warp Mode</seeguide> will be changed from
+ <seeguide marker="erts:time_correction#No_Time_Warp_Mode">
+ no time warp mode</seeguide> to <seeguide marker="erts:time_correction#Multi_Time_Warp_Mode">
+ multi-time warp mode</seeguide>. See <seeguide marker="erts:time_correction">
+ Time and Time Correction in Erlang</seeguide> for details on how this will
+ effect your system.
+ </p>
+ </section>
+
</section>
</chapter>
diff --git a/system/doc/programming_examples/bit_syntax.xml b/system/doc/programming_examples/bit_syntax.xml
index cc89f3a469..08587ccff3 100644
--- a/system/doc/programming_examples/bit_syntax.xml
+++ b/system/doc/programming_examples/bit_syntax.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2020</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -206,7 +206,7 @@ X:4/little-signed-integer-unit:8</code>
matching, this default value is only valid for the last
element. All other binary elements in matching must have a size
specification.</p>
- <p>The default unit depends on the the type. For <c>integer</c>,
+ <p>The default unit depends on the type. For <c>integer</c>,
<c>float</c>, and <c>bitstring</c> it is 1. For binary it is 8.</p>
<p>The default signedness is <c>unsigned</c>.</p>
<p>The default endianness is <c>big</c>.</p>
@@ -311,8 +311,8 @@ foo(N, Bin) ->
<section>
<title>Binding and Using a Size Variable</title>
<p>There is one exception to the rule that a variable that is
- as size must be previously bound. It is possible to match and
- bind a variable, and use it as a size within the the same
+ used as size must be previously bound. It is possible to match and
+ bind a variable, and use it as a size within the same
binary pattern. For example:</p>
<code type="none"><![CDATA[
diff --git a/system/doc/reference_manual/data_types.xml b/system/doc/reference_manual/data_types.xml
index 15983ebbf9..1a4bdc5680 100644
--- a/system/doc/reference_manual/data_types.xml
+++ b/system/doc/reference_manual/data_types.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,7 +30,15 @@
<file>data_types.xml</file>
</header>
<p>Erlang provides a number of data types, which are listed in
- this section.</p>
+ this section.</p>
+
+ <marker id="no_user_types" />
+ <p>Note that Erlang has no user defined types, only composite
+ types (data structures) made of Erlang terms. This means that any
+ function testing for a composite type, typically named
+ <c>is_type/1</c>, might return <c>true</c> for a term
+ that coincides with the chosen representation. The corresponding
+ functions for built in types do not suffer from this.</p>
<section>
<title>Terms</title>
@@ -85,8 +93,8 @@
<p>When working with floats you may not see what you expect when printing or
doing arithmetic operations. This is because floats
are represented by a fixed number of bits in a base-2 system while
- printed floats are represented with a base-10 system. Here are
- examples of this phenomenon:
+ printed floats are represented with a base-10 system. Erlang
+ uses 64-bit floats. Here are examples of this phenomenon:
</p>
<pre>
> <input>0.1+0.2.</input>
diff --git a/system/doc/reference_manual/distributed.xml b/system/doc/reference_manual/distributed.xml
index cc4746825b..f8fb159be3 100644
--- a/system/doc/reference_manual/distributed.xml
+++ b/system/doc/reference_manual/distributed.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -155,7 +155,7 @@ dilbert@uab</pre>
name from the first node it connects to. In addition these
distribution settings will be set:
</p>
- <pre><seeapp marker="kernel:kernel_app#dist_listen">-dist_listen false</seeapp> <seecom marker="erts:erl#hidden">-hidden</seecom> <seeapp marker="kernel:kernel_app#dist_auto_connect">-dist_auto_connect never</seeapp></pre>
+ <pre><seecom marker="erts:erl#dist_listen">-dist_listen false</seecom> <seecom marker="erts:erl#hidden">-hidden</seecom> <seeapp marker="kernel:kernel_app#dist_auto_connect">-kernel dist_auto_connect never</seeapp></pre>
<p>
As <c>-dist_auto_connect</c> is set to <c>never</c>,
<seemfa marker="kernel:net_kernel#connect_node/1"><c>net_kernel:connect_node/1</c></seemfa>
@@ -212,7 +212,7 @@ dilbert@uab</pre>
in the following text is not very unpredictable.
A better one can be generated using primitives
in the <c>crypto</c> module, though this still does not make
- the inital handshake cryptographically secure.
+ the initial handshake cryptographically secure.
And inter-node communication is still in clear text.
</p>
</note>
@@ -230,9 +230,14 @@ dilbert@uab</pre>
<p>At start-up, a node has a random atom assigned as its default
magic cookie and the cookie of other nodes is assumed to be
<c>nocookie</c>. The first action of the Erlang network
- authentication server (<c>auth</c>) is then to read a file named
- <c>$HOME/.erlang.cookie</c>. If the file does not exist, it is
- created. The UNIX permissions mode of the file is set to octal
+ authentication server (<c>auth</c>) is then to search for a file named
+ <c>.erlang.cookie</c> in the <seeerl marker="erts:init#home">
+ user&apos;s home directory</seeerl> and then in
+ <seeerl marker="stdlib:filename#user_config">
+ <c>filename:basedir(user_config, "erlang")</c></seeerl>.
+ If none of the files exist, a <c>.erlang.cooke</c> file is created
+ in the user&apos;s home directory.
+ The UNIX permissions mode of the file is set to octal
400 (read-only by user) and its content is a random string. An
atom <c>Cookie</c> is created from the contents of the file and
the cookie of the local node is set to this using
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index 8dbc620bd0..af143ad4d5 100644
--- a/system/doc/reference_manual/expressions.xml
+++ b/system/doc/reference_manual/expressions.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -395,6 +395,139 @@ is_valid_signal(Signal) ->
</section>
<section>
+ <marker id="maybe"></marker>
+ <title>Maybe</title>
+ <note><p><c>maybe</c> is an experimental new <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>
+ introduced in OTP 25. By default, it is disabled. To enable
+ <c>maybe</c>, either use the <c>-feature(maybe_expr,enable)</c>
+ directive (from within source code), or the compiler option
+ <c>{feature,maybe_expr,enable}</c>. The feature must also be enabled
+ in runtime using the <c>-enable-feature</c> option to <c>erl</c>.</p>
+ </note>
+
+ <code type="erl"><![CDATA[
+maybe
+ Expr1,
+ ...,
+ ExprN
+end]]></code>
+
+ <p>The expressions in a <c>maybe</c> block are evaluated sequentially. If all
+ expressions are evaluated successfully, the return value of the <c>maybe</c>
+ block is <c>ExprN</c>. However, execution can be short-circuited by a
+ conditional match expression:</p>
+
+ <code type="erl"><![CDATA[
+Expr1 ?= Expr2]]></code>
+
+ <p><c>?=</c> is called the conditional match operator. It is only
+ allowed to be used at the top-level of a <c>maybe</c> block. It
+ matches the pattern <c>Expr1</c> against <c>Expr2</c>. If the
+ matching succeeds, any unbound variable in the pattern becomes
+ bound. If the expression is the last expression in the
+ <c>maybe</c> block, it also returns the value of <c>Expr2</c>. If the
+ matching is unsuccessful, the rest of the expressions in the <c>maybe</c>
+ block are skipped and the return value of the <c>maybe</c>
+ block is <c>Expr2</c>.</p>
+
+ <p>None of the variables bound in a <c>maybe</c> block must be
+ used in the code that follows the block.</p>
+
+ <p>Here is an example:</p>
+
+ <code type="erl"><![CDATA[
+maybe
+ {ok, A} ?= a(),
+ true = A >= 0,
+ {ok, B} ?= b(),
+ A + B
+end]]></code>
+
+ <p>Let us first assume that <c>a()</c> returns <c>{ok,42}</c> and
+ <c>b()</c> returns <c>{ok,58}</c>. With those return values, all
+ of the match operators will succeed, and the return value of the
+ <c>maybe</c> block is <c>A + B</c>, which is equal to <c>42 +
+ 58 = 100</c>.</p>
+
+ <p>Now let us assume that <c>a()</c> returns <c>error</c>. The
+ conditional match operator in <c>{ok, A} ?= a()</c> fails to
+ match, and the return value of the <c>maybe</c> block is the
+ value of the expression that failed to match, namely <c>error</c>.
+ Similarly, if <c>b()</c> returns <c>wrong</c>, the return value of
+ the <c>maybe</c> block is <c>wrong</c>.</p>
+
+ <p>Finally, let us assume that <c>a()</c> returns
+ <c>-1</c>. Because <c>true = A >= 0</c> uses the match operator
+ `=`, a <c>{badmatch,false}</c> run-time error occurs when the
+ expression fails to match the pattern.</p>
+
+ <p>The example can be written in a less succient way using nested
+ case expressions:</p>
+
+ <code type="erl"><![CDATA[
+case a() of
+ {ok, A} ->
+ true = A >= 0,
+ case b() of
+ {ok, B} ->
+ A + B;
+ Other1 ->
+ Other1
+ end;
+ Other2 ->
+ Other2
+end]]></code>
+
+ <p>The <c>maybe</c> block can be augmented with <c>else</c> clauses:</p>
+
+ <code type="erl"><![CDATA[
+maybe
+ Expr1,
+ ...,
+ ExprN
+else
+ Pattern1 [when GuardSeq1] ->
+ Body1;
+ ...;
+ PatternN [when GuardSeqN] ->
+ BodyN
+end]]></code>
+
+ <p>If a conditional match operator fails, the failed expression is
+ matched against the patterns in all clauses between the
+ <c>else</c> and <c>end</c> keywords. If a match succeeds and the
+ optional guard sequence <c>GuardSeq</c> is true, the corresponding
+ <c>Body</c> is evaluated. The value returned from the body is the
+ return value of the <c>maybe</c> block.</p>
+
+ <p>If there is no matching pattern with a true guard sequence,
+ an <c>else_clause</c> run-time error occurs.</p>
+
+ <p>None of the variables bound in a <c>maybe</c> block must be used in
+ the <c>else</c> clauses. None of the variables bound in the <c>else</c> clauses
+ must be used in the code that follows the <c>maybe</c> block.</p>
+
+ <p>Here is the previous example augmented with a <c>else</c> clauses:</p>
+
+ <code type="erl"><![CDATA[
+maybe
+ {ok, A} ?= a(),
+ true = A >= 0,
+ {ok, B} ?= b(),
+ A + B
+else
+ error -> error;
+ wrong -> error
+end]]></code>
+
+ <p>The <c>else</c> clauses translate the failing value from
+ the conditional match operators to the value <c>error</c>. If the
+ failing value is not one of the recognized values, a
+ <c>else_clause</c> run-time error occurs.</p>
+ </section>
+
+ <section>
<marker id="send"></marker>
<title>Send</title>
<pre>
@@ -824,7 +957,7 @@ Expr1 -- Expr2</pre>
<p>The list concatenation operator <c>++</c> appends its second
argument to its first and returns the resulting list.</p>
<p>The list subtraction operator <c>--</c> produces a list that
- is a copy of the first argument. The procedure is a follows:
+ is a copy of the first argument. The procedure is as follows:
for each element in the second argument, the first
occurrence of this element (if any) is removed.</p>
<p><em>Example:</em></p>
@@ -1014,7 +1147,7 @@ M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code>
<p>
Here keys <c>K1 .. Kn</c> are any expressions with
literals or bound variables. If all key expressions
- evalute successfully and all keys exist in map
+ evaluate successfully and all keys exist in map
<c>M</c>, all variables in <c>V1 .. Vn</c> is
matched to the associated values of their respective
keys.
@@ -1575,7 +1708,11 @@ end</pre>
<c>BitStringExpr</c> must be an expression, which evaluates to a
bitstring.</item>
<item>A <em>filter</em> is an expression, which evaluates to
- <c>true</c> or <c>false</c>.</item>
+ <c>true</c> or <c>false</c>, or a
+ <seeguide marker="#guard_expressions">guard expression</seeguide>.
+ If the filter is not a guard expression and evaluates
+ to a non-Boolean value <c>Val</c>, an exception
+ <c>{bad_filter, Val}</c> is triggered at runtime.</item>
</list>
<p>The variables in the generator patterns shadow previously bound variables,
including variables bound in a previous generator pattern.</p>
@@ -1612,7 +1749,7 @@ end</pre>
the following syntax:</p>
<pre>
&lt;&lt; BitStringExpr || Qualifier1,...,QualifierN &gt;&gt;</pre>
- <p><c>BitStringExpr</c> is an expression that evalutes to a bit
+ <p><c>BitStringExpr</c> is an expression that evaluates to a bit
string. If <c>BitStringExpr</c> is a function call, it must be
enclosed in parentheses. Each <c>Qualifier</c> is either a
generator, a bit string generator or a filter.</p>
@@ -1626,8 +1763,12 @@ end</pre>
&nbsp;&nbsp;<c><![CDATA[BitstringPattern <= BitStringExpr]]></c>. <br></br>
<c>BitStringExpr</c> must be an expression that evaluates to a
bitstring.</item>
- <item>A <em>filter</em> is an expression that evaluates to
- <c>true</c> or <c>false</c>.</item>
+ <item>A <em>filter</em> is an expression, which evaluates to
+ <c>true</c> or <c>false</c>, or a
+ <seeguide marker="#guard_expressions">guard expression</seeguide>.
+ If the filter is not a guard expression and evaluates
+ to a non-Boolean value <c>Val</c>, an exception
+ <c>{bad_filter, Val}</c> is triggered at runtime.</item>
</list>
<p>The variables in the generator patterns shadow previously bound variables,
including variables bound in a previous generator pattern.</p>
@@ -1675,7 +1816,7 @@ end</pre>
<item>Expressions that construct atoms, integer, floats, lists,
tuples, records, binaries, and maps</item>
<item>Expressions that update a map</item>
- <item>The record epxressions <c>Expr#Name.Field</c> and <c>#Name.Field</c></item>
+ <item>The record expressions <c>Expr#Name.Field</c> and <c>#Name.Field</c></item>
<item>Calls to the BIFs specified in tables <em>Type Test BIFs</em> and
<em>Other BIFs Allowed in Guard Expressions</em></item>
<item>Term comparisons</item>
@@ -1854,6 +1995,10 @@ end</pre>
<cell align="left" valign="middle">Right associative</cell>
</row>
<row>
+ <cell align="left" valign="middle">?=</cell>
+ <cell align="left" valign="middle">&nbsp;</cell>
+ </row>
+ <row>
<cell align="left" valign="middle">catch</cell>
<cell align="left" valign="middle">&nbsp;</cell>
</row>
diff --git a/system/doc/reference_manual/features.xml b/system/doc/reference_manual/features.xml
new file mode 100644
index 0000000000..882cdd2582
--- /dev/null
+++ b/system/doc/reference_manual/features.xml
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2022</year><year>2022</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Features</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>features.xml</file>
+ </header>
+ <p>
+ <marker id="features"/>
+ Introduced in OTP 25, Erlang has the concept of selectable features.
+ A feature can change, add or remove behaviour of the language and/or
+ runtime system. Examples can include
+ </p>
+ <list>
+ <item>Adding new syntactical constructs to the language</item>
+ <item>Change the semantics of an existing construct</item>
+ <item>Change the behaviour of some runtime aspect</item>
+ </list>
+ <p>
+ A feature will start out with a status of experimental part of OTP,
+ making it possible to try out for users and give feedback. The
+ possibility to try out features is enabled by options to the
+ compiler, directives in a module and options to the runtime system.
+ Even when a feature is not experimental it will still be possible to
+ enable or disable it. This makes it possible to adapt a code base
+ at a suitable pace instead of being forced when changing to a new
+ release.
+ </p>
+ <p>
+ The status of a feature will eventually end up as being either a
+ permanent part of OTP or rejected, being removed and no longer
+ selectable.
+ </p>
+
+ <section>
+ <title>Life cycle of features</title>
+ <p>A feature is in one of four possible states:</p>
+ <taglist>
+ <tag>Experimental</tag>
+ <item>The initial state, is meant for trying out and collecting
+ feedback. The feature can be enabled but is disabled by
+ default.</item>
+ <tag>Approved</tag>
+ <item>The feature has been finalised and is now part of OTP. By
+ default it is enabled, but can be disabled.</item>
+ <tag>Permanent</tag>
+ <item>The feature is now a permanent part of OTP. It can no
+ longer be disabled.</item>
+ <tag>Rejected</tag>
+ <item>The feature never reached the approved state and will not
+ be part of OTP. It cannot be enabled.</item>
+ </taglist>
+ <p>
+ After leaving the experimental state, a feature can enter any of
+ the other three states, and if the next state is approved, the
+ feature will eventually end up in the permanent state. A feature
+ can change state only in connection with a release.
+ </p>
+ <p>
+ A feature may be in the approved state for several releases.
+ </p>
+ <table>
+ <row>
+ <cell>State</cell>
+ <cell>Default</cell>
+ <cell>Configurable</cell>
+ <cell>Available</cell>
+ </row>
+ <row>
+ <cell>Experimental</cell>
+ <cell>disabled</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ </row>
+ <row>
+ <cell>Approved</cell>
+ <cell>enabled</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ </row>
+ <row>
+ <cell>Permanent</cell>
+ <cell>enabled</cell>
+ <cell>no</cell>
+ <cell>yes</cell>
+ </row>
+ <row>
+ <cell>Rejected</cell>
+ <cell>disabled</cell>
+ <cell>no</cell>
+ <cell>no</cell>
+ </row>
+ <tcaption>Feature States</tcaption>
+ </table>
+ <list>
+ <item>Being configurable means the possibility to enable or
+ disable the feature by means of compiler options and directives
+ in the file being compiled.</item>
+ <item>Being available can be seen using the
+ <c>FEATURE_AVAILABLE</c> macro.</item>
+ </list>
+ </section>
+
+ <section>
+ <title>Enabling and Disabling Features</title>
+ <p>To use a feature that is in the experimental state, it has to
+ be enabled during compilation. This can be done in a number of
+ different ways:
+ </p>
+ <taglist>
+ <tag>Options to <c>erlc</c></tag>
+ <item>Options <seecom
+ marker="erts:erlc#enable-feature"><c>-enable-feature</c></seecom>
+ and <seecom
+ marker="erts:erlc#disable-feature"><c>-disable-feature</c></seecom>
+ can be used to enable or disable individal features.</item>
+ <tag>Compiler options</tag>
+ <item>The compiler option <seeerl
+ marker="compiler:compile#feature-option"><c>{feature,
+ &lt;feature&gt;, enable|disable}</c></seeerl> can be used either
+ as a <c>+&lt;term&gt;</c> option to <c>erlc</c> or in the options
+ argument to functions in the <c>compile</c> module.</item>
+ <tag>The feature directive</tag>
+ <item>Inside a prefix of a module, one can use a <seeguide
+ marker="macros#feature-directive"><c>-feature(&lt;feature&gt;,
+ enable|disable)</c></seeguide> directive. This is the preferred
+ method of enabling and disabling features.</item>
+ </taglist>
+ <p>
+ Note that to load a module compiled with features enabled, the
+ corresponding features must be enabled in the runtime. This
+ is done using options <seecom
+ marker="erts:erl#enable-feature"><c>-enable-feature</c></seecom>
+ and <seecom
+ marker="erts:erl#disable-feature"><c>-disable-feature</c></seecom>
+ to <c>erl</c>. This is to allow the possibility to prevent
+ the use of experimental features in, e.g., production. This
+ will catch experimental features used in both own and third
+ party components. An active choice to use experimental
+ features must be done.
+ </p>
+ </section>
+
+ <section>
+ <title>Preprocessor Additions</title>
+ <p>
+ To allow for conditional compilation during transitioning of a
+ code base and/or trying out experimental features <seeguide
+ marker="system/reference_manual:macros#predefined-macros">feature</seeguide>
+ <c>predefined macros</c> <c>?FEATURE_AVAILABLE(Feature)</c> and
+ <c>?FEATURE_ENABLED(Feature)</c> are available.
+ </p>
+ </section>
+
+ <section>
+ <title>Information about Existing Features</title>
+ <p>
+ The module <c>erl_features</c> <seeerl
+ marker="stdlib:erl_features"><c>erl_features</c></seeerl> exports
+ a number of functions that can be used to obtain information about
+ current features as well as the features used when compiling a
+ module.
+ </p>
+ <p>One can also use the <c>erlc</c> options <seecom
+ marker="erts:erlc#list-features"><c>-list-features</c></seecom>
+ and <seecom
+ marker="erts:erlc#describe-feature"><c>-describe-feature
+ &lt;feature&gt;</c></seecom> to get information about existing
+ features.
+ </p>
+ <p>
+ Additionally, there is the compiler option
+ <seeerl
+ marker="compiler:compile#warn-keywords"><c>warn_keywords</c></seeerl>
+ that can be used to find atoms in the code base that might
+ collide with keywords in features not yet enabled.
+ </p>
+ </section>
+
+ <section>
+ <title>Existing Features</title>
+ <p>
+ The following configurable features exist:
+ </p>
+ <taglist>
+ <tag><c>maybe_expr</c> (experimental)</tag>
+ <item>
+ Implementation of the <seeguide
+ marker="expressions#maybe"><c>maybe</c></seeguide> expression
+ proposed in <url href="https://www.erlang.org/eeps/eep-0049">EEP 49</url>.</item>
+ </taglist>
+ </section>
+</chapter>
diff --git a/system/doc/reference_manual/macros.xml b/system/doc/reference_manual/macros.xml
index 0943dbd56d..e54e0e1d30 100644
--- a/system/doc/reference_manual/macros.xml
+++ b/system/doc/reference_manual/macros.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -134,7 +134,8 @@ bar(X) ->
<section>
<title>Predefined Macros</title>
- <p>The following macros are predefined:</p>
+ <p>
+ The following macros are predefined:</p>
<taglist>
<tag><c>?MODULE</c></tag>
<item>The name of the current module.</item>
@@ -155,6 +156,17 @@ bar(X) ->
application is part of, as an integer. For details, see
<seemfa marker="erts:erlang#system_info/1"><c>erlang:system_info(otp_release)</c></seemfa>.
This macro was introduced in OTP release 21.</item>
+ <tag><c>?FEATURE_AVAILABLE(Feature)</c></tag>
+ <item>Expands to <c>true</c> if the <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>
+ <c>Feature</c> is available. The feature might or might not
+ be enabled. This macro was introduced with OTP release
+ 25.</item>
+ <tag><c>?FEATURE_ENABLED(Feature)</c></tag>
+ <item>Expands to <c>true</c> if the <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>
+ <c>Feature</c> is enabled. This macro was introduced with OTP
+ release 25.</item>
</taglist>
</section>
@@ -265,6 +277,27 @@ or
</section>
<section>
+ <title>
+ The -feature() directive
+ </title>
+ <marker id="feature-directive"/>
+
+ <p>
+ The directive <c>-feature(FeatureName, enable | disable)</c> can
+ be used to enable or disable the <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>
+ <c>FeatureName</c>. This is the preferred way of enabling
+ (disabling) features, although it is possible to do it with
+ options to the compiler as well.
+ </p>
+ <p>
+ Note that the <c>-feature(..)</c> directive may only appear
+ before any syntax is used. In practice this means it should
+ appear before any <c>-export(..)</c> or record definitions.
+ </p>
+ </section>
+
+ <section>
<title>-error() and -warning() directives</title>
<p>The directive <c>-error(Term)</c> causes a compilation error.</p>
diff --git a/system/doc/reference_manual/modules.xml b/system/doc/reference_manual/modules.xml
index f5ea7d1580..b373e2506b 100644
--- a/system/doc/reference_manual/modules.xml
+++ b/system/doc/reference_manual/modules.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -129,6 +129,36 @@ fact(0) -> % |
<seeguide marker="code_loading#on_load">
Running a Function When a Module is Loaded</seeguide>.</p>
</item>
+ <tag><marker id="nifs_attribute"/><c>-nifs(Functions).</c></tag>
+ <item>
+ <p>
+ Specifies which of the functions, defined within the module, that
+ may be loaded as NIFs with <seemfa marker="erts:erlang#load_nif/2">
+ <c>erlang:load_nif/2</c></seemfa>.
+ </p>
+ <p>
+ <c>Functions</c> is a list
+ <c>[Name1/Arity1, ..., NameN/ArityN]</c>, where each
+ <c>NameI</c> is an atom and <c>ArityI</c> an integer.
+ </p>
+ <note>
+ <p>
+ The <c>-nifs()</c> attribute was introduced in OTP 25.0. For older
+ Erlang source code without it, any functions in the module may be
+ loaded as NIFs. However, it is recommended to declare the NIFs with
+ the <c>-nifs</c> attribute. This allows the compiler to make better
+ decisions regarding optimizations for example.
+ </p>
+ <p>
+ There is no need to add <c>-nifs([])</c> in modules that do not
+ load NIFs. The lack of any call to
+ <seemfa marker="erts:erlang#load_nif/2"><c>erlang:load_nif/2</c></seemfa>,
+ from within the module, is enough for the compiler to draw the
+ same conclusion.
+ </p>
+ </note>
+ </item>
+
</taglist>
</section>
@@ -221,6 +251,30 @@ behaviour_info(callbacks) -> Callbacks.</pre>
</section>
<section>
+ <title>
+ The feature directive
+ </title>
+
+ <p>
+ While not a module attribute, but rather a directive (since it
+ might affect syntax), there is the <c>-feature(..)</c>
+ directive used for enabling and disabling <seeguide
+ marker="system/reference_manual:features#features">features</seeguide>.
+ </p>
+ <p>
+ The syntax is similar to that of an attribute, but has two
+ arguments:
+ </p>
+ <pre>
+-feature(FeatureName, enable | disable).</pre>
+ <p>
+ Note that the <seeguide
+ marker="macros#feature-directive">feature directive</seeguide>
+ can only appear in a prefix of the module.
+ </p>
+ </section>
+
+ <section>
<title>Comments</title>
<p>Comments can be placed anywhere in a module except within strings
and quoted atoms. A comment begins with the character "%",
diff --git a/system/doc/reference_manual/opaques.xml b/system/doc/reference_manual/opaques.xml
new file mode 100644
index 0000000000..8fa3bae3e5
--- /dev/null
+++ b/system/doc/reference_manual/opaques.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2021</year>
+ <year>2022</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Opaques</title>
+ <prepared>Max Heiber</prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>opaques.xml</file>
+ </header>
+
+ <section>
+ <title>Opaque Type Aliases</title>
+ <p>The main use case for opacity in Erlang is to hide the implementation of a data type, enabling evolving the API while minimizing the risk of breaking consumers. The runtime does not check opacity. Dialyzer provides some opacity-checking, but the rest is up to convention.
+ </p>
+ <p>
+ This document explains what Erlang opacity is (and the trade-offs involved) via the example of OTP's
+ <c>sets:set()</c>
+ data type. This type
+ <em>was</em>
+ defined in `sets` module like this:
+ </p>
+ <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)}.</code>
+ <p>OTP 24 changed the definition to the following, in
+ <url href="https://github.com/erlang/otp/commit/e66941e8d7c47b973dff94c0308ea85a6be1958e">this commit</url>
+ </p>
+ <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)} | #{Element => ?VALUE}.</code>
+ <p>
+ And this change was safer and more backwards-compatible than if the type had been defined with
+ <c>-type</c>
+ instead of
+ <c>-opaque</c>
+ . Here's why: when a module defines an
+ <c>-opaque</c>
+ , the contract is that only the defining module should rely on the definition of the type: no other modules should rely on the definition.
+ </p>
+ <p>
+ This means that code that pattern-matched on
+ <c>set</c>
+ as a record/tuple technically broke the contract, and opted in to being potentially broken when the definition of
+ <c>set()</c>
+ changed. Before OTP 24, this code printed
+ <c>ok</c>
+ . In OTP 24 it may error:
+ </p>
+ <code type="erl">
+case sets:new() of
+ Set when is_tuple(Set) -&gt;
+ io:format(&quot;ok&quot;)
+end.
+ </code>
+ <p>
+ <strong>When working with an opaque defined in another module, here are some recommendations:</strong>
+ </p>
+
+ <list type="bulleted">
+ <item>
+ Don't examine the underlying type using pattern-matching, guards, or functions that reveal the type, such as
+ <c>tuple_size/1</c>
+ .
+ </item>
+ <item>
+ Instead, use functions provided by the module for working with the type. For example,
+ <c>sets</c>
+ module provides
+ <c>sets:new/0</c>
+ ,
+ <c>sets:add/2</c>
+ ,
+ <c>sets:is_element/2</c>
+ , etc.
+ </item>
+ <item>
+ <c>sets:set(a)</c>
+ is a subtype of
+ <c>sets:set(a | b)</c>
+ and not the other way around. Generally, you can rely on the property that
+ <c>the_opaque(T)</c>
+ is a subtype of
+ <c>the_opaque(U)</c>
+ when T is a subtype of U.
+ </item>
+ </list>
+ <p>
+ <strong>When defining your own opaques, here are some recommendations:</strong>
+ </p>
+ <list type="bulleted">
+ <item>
+ Since consumers are expected to not rely on the definition of the opaque type, you must provide functions for constructing and querying/deconstructing intances of your opaque type. For example, sets can be constructed with
+ <c>sets:new/0</c>, <c>sets:from_list/1</c>, <c>sets:add/2</c>, queried with <c>sets:is_element/2</c>, and deconstructed with<c>sets:to_list/1</c>.
+ </item>
+ <item>
+ Don't define an opaque with a type variable in parameter position. This breaks the normal and expected behavior that (for example)
+ <c>my_type(a)</c> is a subtype of <c>my_type(a | b)</c>
+ </item>
+ <item>
+ Add <seeguide marker="typespec">specs</seeguide> to exported functions that use the opaque type
+ </item>
+ </list>
+ <p>Note that opaques can be harder to work with for consumers, since the consumer is expected not to pattern-match and must instead use functions that the author of the opaque type provides to use instances of the type.</p>
+ <p>
+ Also, opacity in Erlang is skin-deep: the runtime does not enforce opacity-checking. So now that sets are implemented in terms of maps, an
+ <c>is_map</c>
+ check on a set
+ <em>will</em>
+ pass. The opacity rules are only enforced by convention and by additional tooling such as Dialyzer. And this enforcement is not total: For example, determined consumer of
+ <c>sets</c>
+ can still do things that reveal the structure of the set, such as by printing, serializing, or using a set as
+ <c>term()</c>
+ and then inspecting via functions like
+ <c>is_map</c>
+ or
+ <c>maps:get/2</c>
+ . And Dialyzer must make some
+ <url href="https://github.com/erlang/otp/issues/5118">approximations</url>
+ . Opacity checking has limitations, but is still a vital tool in scalable Erlang development.
+ </p>
+ </section>
+</chapter>
diff --git a/system/doc/reference_manual/part.xml b/system/doc/reference_manual/part.xml
index 3d31157973..ec2e3e0306 100644
--- a/system/doc/reference_manual/part.xml
+++ b/system/doc/reference_manual/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2003</year><year>2016</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,10 +35,12 @@
<xi:include href="modules.xml"/>
<xi:include href="functions.xml"/>
<xi:include href="typespec.xml"/>
+ <xi:include href="opaques.xml"/>
<xi:include href="expressions.xml"/>
<xi:include href="macros.xml"/>
<xi:include href="records.xml"/>
<xi:include href="errors.xml"/>
+ <xi:include href="features.xml"/>
<xi:include href="processes.xml"/>
<xi:include href="distributed.xml"/>
<xi:include href="code_loading.xml"/>
diff --git a/system/doc/reference_manual/processes.xml b/system/doc/reference_manual/processes.xml
index 4c8c5f7e3f..92be5b60d3 100644
--- a/system/doc/reference_manual/processes.xml
+++ b/system/doc/reference_manual/processes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -700,7 +700,12 @@ spawn(Module, Name, Args) -> pid()
<seecom marker="erts:erl#+zdbbl"><c>+zdbbl</c></seecom>. Note
that if you do raise the limit like this, you need to take care
of flow control yourself to ensure that you do not get into a
- situation with excessive memory usage.
+ situation with excessive memory usage. As of OTP 25.3 it is
+ also possible to enable <i>fully asynchronous distributed
+ signaling</i> on a per process level using
+ <seeerl marker="erts:erlang#process_flag_async_dist">
+ <c>process_flag(async_dist, Bool)</c></seeerl>. Also in this case
+ you need to take care of flow control yourself.
</p>
</item>
</taglist>
@@ -798,7 +803,7 @@ spawn(Module, Name, Args) -> pid()
<list>
<item><p>
<c>noproc</c> in case no process or port was
- found when setting up a link in a preceeding
+ found when setting up a link in a preceding
call to the
<seemfa marker="erts:erlang#link/1"><c>link(PidOrPort)</c></seemfa>
BIF. The process or port identified as sender
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index 0e3d909099..75482e5be1 100644
--- a/system/doc/reference_manual/typespec.xml
+++ b/system/doc/reference_manual/typespec.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -160,7 +160,7 @@
]]></pre>
<p>
Integer values are either integer or character literals or expressions
- consisting of possibily nested unary or binary operations that evaluate to
+ consisting of possibly nested unary or binary operations that evaluate to
an integer. Such expressions can also be used in bit strings and ranges.
</p>
<p>
@@ -411,6 +411,7 @@
types are not accessible by other modules anyway - and is
always to be exported.
</p>
+ <p>Read more on <seeguide marker="opaques">Opaques</seeguide></p>
</section>
<section>
@@ -537,8 +538,7 @@
; (T4, T5) -> T6.</pre>
<p>
A current restriction, which currently results in a warning
- (not an error) by the compiler, is that the domains of
- the argument types cannot overlap.
+ by Dialyzer, is that the domains of the argument types cannot overlap.
For example, the following specification results in a warning:
</p>
<pre>
@@ -607,5 +607,13 @@
of the following form:
</p>
<pre> -spec my_error(term()) -> no_return().</pre>
+
+ <note>
+ <p>Erlang uses the shorthand version <c>_</c> as an anonymous type variable
+ equivalent to <c>term()</c> or <c>any()</c>. For example, the following function</p>
+ <pre> -spec Function(string(), _) -> string().</pre>
+ <p>is equivalent to:</p>
+ <pre> -spec Function(string(), any()) -> string().</pre>
+ </note>
</section>
</chapter>
diff --git a/system/doc/reference_manual/xmlfiles.mk b/system/doc/reference_manual/xmlfiles.mk
index 92d232b628..8e2af09699 100644
--- a/system/doc/reference_manual/xmlfiles.mk
+++ b/system/doc/reference_manual/xmlfiles.mk
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2018. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -27,9 +27,11 @@ REF_MAN_CHAPTER_FILES = \
macros.xml \
records.xml \
errors.xml \
+ features.xml \
processes.xml \
distributed.xml \
code_loading.xml \
ports.xml \
character_set.xml \
- typespec.xml
+ typespec.xml \
+ opaques.xml
diff --git a/system/doc/system_principles/system_principles.xml b/system/doc/system_principles/system_principles.xml
index d0c6f59807..c731e7fb66 100644
--- a/system/doc/system_principles/system_principles.xml
+++ b/system/doc/system_principles/system_principles.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2020</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -107,7 +107,7 @@ init:stop()</pre>
the applications Kernel and STDLIB.</item>
<item><c>start_sasl.boot</c> - Loads the code for and starts
the applications Kernel, STDLIB, and
- SASL).</item>
+ SASL.</item>
<item><c>no_dot_erlang.boot</c> - Loads the code for and
starts the applications Kernel and STDLIB.
Skips loading the file <c>.erlang</c>. Useful for scripts and
diff --git a/system/doc/top/src/erl_html_tools.erl b/system/doc/top/src/erl_html_tools.erl
index 5942861f0f..d609f35380 100644
--- a/system/doc/top/src/erl_html_tools.erl
+++ b/system/doc/top/src/erl_html_tools.erl
@@ -261,7 +261,7 @@ find_application_infos([{App, Vsn, AppPath, IndexURL} | Paths]) ->
case lists:keysearch("group", 1, Db) of
{value, {_, G0}} ->
% This value may be in two parts,
- % tag and desciption
+ % tag and description
case string:str(G0, " ") of
0 ->
{list_to_atom(G0), ""};
diff --git a/system/doc/tutorial/c_port.xmlsrc b/system/doc/tutorial/c_port.xmlsrc
index d89c87eeac..6646f2298e 100644
--- a/system/doc/tutorial/c_port.xmlsrc
+++ b/system/doc/tutorial/c_port.xmlsrc
@@ -158,7 +158,7 @@ Eshell V4.9.1.2 (abort with ^G)
{ok,complex1}</pre>
<p><em>Step 3.</em> Run the example:</p>
<pre>
-2> <input>complex1:start("extprg").</input>
+2> <input>complex1:start("./extprg").</input>
&lt;0.34.0>
3> <input>complex1:foo(3).</input>
4
diff --git a/system/doc/tutorial/complex6.erl b/system/doc/tutorial/complex6.erl
index a5f51886c8..05aa8e68f1 100644
--- a/system/doc/tutorial/complex6.erl
+++ b/system/doc/tutorial/complex6.erl
@@ -1,5 +1,6 @@
-module(complex6).
-export([foo/1, bar/1]).
+-nifs([foo/1, bar/1]).
-on_load(init/0).
init() ->
diff --git a/system/doc/tutorial/debugging.xml b/system/doc/tutorial/debugging.xml
new file mode 100644
index 0000000000..4439bc6d19
--- /dev/null
+++ b/system/doc/tutorial/debugging.xml
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+<chapter>
+ <header>
+ <copyright>
+ <year>2022</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Debugging NIFs and Port Drivers</title>
+ <prepared/>
+ <docno/>
+ <date/>
+ <rev/>
+ <file>debugging.xml</file>
+ </header>
+
+ <section>
+ <title>With great power comes great responsibilty</title>
+ <p>
+ NIFs and port driver code run inside the Erlang VM OS process (the
+ "Beam"). To maximize performance the code is called directly by the same
+ threads executing Erlang beam code and has full access to all the memory
+ of the OS process. A buggy NIF/driver can thus make severe damage by
+ corrupting memory.
+ </p>
+ <p>
+ In a best case scenario such memory corruption is detected immediately
+ causing the Beam to crash generating a core dump file which can be
+ analyzed to find the bug. However, it is very common for memory corruption
+ bugs to not be immediately detected when the faulty write happens, but
+ instead much later, for example when the calling Erlang process is garbage
+ collected. When that happens it can be very hard to find the root cause of
+ the memory corruption by analysing the core dump. All traces that could
+ have indicated which specific buggy NIF/driver that caused the corruption
+ may be long gone.
+ </p>
+ </section>
+ <section>
+ <title>The debug emulator</title>
+ <p>
+ One way to make debugging easier is to run an emulator built with target
+ <c>debug</c>. It will
+ </p>
+ <list type="bulleted">
+ <item>
+ <p>
+ <em>Increase probability of detecting bugs earlier</em>. It contains a
+ lot more runtime checks to ensure correct use of internal interfaces
+ and data structures.
+ </p>
+ </item>
+ <item>
+ <p>
+ <em>Generate a core dump that is easier to analyze</em>. Compiler
+ optimizations are turned off, which stops the compiler from
+ "optimizing away" variables, thus making it easier/possible to inspect
+ their state.
+ </p>
+ </item>
+ <item>
+ <p>
+ <em>Detect lock order violations</em>. A runtime lock checker will
+ verify that the locks in the
+ <seecref marker="erts:erl_nif"><c>erl_nif</c></seecref> and
+ <seecref marker="erts:erl_driver"><c>erl_driver</c></seecref>
+ APIs are seized in a consistent order that cannot result in deadlock
+ bugs.
+ </p>
+ </item>
+ </list>
+ <p>
+ In fact, we recommend to use the debug emulator as default during
+ development of NIFs and drivers, regardless if you are troubleshooting
+ bugs or not. Some subtle bugs may not be detected by the normal emulator
+ and just happen to work anyway by chance. However, another version of the
+ emulator, or even different circumstances within the same emulator, may
+ cause the bug to later provoke all kinds of problems.
+ </p>
+ <p>
+ The main disadvantage of the <c>debug</c> emulator is its reduced
+ performance. The extra runtime checks and lack of compiler optimizations
+ may result in a slowdown with a factor of two or more depending on
+ load. The memory footprint should be about the same.
+ </p>
+ <p>
+ If the <c>debug</c> emulator is part of the Erlang/OTP installation, it can be
+ started with the <seecom marker="erts:erl#emu_type"><c>-emu_type</c></seecom>
+ option.
+ </p>
+ <pre>
+> <input>erl -emu_type debug</input>
+Erlang/OTP 25 [erts-13.0.2] ... <em>[type-assertions] [debug-compiled] [lock-checking]</em>
+
+Eshell V13.0.2 (abort with ^G)
+1>
+</pre>
+ <p>
+ If the <c>debug</c> emulator is not part of the installation, you need to
+ <seeguide marker="system/installation_guide:INSTALL#Advanced-configuration-and-build-of-ErlangOTP_Building_How-to-Build-a-Debug-Enabled-Erlang-RunTime-System">
+ build it from the Erlang/OTP source code</seeguide>. After building from source
+ either make an Erlang/OTP installation or you can run the debug emulator
+ directly in the source tree with the <c>cerl</c> script:
+ </p>
+ <pre>
+> <input>$ERL_TOP/bin/cerl -debug</input>
+Erlang/OTP 25 [erts-13.0.2] ... <em>[type-assertions] [debug-compiled] [lock-checking]</em>
+
+Eshell V13.0.2 (abort with ^G)
+1>
+</pre>
+ <p>
+ The <c>cerl</c> script can also be used as a convenient way to start
+ the debugger <c>gdb</c> for core dump analysis:
+ </p>
+ <pre>
+> <input>$ERL_TOP/bin/cerl -debug -core core.12345</input>
+or
+> <input>$ERL_TOP/bin/cerl -debug -rcore core.12345</input>
+</pre>
+ <p>
+ The first variant starts Emacs and runs <c>gdb</c> within, while
+ the other <c>-rcore</c> runs <c>gdb</c> directly in the terminal. Apart
+ from starting <c>gdb</c> with the correct <c>beam.debug.smp</c> executable
+ file it will also read the file <c>$ERL_TOP/erts/etc/unix/etp-commands</c>
+ which contains a lot of <c>gdb</c> command for inspecting a beam core
+ dump. For example, the command <c>etp</c> that will print the content of
+ an Erlang term (<c>Eterm</c>) in plain Erlang syntax.
+ </p>
+ </section>
+ <section>
+ <title>Address Sanitizer</title>
+ <p>
+ <url href="https://clang.llvm.org/docs/AddressSanitizer.html">
+ AddressSanitizer</url> (asan) is an open source programming tool that
+ detects memory corruption bugs such as buffer overflows, use-after-free
+ and memory leaks. AddressSanitizer is based on compiler instrumentation
+ and is supported by both gcc and clang.
+ </p>
+ <p>
+ Similar to the <c>debug</c> emulator, the <c>asan</c> emulator runs slower
+ than normal, about 2-3 times slower. However, it also has a larger memory
+ footprint, about 3 times more memory than normal.
+ </p>
+ <p>
+ To get full effect you should compile both your own NIF/driver code as
+ well as the Erlang emulator with AddressSanitizer instrumentation. Compile
+ your own code by passing option <c>-fsanitize=address</c> to gcc or
+ clang. Other recommended options that will improve the fault
+ identification are <c>-fno-common</c> and <c>-fno-omit-frame-pointer</c>.
+ </p>
+ <p>
+ Build and run the emulator with AddressSanitizer support by using the same
+ procedure as for the debug emulator, except use the <c>asan</c> build
+ target instead of <c>debug</c>.
+ </p>
+ <taglist>
+ <tag>Run in source tree</tag>
+ <item>
+ <p>
+ If you run the <c>asan</c> emulator directly in the source tree with the
+ <c>cerl</c> script you only need to set environment variable
+ <c>ASAN_LOG_DIR</c> to the directory where the error log files will be
+ generated.
+ </p>
+ <pre>
+> <input>export ASAN_LOG_DIR=/my/asan/log/dir</input>
+> <input>$ERL_TOP/bin/cerl -asan</input>
+Erlang/OTP 25 [erts-13.0.2] ... <em>[address-sanitizer]</em>
+
+Eshell V13.0.2 (abort with ^G)
+1>
+</pre>
+ <p>
+ You may however also want to set <c>ASAN_OPTIONS="halt_on_error=true"</c>
+ if you want the emulator to crash when an error is detected.
+ </p>
+ </item>
+ <tag>Run installed Erlang/OTP</tag>
+ <item>
+ <p>
+ If you run the <c>asan</c> emulator in an installed Erlang/OTP with <c>erl
+ -emu_type asan</c> you need to set the path to the error log
+ <em>file</em> with
+ </p>
+ <pre>
+> <input>export ASAN_OPTIONS="log_path=/my/asan/log/file"</input></pre>
+ <p>
+ To avoid false positive memory leak reports from the emulator
+ itself set <c>LSAN_OPTIONS</c> (LSAN=LeakSanitizer):
+ </p>
+ <pre>
+> <input>export LSAN_OPTIONS="suppressions=$ERL_TOP/erts/emulator/asan/suppress"</input></pre>
+ <p>
+ The <c>suppress</c> file is currently not installed but can be copied
+ manually from the source tree to wherever you want it.
+ </p>
+ </item>
+ </taglist>
+ <p>
+ Memory corruption errors are reported by AddressSanitizer when they
+ happen, but memory leaks are only checked and reported by default then the
+ emulator terminates.
+ </p>
+ </section>
+ <section>
+ <title>Valgrind</title>
+ <p>
+ An even more heavy weight debugging tool is <url
+ href="https://valgrind.org">Valgrind</url>. It can also find memory
+ corruption bugs and memory leaks similar to <c>asan</c>. Valgrind is not
+ as good at buffer overflow bugs, but it will find use of undefined data,
+ which is a type of error that <c>asan</c> cannot detect.
+ </p>
+ <p>
+ Valgrind is much slower than <c>asan</c> and it is incapable at
+ exploiting CPU multicore processing. We therefore recommend <c>asan</c> as
+ the first choice before trying valgrind.
+ </p>
+ <p>
+ Valgrind runs as a virtual machine itself, emulating execution of hardware
+ machine instructions. This means you can run almost any program unchanged
+ on valgrind. However, we have found that the beam executable benefits from
+ being compiled with special adaptions for running on valgrind.
+ </p>
+ <p>
+ Build the emulator with <c>valgrind</c> target the same as is done for
+ <c>debug</c> and <c>asan</c>. Note that <c>valgrind</c> needs to be
+ installed on the machine before the build starts.
+ </p>
+ <p>
+ Run the <c>valgrind</c> emulator directly in the source tree with the
+ <c>cerl</c> script. Set environment variable <c>VALGRIND_LOG_DIR</c> to
+ the directory where the error log files will be generated.
+ </p>
+ <pre>
+> <input>export VALGRIND_LOG_DIR=/my/valgrind/log/dir</input>
+> <input>$ERL_TOP/bin/cerl -valgrind</input>
+Erlang/OTP 25 [erts-13.0.2] ... <em>[valgrind-compiled]</em>
+
+Eshell V13.0.2 (abort with ^G)
+1>
+</pre>
+ </section>
+ <section>
+ <title>rr - Record and Replay</title>
+ <p>
+ Last but not least, the fantastic interactive debugging tool <url
+ href="https://rr-project.org/">rr</url>, developed by Mozilla as
+ open source. <c>rr</c> stands for Record and Replay. While a core dump
+ represents only a static snapshot of the OS process when it crashed, with
+ <c>rr</c> you instead record the entire session, from start of the OS
+ process to the end (the crash). You can then replay that session from
+ within <c>gdb</c>. Single step, set breakpoints and watchpoints, and even
+ <em>execute backwards</em>.
+ </p>
+ <p>
+ Considering its powerful utility, <c>rr</c> is remarkably light weight.
+ It runs on Linux with any reasonably modern x86 CPU. You may get a two
+ times slowdown when executing in recording mode. The big weakness is its
+ inability to exploite CPU multicore processing. If the bug is a race
+ condition between concurrently running threads, it may be hard to
+ reproduce with <c>rr</c>.
+ </p>
+ <p>
+ <c>rr</c> does not require any special instrumented compilation. However,
+ if possible, run it together with the <c>debug</c> emulator, as that will
+ result in a much nicer debugging experience. You run <c>rr</c> in the
+ source tree using the <c>cerl</c> script.
+ </p>
+ <p>
+ Here is an example of a typical session. First we catch the crash in an rr
+ recording session:
+ </p>
+ <pre>
+> <input>$ERL_TOP/bin/cerl -debug -rr</input>
+rr: Saving execution to trace directory /home/foobar/.local/share/rr/beam.debug.smp-1.
+Erlang/OTP 25 [erts-13.0.2]
+
+Eshell V13.0.2 (abort with ^G)
+1> <input>mymod:buggy_nif().</input>
+Segmentation fault</pre>
+ <p>
+ Now we can replay that session with <c>rr replay</c>:
+ </p>
+ <pre>
+> <input>rr replay</input>
+GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
+:
+(rr) <input>continue</input>
+:
+Thread 2 received signal SIGSEGV, Segmentation fault.
+(rr) <input>backtrace</input></pre>
+ <p>
+ You get the call stack at the moment of the crash. Bad luck, it is
+ somewhere deep down in the garbage collection of the beam. But you manage
+ to figure out that variable <c>hp</c> points to a broken Erlang term.
+ </p>
+ <p>
+ Set a watch point on that memory position and resume execution
+ <em>backwards</em>. The debugger will then stop at the exact position when
+ that memory position <c>*hp</c> was written.
+ </p>
+ <pre>
+(rr) <input>watch -l *hp</input>
+Hardware watchpoint 1: -location *hp
+(rr) <input>reverse-continue</input>
+Continuing.
+
+Thread 2 received signal SIGSEGV, Segmentation fault.</pre>
+ <p>
+ This is a quirk to be aware about. We started by executing forward until
+ it crashed with SIGSEGV. We are now executing backwards from that point,
+ so we are hitting the same SIGSEGV again but from the other
+ direction. Just continue backwards once more to move past it.
+ </p>
+ <pre>
+(rr) <input>reverse-continue</input>
+Continuing.
+
+Thread 2 hit Hardware watchpoint 1: -location *hp
+
+Old value = 42
+New value = 0</pre>
+ <p>
+ And here we are at the position when someone wrote a broken term on the
+ process heap. Note that "Old value" and "New value" are reversed when we
+ execute backwards. In this case the value 42 was written on the heap.
+ Let's see who the guilty one is:
+ </p>
+ <pre>
+(rr) <input>backtrace</input></pre>
+ </section>
+</chapter>
diff --git a/system/doc/tutorial/nif.xmlsrc b/system/doc/tutorial/nif.xmlsrc
index 5fd94a7946..5f932cd5ba 100644
--- a/system/doc/tutorial/nif.xmlsrc
+++ b/system/doc/tutorial/nif.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2021</year>
+ <year>2000</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,8 +32,7 @@
<p>This section outlines an example of how to solve the example
problem in <seeguide marker="example">Problem Example</seeguide>
by using Native Implemented Functions (NIFs).</p>
- <p>NIFs were introduced in Erlang/OTP R13B03 as an experimental
- feature. It is a simpler and more efficient way of calling C-code
+ <p>NIFs are a simpler and more efficient way of calling C-code
than using port drivers. NIFs are most suitable for synchronous
functions, such as <c>foo</c> and <c>bar</c> in the example, that
do some relatively short calculations without side effects and
@@ -62,7 +61,7 @@
</list>
<p>Normally these are minimal stub implementations that throw an
exception. But they can also be used as fallback implementations
- for functions that do not have native implemenations on some
+ for functions that do not have native implementations on some
architectures.</p>
<p>NIF libraries are loaded by calling <c>erlang:load_nif/2</c>,
with the name of the shared library as argument. The second
@@ -99,7 +98,7 @@
<codeinclude file="complex6_nif.c" tag="" type="none"></codeinclude>
- <p>Here,<c>ERL_NIF_INIT</c> has the following arguments:</p>
+ <p>Here, <c>ERL_NIF_INIT</c> has the following arguments:</p>
<list type="bulleted">
<item><p>The first argument must be the name of the
Erlang module as a C-identifier. It will be stringified by the
diff --git a/system/doc/tutorial/part.xml b/system/doc/tutorial/part.xml
index 4a66f0cb22..f546890e79 100644
--- a/system/doc/tutorial/part.xml
+++ b/system/doc/tutorial/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2000</year><year>2016</year>
+ <year>2000</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,5 +36,6 @@
<xi:include href="c_portdriver.xml"/>
<xi:include href="cnode.xml"/>
<xi:include href="nif.xml"/>
+ <xi:include href="debugging.xml"/>
</part>
diff --git a/system/doc/tutorial/xmlfiles.mk b/system/doc/tutorial/xmlfiles.mk
index 74e174f6d4..a2c024d2dd 100644
--- a/system/doc/tutorial/xmlfiles.mk
+++ b/system/doc/tutorial/xmlfiles.mk
@@ -1,7 +1,8 @@
+
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2018. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,7 +20,8 @@
#
TUTORIAL_CHAPTER_FILES = \
introduction.xml\
- overview.xml
+ overview.xml\
+ debugging.xml
TUTORIAL_CHAPTER_GEN_FILES = \
cnode.xml\