diff options
Diffstat (limited to 'erts/doc/src')
-rw-r--r-- | erts/doc/src/absform.xml | 22 | ||||
-rw-r--r-- | erts/doc/src/erl.xml | 115 | ||||
-rw-r--r-- | erts/doc/src/erl_dist_protocol.xml | 13 | ||||
-rw-r--r-- | erts/doc/src/erl_ext_dist.xml | 163 | ||||
-rw-r--r-- | erts/doc/src/erl_nif.xml | 732 | ||||
-rw-r--r-- | erts/doc/src/erl_tracer.xml | 19 | ||||
-rw-r--r-- | erts/doc/src/erlang.xml | 608 | ||||
-rw-r--r-- | erts/doc/src/erts_alloc.xml | 6 | ||||
-rw-r--r-- | erts/doc/src/escript.xml | 24 | ||||
-rw-r--r-- | erts/doc/src/notes.xml | 837 | ||||
-rw-r--r-- | erts/doc/src/zlib.xml | 219 |
11 files changed, 2288 insertions, 470 deletions
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml index ab00d47425..e49c8c32e9 100644 --- a/erts/doc/src/absform.xml +++ b/erts/doc/src/absform.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2001</year><year>2016</year> + <year>2001</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -182,10 +182,18 @@ can contain the following:</p> <list type="bulleted"> - <item>Tuples <c>{error,E}</c> and <c>{warning,W}</c>, denoting - syntactically incorrect forms and warnings</item> - <item><c>{eof,LINE}</c>, denoting an end-of-stream - encountered before a complete form had been parsed</item> + <item> + <p>Tuples <c>{error,E}</c> and <c>{warning,W}</c>, denoting + syntactically incorrect forms and warnings. + </p> + </item> + <item> + <p><c>{eof,LOCATION}</c>, denoting an end-of-stream + encountered before a complete form had been parsed. + The word <c>LOCATION</c> represents an integer, and denotes the + number of the last line in the source file. + </p> + </item> </list> </section> </section> @@ -357,7 +365,7 @@ <c>{cons,LINE,Rep(E_h),Rep(E_t)}</c>.</p> </item> <item> - <p>>If E is a fun expression <c>fun Name/Arity</c>, then Rep(E) = + <p>If E is a fun expression <c>fun Name/Arity</c>, then Rep(E) = <c>{'fun',LINE,{function,Name,Arity}}</c>.</p> </item> <item> @@ -886,7 +894,7 @@ Rep(Fc) = <c>[Rep(C_1), ..., Rep(C_k)]</c>.</p> <list type="bulleted"> - <item>If C is a constraint <c>is_subtype(V, T)</c> or <c>V :: T</c>, + <item>If C is a constraint <c>V :: T</c>, where <c>V</c> is a type variable and <c>T</c> is a type, then Rep(C) = <c>{type,LINE,constraint,[{atom,LINE,is_subtype},[Rep(V),Rep(T)]]}</c>. diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index 8da832ac37..638e88ca31 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -4,7 +4,7 @@ <comref> <header> <copyright> - <year>1996</year><year>2016</year> + <year>1996</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -239,6 +239,13 @@ <item> <p>Useful for debugging. Prints the arguments sent to the emulator.</p> </item> + <tag><c><![CDATA[-emu_type Type]]></c></tag> + <item> + <p>Start an emulator of a different type. For example, to start + the lock-counter emualator, use <c>-emu_type lcnt</c>. (The emulator + must already be built. Use the <c>configure</c> option + <c>--enable-lock-counter</c> to build the lock-counter emulator.)</p> + </item> <tag><c><![CDATA[-env Variable Value]]></c></tag> <item> <p>Sets the host OS environment variable <c><![CDATA[Variable]]></c> to @@ -372,6 +379,16 @@ <c><![CDATA[Host]]></c> is the fully qualified host name of the current host. For short names, use flag <c><![CDATA[-sname]]></c> instead.</p> + <warning> + <p> + Starting a distributed node without also specifying + <seealso marker="#proto_dist"><c>-proto_dist inet_tls</c></seealso> + will expose the node to attacks that may give the attacker + complete access to the node and in extension the cluster. + When using un-secure distributed nodes, make sure that the + network is configured to keep potential attackers out. + </p> + </warning> </item> <tag><c><![CDATA[-noinput]]></c></tag> <item> @@ -421,12 +438,17 @@ </item> <tag><c><![CDATA[-proto_dist Proto]]></c></tag> <item> + <marker id="proto_dist"/> <p>Specifies a protocol for Erlang distribution:</p> <taglist> <tag><c>inet_tcp</c></tag> <item>TCP over IPv4 (the default)</item> <tag><c>inet_tls</c></tag> - <item>Distribution over TLS/SSL</item> + <item>Distribution over TLS/SSL, See the + <seealso marker="ssl:ssl_distribution"> + Using SSL for Erlang Distribution</seealso> User's Guide + for details on how to setup a secure distributed node. + </item> <tag><c>inet6_tcp</c></tag> <item>TCP over IPv6</item> </taglist> @@ -490,6 +512,16 @@ exist between nodes running with flag <c><![CDATA[-sname]]></c> and those running with flag <c><![CDATA[-name]]></c>, as node names must be unique in distributed Erlang systems.</p> + <warning> + <p> + Starting a distributed node without also specifying + <seealso marker="#proto_dist"><c>-proto_dist inet_tls</c></seealso> + will expose the node to attacks that may give the attacker + complete access to the node and in extension the cluster. + When using un-secure distributed nodes, make sure that the + network is configured to keep potential attackers out. + </p> + </warning> </item> <tag><marker id="start_epmd"/><c>-start_epmd true | false</c></tag> <item> @@ -513,11 +545,11 @@ system with SMP support is available. <c>-smp auto</c> starts the Erlang runtime system with SMP support enabled if it is available and more than one logical processor is detected. - <c>-smp disable</c> starts a runtime system without SMP support.</p> + <c>-smp disable</c> starts a runtime system without SMP support. + The runtime system without SMP support is deprecated and will + be removed in a future major release.</p> <note> - <p>The runtime system with SMP support is not available on all - supported platforms. See also flag - <seealso marker="#+S"><c>+S</c></seealso>.</p> + <p>See also flag<seealso marker="#+S"><c>+S</c></seealso>.</p> </note> </item> <tag><c><![CDATA[-version]]></c> (emulator flag)</tag> @@ -638,7 +670,7 @@ this value also applies to command-line parameters and environment variables (see section <seealso marker="stdlib:unicode_usage#unicode_in_environment_and_parameters"> - Unicode in Enviroment and Parameters</seealso> in the STDLIB + Unicode in Environment and Parameters</seealso> in the STDLIB User's Guide).</p> </item> <tag><c><![CDATA[+fnu[{w|i|e}]]]></c></tag> @@ -674,7 +706,7 @@ this value also applies to command-line parameters and environment variables (see section <seealso marker="stdlib:unicode_usage#unicode_in_environment_and_parameters"> - Unicode in Enviroment and Parameters</seealso> in the STDLIB + Unicode in Environment and Parameters</seealso> in the STDLIB User's Guide).</p> </item> <tag><c><![CDATA[+fna[{w|i|e}]]]></c></tag> @@ -695,7 +727,7 @@ this value also applies to command-line parameters and environment variables (see section <seealso marker="stdlib:unicode_usage#unicode_in_environment_and_parameters"> - Unicode in Enviroment and Parameters</seealso> in the STDLIB + Unicode in Environment and Parameters</seealso> in the STDLIB User's Guide).</p> </item> <tag><c><![CDATA[+hms Size]]></c></tag> @@ -946,9 +978,7 @@ schedulers was allowed to be unlimited, dirty CPU bound jobs would potentially starve normal jobs.</p> <p>This option is ignored if the emulator does not have threading - support enabled. <em>This option is experimental</em> and - is supported only if the emulator was configured and built with - support for dirty schedulers enabled (it is disabled by default).</p> + support enabled.</p> </item> <tag><marker id="+SDPcpu"/><c><![CDATA[+SDPcpu DirtyCPUSchedulersPercentage:DirtyCPUSchedulersOnlinePercentage]]></c></tag> @@ -974,9 +1004,7 @@ either order) results in 2 dirty CPU scheduler threads (50% of 4) and 1 dirty CPU scheduler thread online (25% of 4).</p> <p>This option is ignored if the emulator does not have threading - support enabled. <em>This option is experimental</em> and - is supported only if the emulator was configured and built with - support for dirty schedulers enabled (it is disabled by default).</p> + support enabled.</p> </item> <tag><marker id="+SDio"/><c><![CDATA[+SDio DirtyIOSchedulers]]></c></tag> <item> @@ -992,9 +1020,7 @@ bound jobs on dirty I/O schedulers, these jobs might starve ordinary jobs executing on ordinary schedulers.</p> <p>This option is ignored if the emulator does not have threading - support enabled. <em>This option is experimental</em> and - is supported only if the emulator was configured and built with - support for dirty schedulers enabled (it is disabled by default).</p> + support enabled.</p> </item> <tag><c><![CDATA[+sFlag Value]]></c></tag> <item> @@ -1324,8 +1350,22 @@ <c><![CDATA[+sss size]]></c></tag> <item> <p>Suggested stack size, in kilowords, for scheduler threads. - Valid range is 4-8192 kilowords. The default stack size is - OS-dependent.</p> + Valid range is 20-8192 kilowords. The default suggested + stack size is 128 kilowords.</p> + </item> + <tag><marker id="dcpu_sched_thread_stack_size"/> + <c><![CDATA[+sssdcpu size]]></c></tag> + <item> + <p>Suggested stack size, in kilowords, for dirty CPU scheduler + threads. Valid range is 20-8192 kilowords. The default + suggested stack size is 40 kilowords.</p> + </item> + <tag><marker id="dio_sched_thread_stack_size"/> + <c><![CDATA[+sssdio size]]></c></tag> + <item> + <p>Suggested stack size, in kilowords, for dirty IO scheduler + threads. Valid range is 20-8192 kilowords. The default + suggested stack size is 40 kilowords.</p> </item> <tag><marker id="+stbt"/><c>+stbt BindType</c></tag> <item> @@ -1513,32 +1553,27 @@ <item> <p><em>Unix systems</em>: This variable gives the number of seconds that the emulator is allowed to spend writing a crash dump. When the - given number of seconds have elapsed, the emulator is terminated by a - <c>SIGALRM</c> signal.</p> - <p>If the variable is <em>not</em> set or set to <c>0</c> seconds - (<c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c>), the runtime system does - not even attempt to write the crash dump file. It only terminates.</p> - <p>If the variable is set to negative value, such as - <c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c>, the runtime system - waits indefinitely for the crash dump file to be written.</p> - <p>This variable is used with <seealso marker="kernel:heart"> - <c>heart(3)</c></seealso> if <c>heart</c> is running:</p> + given number of seconds have elapsed, the emulator is terminated.</p> <taglist> <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c></tag> - <item>Suppresses the writing a crash dump file entirely, thus - rebooting the runtime system immediately. This is the same as not - setting the environment variable. + <item>If the variable is set to <c>0</c> seconds, the runtime system does + not even attempt to write the crash dump file. It only terminates. + This is the default if option <c>-heart</c> is passed to <c>erl</c> + and <c>ERL_CRASH_DUMP_SECONDS</c> is not set. + </item> + <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=S]]></c></tag> + <item>If the variable is set to a positive value <c>S</c>, + wait for <c>S</c> seconds to complete the crash dump file and + then terminates the runtime system with a <c>SIGALRM</c> signal. </item> <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c></tag> - <item>Setting the environment variable to a negative value causes the - termination of the runtime system to wait until the crash dump file - has been completly written. - </item> - <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=S]]></c></tag> - <item>Waits for <c>S</c> seconds to complete the crash dump file and - then terminates the runtime system. + <item>A negative value causes the termination of the runtime system + to wait indefinitely until the crash dump file has been completly + written. This is the default if option <c>-heart</c> is <em>not</em> + passed to <c>erl</c> and <c>ERL_CRASH_DUMP_SECONDS</c> is not set. </item> </taglist> + <p>See also <seealso marker="kernel:heart"><c>heart(3)</c></seealso>.</p> </item> <tag><c><![CDATA[ERL_CRASH_DUMP_BYTES]]></c></tag> <item> diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml index ee74983730..610351db6c 100644 --- a/erts/doc/src/erl_dist_protocol.xml +++ b/erts/doc/src/erl_dist_protocol.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2007</year> - <year>2016</year> + <year>2017</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -70,6 +70,17 @@ <p>The integers in all multibyte fields are in big-endian order.</p> + <warning> + <p> + The Erlang Distribution protocol is not by itself secure and does not + aim to be so. In order to get secure distribution the distributed nodes + should be configured to use distribution over tls. + See the <seealso marker="ssl:ssl_distribution"> + Using SSL for Erlang Distribution</seealso> User's Guide + for details on how to setup a secure distributed node. + </p> + </warning> + <section> <title>EPMD Protocol</title> <p>The requests served by the EPMD are summarized in the following diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml index 4f799f8f34..b7090d0472 100644 --- a/erts/doc/src/erl_ext_dist.xml +++ b/erts/doc/src/erl_ext_dist.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2007</year> - <year>2016</year> + <year>2017</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -51,7 +51,7 @@ term into the external format. To convert binary data encoding to a term, the BIF <seealso marker="erts:erlang#binary_to_term/1"> - <c>erlang:binary_to_term/1</c>c></seealso> is used. + <c>erlang:binary_to_term/1</c></seealso> is used. </p> <p> The distribution does this implicitly when sending messages across @@ -119,27 +119,18 @@ <tcaption>Compressed Data Format when Expanded</tcaption></table> <marker id="utf8_atoms"/> <note> - <p>As from ERTS 5.10 (OTP R16) support - for UTF-8 encoded atoms has been introduced in the external format. - However, only characters that can be encoded using Latin-1 (ISO-8859-1) - are currently supported in atoms. The support for UTF-8 encoded atoms - in the external format has been implemented to be able to support - all Unicode characters in atoms in <em>some future release</em>. - Until full Unicode support for atoms has been introduced, - it is an <em>error</em> to pass atoms containing - characters that cannot be encoded in Latin-1, and <em>the behavior is - undefined</em>.</p> - <p>When distribution flag <seealso marker="erl_dist_protocol#dflags"> - <c>DFLAG_UTF8_ATOMS</c></seealso> has been exchanged between both nodes - in the <seealso marker="erl_dist_protocol#distribution_handshake"> - distribution handshake</seealso>, all atoms in the distribution header - are encoded in UTF-8, otherwise in Latin-1. The two - new tags <seealso marker="#ATOM_UTF8_EXT"><c>ATOM_UTF8_EXT</c></seealso> - and <seealso marker="#SMALL_ATOM_UTF8_EXT"> - <c>SMALL_ATOM_UTF8_EXT</c></seealso> - are only used if the distribution flag <c>DFLAG_UTF8_ATOMS</c> has - been exchanged between nodes, or if an atom containing characters - that cannot be encoded in Latin-1 is encountered.</p> + <p>As from ERTS 9.0 (OTP 20), atoms may contain any Unicode + characters and are always encoded using the UTF-8 external formats + <seealso marker="#ATOM_UTF8_EXT"><c>ATOM_UTF8_EXT</c></seealso> + or <seealso marker="#SMALL_ATOM_UTF8_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>. + The old Latin-1 formats <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso> + and <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso> + are deprecated and are only kept for backward + compatibility when decoding terms encoded by older nodes.</p> + <p>Support for UTF-8 encoded atoms in the external format has been + available since ERTS 5.10 (OTP R16). This abillity allows such old nodes + to decode, store and encode any Unicode atoms received from a new OTP 20 + node.</p> <p>The maximum number of allowed characters in an atom is 255. In the UTF-8 case, each character can need 4 bytes to be encoded.</p> </note> @@ -395,28 +386,6 @@ </section> <section> - <marker id="ATOM_EXT"/> - <title>ATOM_EXT</title> - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">2</cell> - <cell align="center">Len</cell> - </row> - <row> - <cell align="center"><c>100</c></cell> - <cell align="center"><c>Len</c></cell> - <cell align="center"><c>AtomName</c></cell> - </row> - <tcaption>ATOM_EXT</tcaption></table> - <p> - An atom is stored with a 2 byte unsigned length in big-endian order, - followed by <c>Len</c> numbers of 8-bit Latin-1 characters that forms - the <c>AtomName</c>. The maximum allowed value for <c>Len</c> is 255. - </p> - </section> - - <section> <marker id="REFERENCE_EXT"/> <title>REFERENCE_EXT</title> <table align="left"> @@ -437,8 +406,8 @@ Encodes a reference object (an object generated with <seealso marker="erlang:make_ref/0">erlang:make_ref/0</seealso>). The <c>Node</c> term is an encoded atom, that is, - <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>, - <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso>, or + <seealso marker="#ATOM_UTF8_EXT"><c>ATOM_UTF8_EXT</c></seealso>, + <seealso marker="#SMALL_ATOM_UTF8_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>, or <seealso marker="#ATOM_CACHE_REF"><c>ATOM_CACHE_REF</c></seealso>. The <c>ID</c> field contains a big-endian unsigned integer, but <em>is to be regarded as uninterpreted data</em>, @@ -777,39 +746,6 @@ </section> <section> - <marker id="SMALL_ATOM_EXT"/> - <title>SMALL_ATOM_EXT</title> - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">Len</cell> - </row> - <row> - <cell align="center"><c>115</c></cell> - <cell align="center"><c>Len</c></cell> - <cell align="center"><c>AtomName</c></cell> - </row> - <tcaption>SMALL_ATOM_EXT</tcaption></table> - <p> - An atom is stored with a 1 byte unsigned length, - followed by <c>Len</c> numbers of 8-bit Latin-1 characters that - forms the <c>AtomName</c>. Longer atoms can be represented - by <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>. - </p> - <note> - <p> - <c>SMALL_ATOM_EXT</c> was introduced in ERTS 5.7.2 and - require an exchange of distribution flag - <seealso marker="erl_dist_protocol#dflags"> - <c>DFLAG_SMALL_ATOM_TAGS</c></seealso> in the - <seealso marker="erl_dist_protocol#distribution_handshake"> - distribution handshake</seealso>. - </p> - </note> - </section> - - <section> <marker id="FUN_EXT"/> <title>FUN_EXT</title> <table align="left"> @@ -843,8 +779,8 @@ <tag><c>Module</c></tag> <item> <p>Encoded as an atom, using - <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>, - <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso>, + <seealso marker="#ATOM_UTF8_EXT"><c>ATOM_UTF8_EXT</c></seealso>, + <seealso marker="#SMALL_ATOM_UTF8_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>, or <seealso marker="#ATOM_CACHE_REF"> <c>ATOM_CACHE_REF</c></seealso>. This is the module that the fun is implemented in. @@ -938,8 +874,8 @@ <tag><c>Module</c></tag> <item> <p>Encoded as an atom, using - <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>, - <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso>, + <seealso marker="#ATOM_EXT"><c>ATOM_UTF8_EXT</c></seealso>, + <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>, or <seealso marker="#ATOM_CACHE_REF"> <c>ATOM_CACHE_REF</c></seealso>. Is the module that the fun is implemented in. @@ -1001,8 +937,8 @@ </p> <p> <c>Module</c> and <c>Function</c> are atoms - (encoded using <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>, - <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso>, or + (encoded using <seealso marker="#ATOM_EXT"><c>ATOM_UTF8_EXT</c></seealso>, + <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>, or <seealso marker="#ATOM_CACHE_REF"><c>ATOM_CACHE_REF</c></seealso>). </p> <p> @@ -1114,6 +1050,61 @@ in the beginning of this section. </p> </section> + + <section> + <marker id="ATOM_EXT"/> + <title>ATOM_EXT (deprecated)</title> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">2</cell> + <cell align="center">Len</cell> + </row> + <row> + <cell align="center"><c>100</c></cell> + <cell align="center"><c>Len</c></cell> + <cell align="center"><c>AtomName</c></cell> + </row> + <tcaption>ATOM_EXT</tcaption></table> + <p> + An atom is stored with a 2 byte unsigned length in big-endian order, + followed by <c>Len</c> numbers of 8-bit Latin-1 characters that forms + the <c>AtomName</c>. The maximum allowed value for <c>Len</c> is 255. + </p> + </section> + + <section> + <marker id="SMALL_ATOM_EXT"/> + <title>SMALL_ATOM_EXT (deprecated)</title> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">Len</cell> + </row> + <row> + <cell align="center"><c>115</c></cell> + <cell align="center"><c>Len</c></cell> + <cell align="center"><c>AtomName</c></cell> + </row> + <tcaption>SMALL_ATOM_EXT</tcaption></table> + <p> + An atom is stored with a 1 byte unsigned length, + followed by <c>Len</c> numbers of 8-bit Latin-1 characters that + forms the <c>AtomName</c>. + </p> + <note> + <p> + <c>SMALL_ATOM_EXT</c> was introduced in ERTS 5.7.2 and + require an exchange of distribution flag + <seealso marker="erl_dist_protocol#dflags"> + <c>DFLAG_SMALL_ATOM_TAGS</c></seealso> in the + <seealso marker="erl_dist_protocol#distribution_handshake"> + distribution handshake</seealso>. + </p> + </note> + </section> + </chapter> diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index b5dc9037c4..419e41693e 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -4,7 +4,7 @@ <cref> <header> <copyright> - <year>2001</year><year>2016</year> + <year>2001</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -80,7 +80,7 @@ <code type="none"> /* niftest.c */ -#include "erl_nif.h" +#include <erl_nif.h> static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { @@ -123,7 +123,7 @@ ok "Hello world!"</code> <p>A better solution for a real module is to take advantage of the new - directive <c>on load</c> (see section + directive <c>on_load</c> (see section <seealso marker="doc/reference_manual:code_loading#on_load">Running a Function When a Module is Loaded</seealso> in the Erlang Reference Manual) to load the NIF library automatically when the module is @@ -135,27 +135,14 @@ ok away by the compiler, causing loading of the NIF library to fail.</p> </note> - <p>A loaded NIF library is tied to the Erlang module code version - that loaded it. If the module is upgraded with a new version, the - new Erlang code need to load its own NIF library (or maybe choose not - to). The new code version can, however, choose to load the - same NIF library as the old code if it wants to. Sharing the - dynamic library means that static data defined by the library - is shared as well. To avoid unintentionally shared static - data, each Erlang module code can keep its own private data. This - private data can be set when the NIF library is loaded and - then retrieved by calling <seealso marker="#enif_priv_data"> - <c>enif_priv_data</c></seealso>.</p> - - <p>A NIF library cannot be loaded explicitly. A library is - automatically unloaded when the module code that it belongs to is purged - by the code server.</p> + <p>Once loaded, a NIF library is persistent. It will not be unloaded + until the module code version that it belongs to is purged.</p> </description> <section> <title>Functionality</title> - <p>All functions that a NIF library needs to do with Erlang are - performed through the NIF API functions. Functions exist + <p>All interaction between NIF code and the Erlang runtime system is + performed by calling NIF API functions. Functions exist for the following functionality:</p> <taglist> @@ -219,7 +206,7 @@ ok <seealso marker="#enif_make_resource"> <c>enif_make_resource</c></seealso>. The term returned by <c>enif_make_resource</c> is opaque in nature. - It can be stored and passed between processes on the same node, but + It can be stored and passed between processes, but the only real end usage is to pass it back as an argument to a NIF. The NIF can then call <seealso marker="#enif_get_resource"> <c>enif_get_resource</c></seealso> and get back a pointer to the @@ -286,6 +273,19 @@ return term;</code> library is postponed as long as there exist resource objects with a destructor function in the library.</p> </item> + <tag>Module upgrade and static data</tag> + <item> + <p>A loaded NIF library is tied to the Erlang module instance + that loaded it. If the module is upgraded, the new module instance + needs to load its own NIF library (or maybe choose not to). The new + module instance can, however, choose to load the exact same NIF library + as the old code if it wants to. Sharing the dynamic library means that + static data defined by the library is shared as well. To avoid + unintentionally shared static data between module instances, each Erlang + module version can keep its own private data. This private data can be + set when the NIF library is loaded and later retrieved by calling + <seealso marker="#enif_priv_data"><c>enif_priv_data</c></seealso>.</p> + </item> <tag>Threads and concurrency</tag> <item> <p>A NIF is thread-safe without any explicit synchronization as @@ -296,8 +296,8 @@ return term;</code> synchronization. This includes terms in process-independent environments that are shared between threads. Resource objects also require synchronization if you treat them as mutable.</p> - <p>The library initialization callbacks <c>load</c>, <c>reload</c>, and - <c>upgrade</c> are all thread-safe even for shared state data.</p> + <p>The library initialization callbacks <c>load</c> and + <c>upgrade</c> are thread-safe even for shared state data.</p> </item> <tag><marker id="version_management"/>Version Management</tag> <item> @@ -344,6 +344,81 @@ return term;</code> <c>enif_convert_time_unit()</c></seealso></item> </list> </item> + <tag><marker id="enif_ioq"/>I/O Queues</tag> + <item> + <p>The Erlang nif library contains function for easily working + with I/O vectors as used by the unix system call <c>writev</c>. + The I/O Queue is not thread safe, so some other synchronization + mechanism has to be used.</p> + <list type="bulleted"> + <item><seealso marker="#SysIOVec"> + <c>SysIOVec</c></seealso></item> + <item><seealso marker="#ErlNifIOVec"> + <c>ErlNifIOVec</c></seealso></item> + <item><seealso marker="#enif_ioq_create"> + <c>enif_ioq_create()</c></seealso></item> + <item><seealso marker="#enif_ioq_destroy"> + <c>enif_ioq_destroy()</c></seealso></item> + <item><seealso marker="#enif_ioq_enq_binary"> + <c>enif_ioq_enq_binary()</c></seealso></item> + <item><seealso marker="#enif_ioq_enqv"> + <c>enif_ioq_enqv()</c></seealso></item> + <item><seealso marker="#enif_ioq_deq"> + <c>enif_ioq_deq()</c></seealso></item> + <item><seealso marker="#enif_ioq_peek"> + <c>enif_ioq_peek()</c></seealso></item> + <item><seealso marker="#enif_inspect_iovec"> + <c>enif_inspect_iovec()</c></seealso></item> + <item><seealso marker="#enif_free_iovec"> + <c>enif_free_iovec()</c></seealso></item> + </list> + <p>Typical usage when writing to a file descriptor looks like this:</p> + <code type="none"><![CDATA[ +int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail, + ErlNifIOQueue *q, int fd) { + + ErlNifIOVec vec, *iovec = &vec; + SysIOVec *sysiovec; + int saved_errno; + int iovcnt, n; + + if (!enif_inspect_iovec(env, 64, term, tail, &iovec)) + return -2; + + if (enif_ioq_size(q) > 0) { + /* If the I/O queue contains data we enqueue the iovec and + then peek the data to write out of the queue. */ + if (!enif_ioq_enqv(q, iovec, 0)) + return -3; + + sysiovec = enif_ioq_peek(q, &iovcnt); + } else { + /* If the I/O queue is empty we skip the trip through it. */ + iovcnt = iovec->iovcnt; + sysiovec = iovec->iov; + } + + /* Attempt to write the data */ + n = writev(fd, sysiovec, iovcnt); + saved_errno = errno; + + if (enif_ioq_size(q) == 0) { + /* If the I/O queue was initially empty we enqueue any + remaining data into the queue for writing later. */ + if (n >= 0 && !enif_ioq_enqv(q, iovec, n)) + return -3; + } else { + /* Dequeue any data that was written from the queue. */ + if (n > 0 && !enif_ioq_deq(q, n, NULL)) + return -4; + } + + /* return n, which is either number of bytes written or -1 if + some error happened */ + errno = saved_errno; + return n; +}]]></code> + </item> <tag><marker id="lengthy_work"/>Long-running NIFs</tag> <item> <p>As mentioned in the <seealso marker="#WARNING">warning</seealso> text @@ -402,14 +477,14 @@ return term;</code> <tag><marker id="dirty_nifs"/>Dirty NIF</tag> <item> <note> - <p><em>The dirty NIF functionality described here - is experimental</em>. Dirty NIF support is available only when - the emulator is configured with dirty schedulers enabled. This - feature is disabled by default. The Erlang runtime - without SMP support does not support dirty schedulers even when - the dirty scheduler support is enabled. To check at runtime for - the presence of dirty scheduler threads, code can use the - <seealso marker="#enif_system_info"> + <p>Dirty NIF support is available only when the emulator is + configured with dirty scheduler support. As of ERTS version + 9.0, dirty scheduler support is enabled by default on the + runtime system with SMP support. The Erlang runtime without + SMP support does <em>not</em> support dirty schedulers even + when the dirty scheduler support is explicitly enabled. To + check at runtime for the presence of dirty scheduler threads, + code can use the <seealso marker="#enif_system_info"> <c>enif_system_info()</c></seealso> API function.</p> </note> <p>A NIF that cannot be split and cannot execute in a millisecond @@ -498,7 +573,7 @@ return term;</code> <title>Initialization</title> <taglist> <tag><marker id="ERL_NIF_INIT"/><c>ERL_NIF_INIT(MODULE, - ErlNifFunc funcs[], load, reload, upgrade, unload)</c></tag> + ErlNifFunc funcs[], load, NULL, upgrade, unload)</c></tag> <item> <p>This is the magic macro to initialize a NIF library. It is to be evaluated in global file scope.</p> @@ -507,11 +582,14 @@ return term;</code> the macro.</p> <p><c>funcs</c> is a static array of function descriptors for all the implemented NIFs in this library.</p> - <p><c>load</c>, <c>reload</c>, <c>upgrade</c> and <c>unload</c> - are pointers to functions. One of <c>load</c>, <c>reload</c>, or + <p><c>load</c>, <c>upgrade</c> and <c>unload</c> + are pointers to functions. One of <c>load</c> or <c>upgrade</c> is called to initialize the library. <c>unload</c> is called to release the library. All are described individually below.</p> + <p>The fourth argument <c>NULL</c> is ignored. It + was earlier used for the deprectated <c>reload</c> callback + which is no longer supported since OTP 20.</p> <p>If compiling a NIF for static inclusion through <c>--enable-static-nifs</c>, you must define <c>STATIC_ERLANG_NIF</c> before the <c>ERL_NIF_INIT</c> declaration.</p> @@ -522,7 +600,7 @@ return term;</code> <p><c>load</c> is called when the NIF library is loaded and no previously loaded library exists for this module.</p> <p><c>*priv_data</c> can be set to point to some private data - that the library needs to keep a state between NIF + if the library needs to keep a state between NIF calls. <c>enif_priv_data</c> returns this pointer. <c>*priv_data</c> is initialized to <c>NULL</c> when <c>load</c> is called.</p> @@ -539,7 +617,7 @@ return term;</code> and there is old code of this module with a loaded NIF library.</p> <p>Works as <c>load</c>, except that <c>*old_priv_data</c> already contains the value set by the last call to <c>load</c> or - <c>reload</c> for the old module code. <c>*priv_data</c> is + <c>upgrade</c> for the old module code. <c>*priv_data</c> is initialized to <c>NULL</c> when <c>upgrade</c> is called. It is allowed to write to both <c>*priv_data</c> and <c>*old_priv_data.</c></p> @@ -551,27 +629,7 @@ return term;</code> <item> <p><c>unload</c> is called when the module code that the NIF library belongs to is purged as old. New code of the same - module may or may not exist. Notice that <c>unload</c> is not - called for a replaced library as a consequence of <c>reload</c>.</p> - </item> - <tag><marker id="reload"/><c>int (*reload)(ErlNifEnv* env, void** - priv_data, ERL_NIF_TERM load_info)</c></tag> - <item> - <note> - <p><em>The reload mechanism is deprecated.</em> It was only intended - as a development feature. Do not use it as an upgrade method for - live production systems. It can be removed in future releases. - Ensure to pass <c>reload</c> as <c>NULL</c> to - <seealso marker="#ERL_NIF_INIT"><c>ERL_NIF_INIT</c></seealso> - to disable it when not used.</p> - </note> - <p><c>reload</c> is called when the NIF library is loaded and a - previously loaded library already exists for this module code.</p> - <p>Works as <c>load</c>, except that - <c>*priv_data</c> already contains the value set by the - previous call to <c>load</c> or <c>reload</c>.</p> - <p>The library fails to load if <c>reload</c> returns - anything other than <c>0</c> or if <c>reload</c> is <c>NULL</c>.</p> + module may or may not exist.</p> </item> </taglist> </section> @@ -659,9 +717,6 @@ typedef struct { <p><c>flags</c> can be used to indicate that the NIF is a <seealso marker="#dirty_nifs">dirty NIF</seealso> that is to be executed on a dirty scheduler thread.</p> - <p><em>The dirty NIF functionality described here is - experimental.</em> You have to enable support for dirty - schedulers when building OTP to try out the functionality.</p> <p>If the dirty NIF is expected to be CPU-bound, its <c>flags</c> field is to be set to <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c> or <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c>.</p> @@ -695,6 +750,18 @@ typedef struct { <p>When receiving data from untrusted sources, use option <c>ERL_NIF_BIN2TERM_SAFE</c>.</p> </item> + <tag><marker id="ErlNifMonitor"/><c>ErlNifMonitor</c></tag> + <item> + <p>This is an opaque data type that identifies a monitor.</p> + <p>The nif writer is to provide the memory for storing the + monitor when calling <seealso marker="#enif_monitor_process"> + <c>enif_monitor_process</c></seealso>. The + address of the data is not stored by the runtime system, so + <c>ErlNifMonitor</c> can be used as any other data, it + can be copied, moved in memory, forgotten, and so on. + To compare two monitors, <seealso marker="#enif_compare_monitors"> + <c>enif_compare_monitors</c></seealso> must be used.</p> + </item> <tag><marker id="ErlNifPid"/><c>ErlNifPid</c></tag> <item> <p>A process identifier (pid). In contrast to pid terms (instances of @@ -716,11 +783,47 @@ typedef struct { Each resource type has a unique name and a destructor function that is called when objects of its type are released.</p> </item> + <tag><marker id="ErlNifResourceTypeInit"/><c>ErlNifResourceTypeInit</c></tag> + <item> + <code type="none"> +typedef struct { + ErlNifResourceDtor* dtor; + ErlNifResourceStop* stop; + ErlNifResourceDown* down; +} ErlNifResourceTypeInit;</code> + <p>Initialization structure read by <seealso marker="#enif_open_resource_type_x"> + enif_open_resource_type_x</seealso>.</p> + </item> <tag><marker id="ErlNifResourceDtor"/><c>ErlNifResourceDtor</c></tag> <item> <code type="none"> typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj);</code> <p>The function prototype of a resource destructor function.</p> + <p>The <c>obj</c> argument is a pointer to the resource. The only + allowed use for the resource in the destructor is to access its + user data one final time. The destructor is guaranteed to be the + last callback before the resource is deallocated.</p> + </item> + <tag><marker id="ErlNifResourceDown"/><c>ErlNifResourceDown</c></tag> + <item> + <code type="none"> +typedef void ErlNifResourceDown(ErlNifEnv* env, void* obj, const ErlNifPid* pid, const ErlNifMonitor* mon);</code> + <p>The function prototype of a resource down function, + called on the behalf of <seealso marker="#enif_monitor_process"> + enif_monitor_process</seealso>. <c>obj</c> is the resource, <c>pid</c> + is the identity of the monitored process that is exiting, and <c>mon</c> + is the identity of the monitor. + </p> + </item> + <tag><marker id="ErlNifResourceStop"/><c>ErlNifResourceStop</c></tag> + <item> + <code type="none"> +typedef void ErlNifResourceStop(ErlNifEnv* env, void* obj, ErlNifEvent event, int is_direct_call);</code> + <p>The function prototype of a resource stop function, + called on the behalf of <seealso marker="#enif_select"> + enif_select</seealso>. <c>obj</c> is the resource, <c>event</c> is OS event, + <c>is_direct_call</c> is true if the call is made directly from <c>enif_select</c> + or false if it is a scheduled call (potentially from another thread).</p> </item> <tag><marker id="ErlNifCharEncoding"/><c>ErlNifCharEncoding</c></tag> <item> @@ -786,6 +889,59 @@ typedef enum { </item> </taglist> </item> + <tag><marker id="ErlNifHash"/><c>ErlNifHash</c></tag> + <item> + <p>An enumeration of the supported hash types that can be generated + using <seealso marker="#enif_hash"><c>enif_hash</c></seealso>. + </p> + <taglist> + <tag><c>ERL_NIF_INTERNAL_HASH</c></tag> + <item> + <p>Non-portable hash function that only guarantees the same hash + for the same term within one Erlang VM instance.</p> + <p>It takes 32-bit salt values and generates hashes within <c>0..2^32-1</c>.</p> + </item> + <tag><c>ERL_NIF_PHASH2</c></tag> + <item> + <p>Portable hash function that gives the same hash for the + same Erlang term regardless of machine architecture and ERTS version.</p> + <p><em>It ignores salt values</em> and generates hashes within <c>0..2^27-1</c>.</p> + <p>Slower than <c>ERL_NIF_INTERNAL_HASH.</c> + It corresponds to <seealso marker="erlang#phash2-1"><c>erlang:phash2/1</c></seealso>. + </p> + </item> + </taglist> + </item> + <tag><marker id="SysIOVec"/><c>SysIOVec</c></tag> + <item> + <p>A system I/O vector, as used by <c>writev</c> on + Unix and <c>WSASend</c> on Win32. It is used in + <c>ErlNifIOVec</c> and by + <seealso marker="#enif_ioq_peek"><c>enif_ioq_peek</c></seealso>.</p> + </item> + <tag><marker id="ErlNifIOVec"/><c>ErlNifIOVec</c></tag> + <item> + <code type="none"> +typedef struct { + int iovcnt; + size_t size; + SysIOVec* iov; +} ErlNifIOVec;</code> + <p>An I/O vector containing <c>iovcnt</c> <c>SysIOVec</c>s + pointing to the data. It is used by + <seealso marker="#enif_inspect_iovec"> + <c>enif_inspect_iovec</c></seealso> and + <seealso marker="#enif_ioq_enqv"> + <c>enif_ioq_enqv</c></seealso>.</p> + </item> + <tag><marker id="ErlNifIOQueueOpts"/><c>ErlNifIOQueueOpts</c></tag> + <item> + Options to configure a <c>ErlNifIOQueue</c>. + <taglist> + <tag>ERL_NIF_IOQ_NORMAL</tag> + <item><p>Create a normal I/O Queue</p></item> + </taglist> + </item> </taglist> </section> @@ -895,6 +1051,21 @@ typedef enum { </func> <func> + <name><ret>int</ret><nametext>enif_compare_monitors(const ErlNifMonitor + *monitor1, const ErlNifMonitor *monitor2)</nametext></name> + <fsummary>Compare two monitors.</fsummary> + <desc> + <marker id="enif_compare_monitors"></marker> + <p>Compares two <seealso marker="#ErlNifMonitor"><c>ErlNifMonitor</c></seealso>s. + Can also be used to imply some artificial order on monitors, + for whatever reason.</p> + <p>Returns <c>0</c> if <c>monitor1</c> and <c>monitor2</c> are equal, + < <c>0</c> if <c>monitor1</c> < <c>monitor2</c>, and + > <c>0</c> if <c>monitor1</c> > <c>monitor2</c>.</p> + </desc> + </func> + + <func> <name><ret>void</ret> <nametext>enif_cond_broadcast(ErlNifCond *cnd)</nametext></name> <fsummary></fsummary> @@ -1022,6 +1193,30 @@ typedef enum { </func> <func> + <name><ret>int</ret><nametext>enif_demonitor_process(ErlNifEnv* env, void* obj, + const ErlNifMonitor* mon)</nametext></name> + <fsummary>Cancel a process monitor.</fsummary> + <desc> + <marker id="enif_demonitor_process"></marker> + <p>Cancels a monitor created earlier with <seealso marker="#enif_monitor_process"> + <c>enif_monitor_process</c></seealso>. Argument <c>obj</c> is a pointer + to the resource holding the monitor and <c>*mon</c> identifies the monitor.</p> + <p>Returns <c>0</c> if the monitor was successfully identified and removed. + Returns a non-zero value if the monitor could not be identified, which means + it was either</p> + <list type="bulleted"> + <item>never created for this resource</item> + <item>already cancelled</item> + <item>already triggered</item> + <item>just about to be triggered by a concurrent thread</item> + </list> + <p>This function is only thread-safe when the emulator with SMP support + is used. It can only be used in a non-SMP emulator from a NIF-calling + thread.</p> + </desc> + </func> + + <func> <name><ret>int</ret> <nametext>enif_equal_tids(ErlNifTid tid1, ErlNifTid tid2)</nametext> </name> @@ -1053,6 +1248,31 @@ typedef enum { </func> <func> + <name><ret>void</ret> + <nametext>enif_free_iovec(ErlNifIOvec* iov)</nametext></name> + <fsummary>Free an ErlIOVec</fsummary> + <desc> + <p>Frees an io vector returned from + <seealso marker="#enif_inspect_iovec"> + <c>enif_inspect_iovec</c></seealso>. + This is needed only if a <c>NULL</c> environment is passed to + <seealso marker="#enif_inspect_iovec"> + <c>enif_inspect_iovec</c></seealso>.</p> + <code type="none"><![CDATA[ +ErlNifIOVec *iovec = NULL; +size_t max_elements = 128; +ERL_NIF_TERM tail; +if (!enif_inspect_iovec(NULL, max_elements, term, &tail, iovec)) + return 0; + +// Do things with the iovec + +/* Free the iovector, possibly in another thread or nif function call */ +enif_free_iovec(iovec);]]></code> + </desc> + </func> + + <func> <name><ret>int</ret><nametext>enif_get_atom(ErlNifEnv* env, ERL_NIF_TERM term, char* buf, unsigned size, ErlNifCharEncoding encode)</nametext> </name> @@ -1306,13 +1526,12 @@ typedef enum { <p>Returns <c>true</c> if a pending exception is associated with the environment <c>env</c>. If <c>reason</c> is a <c>NULL</c> pointer, ignore it. Otherwise, if a pending exception associated with - <c>env</c> exists, set <c>ERL_NIF_TERM</c> to which <c>reason</c> - points to the value of the exception's term. For example, if - <seealso marker="#enif_make_badarg"> + <c>env</c> exists, set <c>*reason</c> to the value of the exception + term. For example, if <seealso marker="#enif_make_badarg"> <c>enif_make_badarg</c></seealso> is called to set a pending <c>badarg</c> exception, a later call to <c>enif_has_pending_exception(env, &reason)</c> sets - <c>reason</c> to the atom <c>badarg</c>, then return <c>true</c>.</p> + <c>*reason</c> to the atom <c>badarg</c>, then return <c>true</c>.</p> <p>See also <seealso marker="#enif_make_badarg"> <c>enif_make_badarg</c></seealso> and <seealso marker="#enif_raise_exception"> @@ -1321,6 +1540,19 @@ typedef enum { </func> <func> + <name> + <ret>ErlNifUInt64</ret> + <nametext>enif_hash(ErlNifHash type, ERL_NIF_TERM term, ErlNifUInt64 salt)</nametext> + </name> + <fsummary>Hash terms.</fsummary> + <desc> + <p>Hashes <c>term</c> according to the specified + <seealso marker="#ErlNifHash"><c>ErlNifHash</c></seealso> <c>type</c>.</p> + <p>Ranges of taken salt (if any) and returned value depend on the hash type.</p> + </desc> + </func> + + <func> <name><ret>int</ret><nametext>enif_inspect_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, ErlNifBinary* bin)</nametext></name> <fsummary>Inspect the content of a binary.</fsummary> @@ -1347,6 +1579,127 @@ typedef enum { </func> <func> + <name><ret>int</ret><nametext>enif_inspect_iovec(ErlNifEnv* + env, size_t max_elements, ERL_NIF_TERM iovec_term, ERL_NIF_TERM* tail, + ErlNifIOVec** iovec)</nametext></name> + <fsummary>Inspect a list of binaries as an ErlNifIOVec.</fsummary> + <desc> + <p>Fills <c>iovec</c> with the list of binaries provided in + <c>iovec_term</c>. The number of elements handled in the call is + limited to <c>max_elements</c>, and <c>tail</c> is set to the + remainder of the list. Note that the output may be longer than + <c>max_elements</c> on some platforms. + </p> + <p>To create a list of binaries from an arbitrary iolist, use + <seealso marker="erts:erlang#iolist_to_iovec/1"> + <c>erlang:iolist_to_iovec/1</c></seealso>.</p> + <p>When calling this function, <c>iovec</c> should contain a pointer to + <c>NULL</c> or a ErlNifIOVec structure that should be used if + possible. e.g. + </p> + <code type="none"> +/* Don't use a pre-allocated structure */ +ErlNifIOVec *iovec = NULL; +enif_inspect_iovec(env, max_elements, term, &tail, &iovec); + +/* Use a stack-allocated vector as an optimization for vectors with few elements */ +ErlNifIOVec vec, *iovec = &vec; +enif_inspect_iovec(env, max_elements, term, &tail, &iovec); +</code> + <p>The contents of the <c>iovec</c> is valid until the called nif + function returns. If the <c>iovec</c> should be valid after the nif + call returns, it is possible to call this function with a + <c>NULL</c> environment. If no environment is given the <c>iovec</c> + owns the data in the vector and it has to be explicitly freed using + <seealso marker="#enif_free_iovec"><c>enif_free_iovec</c> + </seealso>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>iovec_term</c> + not an iovec.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifIOQueue *</ret> + <nametext>enif_ioq_create(ErlNifIOQueueOpts opts)</nametext></name> + <fsummary>Create a new IO Queue</fsummary> + <desc> + <p>Create a new I/O Queue that can be used to store data. + <c>opts</c> has to be set to <c>ERL_NIF_IOQ_NORMAL</c>. + </p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_ioq_destroy(ErlNifIOQueue *q)</nametext></name> + <fsummary>Destroy an IO Queue and free it's content</fsummary> + <desc> + <p>Destroy the I/O queue and free all of it's contents</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_ioq_deq(ErlNifIOQueue *q, size_t count, size_t *size)</nametext></name> + <fsummary>Dequeue count bytes from the IO Queue</fsummary> + <desc> + <p>Dequeue <c>count</c> bytes from the I/O queue. + If <c>size</c> is not <c>NULL</c>, the new size of the queue + is placed there.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if the I/O does + not contain <c>count</c> bytes. On failure the queue is left un-altered.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_ioq_enq_binary(ErlNifIOQueue *q, ErlNifBinary *bin, size_t skip)</nametext></name> + <fsummary>Enqueue the binary into the IO Queue</fsummary> + <desc> + <p>Enqueue the <c>bin</c> into <c>q</c> skipping the first <c>skip</c> bytes.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>skip</c> is greater + than the size of <c>bin</c>. Any ownership of the binary data is transferred + to the queue and <c>bin</c> is to be considered read-only for the rest of the NIF + call and then as released.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_ioq_enqv(ErlNifIOQueue *q, ErlNifIOVec *iovec, size_t skip)</nametext></name> + <fsummary>Enqueue the iovec into the IO Queue</fsummary> + <desc> + <p>Enqueue the <c>iovec</c> into <c>q</c> skipping the first <c>skip</c> bytes.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>skip</c> is greater + than the size of <c>iovec</c>.</p> + </desc> + </func> + + <func> + <name><ret>SysIOVec *</ret> + <nametext>enif_ioq_peek(ErlNifIOQueue *q, int *iovlen)</nametext></name> + <fsummary>Peek inside the IO Queue</fsummary> + <desc> + <p>Get the I/O queue as a pointer to an array of <c>SysIOVec</c>s. + It also returns the number of elements in <c>iovlen</c>. + This is the only way to get data out of the queue.</p> + <p>Nothing is removed from the queue by this function, that must be done + with <seealso marker="#enif_ioq_deq"><c>enif_ioq_deq</c></seealso>.</p> + <p>The returned array is suitable to use with the Unix system + call <c>writev</c>.</p> + </desc> + </func> + + <func> + <name><ret>size_t</ret> + <nametext>enif_ioq_size(ErlNifIOQueue *q)</nametext></name> + <fsummary>Get the current size of the IO Queue</fsummary> + <desc> + <p>Get the size of <c>q</c>.</p> + </desc> + </func> + + <func> <name><ret>int</ret> <nametext>enif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term)</nametext> </name> @@ -1850,10 +2203,33 @@ typedef enum { details, see the <seealso marker="#enif_resource_example">example of creating and returning a resource object</seealso> in the User's Guide.</p> - <p>Notice that the only defined behavior of using a resource term in - an Erlang program is to store it and send it between processes on the - same node. Other operations, such as matching or - <c>term_to_binary</c>, have unpredictable (but harmless) results.</p> + <note> + <p>Since ERTS 9.0 (OTP-20.0), resource terms have a defined behavior + when compared and serialized through <c>term_to_binary</c> or passed + between nodes.</p> + <list type="bulleted"> + <item> + <p>Two resource terms will compare equal iff they + would yield the same resource object pointer when passed to + <seealso marker="#enif_get_resource"><c>enif_get_resource</c></seealso>.</p> + </item> + <item> + <p>A resoure term can be serialized with <c>term_to_binary</c> and later + be fully recreated if the resource object is still alive when + <c>binary_to_term</c> is called. A <em>stale</em> resource term will be + returned from <c>binary_to_term</c> if the resource object has + been deallocated. <seealso marker="#enif_get_resource"><c>enif_get_resource</c></seealso> + will return false for stale resource terms.</p> + <p>The same principles of serialization apply when passing + resource terms in messages to remote nodes and back again. A + resource term will act stale on all nodes except the node where + its resource object is still alive in memory.</p> + </item> + </list> + <p>Before ERTS 9.0 (OTP-20.0), all resource terms did + compare equal to each other and to empty binaries (<c><<>></c>). + If serialized, they would be recreated as plain empty binaries.</p> + </note> </desc> </func> @@ -2137,6 +2513,36 @@ enif_map_iterator_destroy(env, &iter);</code> </func> <func> + <name><ret>int</ret><nametext>enif_monitor_process(ErlNifEnv* env, void* obj, + const ErlNifPid* target_pid, ErlNifMonitor* mon)</nametext></name> + <fsummary>Monitor a process from a resource.</fsummary> + <desc> + <marker id="enif_monitor_process"></marker> + <p>Starts monitoring a process from a resource. When a process is + monitored, a process exit results in a call to the provided + <seealso marker="#ErlNifResourceDown"> + <c>down</c></seealso> callback associated with the resource type.</p> + <p>Argument <c>obj</c> is pointer to the resource to hold the monitor and + <c>*target_pid</c> identifies the local process to be monitored.</p> + <p>If <c>mon</c> is not <c>NULL</c>, a successful call stores the + identity of the monitor in the + <seealso marker="#ErlNifMonitor"><c>ErlNifMonitor</c></seealso> + struct pointed to by <c>mon</c>. This identifier is used to refer to the + monitor for later removal with + <seealso marker="#enif_demonitor_process"><c>enif_demonitor_process</c></seealso> + or compare with + <seealso marker="#enif_compare_monitors"><c>enif_compare_monitors</c></seealso>. + A monitor is automatically removed when it triggers or when + the resource is deallocated.</p> + <p>Returns <c>0</c> on success, < 0 if no <c>down</c> callback is + provided, and > 0 if the process is no longer alive.</p> + <p>This function is only thread-safe when the emulator with SMP support + is used. It can only be used in a non-SMP emulator from a NIF-calling + thread.</p> + </desc> + </func> + + <func> <name><ret>ErlNifTime</ret> <nametext>enif_monotonic_time(ErlNifTimeUnit time_unit)</nametext> </name> @@ -2249,10 +2655,30 @@ enif_map_iterator_destroy(env, &iter);</code> returns <c>NULL</c> and sets <c>*tried</c> to <c>flags</c>. It is allowed to set <c>tried</c> to <c>NULL</c>.</p> <p>Notice that <c>enif_open_resource_type</c> is only allowed to be - called in the three callbacks - <seealso marker="#load"><c>load</c></seealso>, - <seealso marker="#reload"><c>reload</c></seealso>, and + called in the two callbacks + <seealso marker="#load"><c>load</c></seealso> and <seealso marker="#upgrade"><c>upgrade</c></seealso>.</p> + <p>See also <seealso marker="#enif_open_resource_type_x"> + <c>enif_open_resource_type_x</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifResourceType *</ret> + <nametext>enif_open_resource_type_x(ErlNifEnv* env, const char* name, + const ErlNifResourceTypeInit* init, + ErlNifResourceFlags flags, ErlNifResourceFlags* tried)</nametext> + </name> + <fsummary>Create or takeover a resource type.</fsummary> + <desc> + <p>Same as <seealso marker="#enif_open_resource_type"><c>enif_open_resource_type</c></seealso> + except it accepts additional callback functions for resource types that are + used together with <seealso marker="#enif_select"><c>enif_select</c></seealso> + and <seealso marker="#enif_monitor_process"><c>enif_monitor_process</c></seealso>.</p> + <p>Argument <c>init</c> is a pointer to an + <seealso marker="#ErlNifResourceTypeInit"><c>ErlNifResourceTypeInit</c></seealso> + structure that contains the function pointers for destructor, down and stop callbacks + for the resource type.</p> </desc> </func> @@ -2305,10 +2731,8 @@ enif_map_iterator_destroy(env, &iter);</code> <fsummary>Get the private data of a NIF library.</fsummary> <desc> <p>Returns the pointer to the private data that was set by - <seealso marker="#load"><c>load</c></seealso>, - <seealso marker="#reload"><c>reload</c></seealso>, or + <seealso marker="#load"><c>load</c></seealso> or <seealso marker="#upgrade"><c>upgrade</c></seealso>.</p> - <p>Was previously named <c>enif_get_data</c>.</p> </desc> </func> @@ -2365,7 +2789,7 @@ enif_map_iterator_destroy(env, &iter);</code> <nametext>enif_release_resource(void* obj)</nametext></name> <fsummary>Release a resource object.</fsummary> <desc> - <p>Removes a reference to resource object <c>obj</c>obtained from + <p>Removes a reference to resource object <c>obj</c> obtained from <seealso marker="#enif_alloc_resource"> <c>enif_alloc_resource</c></seealso>. The resource object is destructed when the last reference is removed. @@ -2470,9 +2894,6 @@ enif_map_iterator_destroy(env, &iter);</code> application to break up long-running work into multiple regular NIF calls or to schedule a <seealso marker="#dirty_nifs"> dirty NIF</seealso> to execute on a dirty scheduler thread.</p> - <p><em>The dirty NIF functionality described here is - experimental.</em> You have to enable support for dirty - schedulers when building OTP to try out the functionality.</p> <taglist> <tag><c>fun_name</c></tag> <item> @@ -2483,13 +2904,13 @@ enif_map_iterator_destroy(env, &iter);</code> <tag><c>flags</c></tag> <item> <p>Must be set to <c>0</c> for a regular NIF. If the emulator was - built with the experimental dirty scheduler support enabled, + built with dirty scheduler support enabled, <c>flags</c> can be set to either <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c> if the job is expected to be CPU-bound, or <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c> for jobs that will be I/O-bound. If dirty scheduler threads are not available in the emulator, an attempt to schedule such a job - results in a <c>badarg</c> exception.</p> + results in a <c>notsup</c> exception.</p> </item> <tag><c>argc</c> and <c>argv</c></tag> <item> @@ -2508,6 +2929,100 @@ enif_map_iterator_destroy(env, &iter);</code> </func> <func> + <name><ret>int</ret> + <nametext>enif_select(ErlNifEnv* env, ErlNifEvent event, enum ErlNifSelectFlags mode, + void* obj, const ErlNifPid* pid, ERL_NIF_TERM ref)</nametext> + </name> + <fsummary>Manage subscription on IO event.</fsummary> + <desc> + <p>This function can be used to receive asynchronous notifications + when OS-specific event objects become ready for either read or write operations.</p> + <p>Argument <c>event</c> identifies the event object. On Unix + systems, the functions <c>select</c>/<c>poll</c> are used. The event + object must be a socket, pipe or other file descriptor object that + <c>select</c>/<c>poll</c> can use.</p> + <p>Argument <c>mode</c> describes the type of events to wait for. It can be + <c>ERL_NIF_SELECT_READ</c>, <c>ERL_NIF_SELECT_WRITE</c> or a bitwise + OR combination to wait for both. It can also be <c>ERL_NIF_SELECT_STOP</c> + which is described further below. When a read or write event is triggerred, + a notification message like this is sent to the process identified by + <c>pid</c>:</p> + <code type="none">{select, Obj, Ref, ready_input | ready_output}</code> + <p><c>ready_input</c> or <c>ready_output</c> indicates if the event object + is ready for reading or writing.</p> + <p>Argument <c>pid</c> may be <c>NULL</c> to indicate the calling process.</p> + <p>Argument <c>obj</c> is a resource object obtained from + <seealso marker="#enif_alloc_resource"><c>enif_alloc_resource</c></seealso>. + The purpose of the resource objects is as a container of the event object + to manage its state and lifetime. A handle to the resource is received + in the notification message as <c>Obj</c>.</p> + <p>Argument <c>ref</c> must be either a reference obtained from + <seealso marker="erlang#make_ref-0"><c>erlang:make_ref/0</c></seealso> + or the atom <c>undefined</c>. It will be passed as <c>Ref</c> in the notifications. + If a selective <c>receive</c> statement is used to wait for the notification + then a reference created just before the <c>receive</c> will exploit a runtime + optimization that bypasses all earlier received messages in the queue.</p> + <p>The notifications are one-shot only. To receive further notifications of the same + type (read or write), repeated calls to <c>enif_select</c> must be made + after receiving each notification.</p> + <p>Use <c>ERL_NIF_SELECT_STOP</c> as <c>mode</c> in order to safely + close an event object that has been passed to <c>enif_select</c>. The + <seealso marker="#ErlNifResourceStop"><c>stop</c></seealso> callback + of the resource <c>obj</c> will be called when it is safe to close + the event object. This safe way of closing event objects must be used + even if all notifications have been received and no further calls to + <c>enif_select</c> have been made.</p> + <p>The first call to <c>enif_select</c> for a specific OS <c>event</c> will establish + a relation between the event object and the containing resource. All subsequent calls + for an <c>event</c> must pass its containing resource as argument + <c>obj</c>. The relation is dissolved when <c>enif_select</c> has + been called with <c>mode</c> as <c>ERL_NIF_SELECT_STOP</c> and the + corresponding <c>stop</c> callback has returned. A resource can contain + several event objects but one event object can only be contained within + one resource. A resource will not be destructed until all its contained relations + have been dissolved.</p> + <note> + <p>Use <seealso marker="#enif_monitor_process"><c>enif_monitor_process</c></seealso> + together with <c>enif_select</c> to detect failing Erlang + processes and prevent them from causing permanent leakage of resources + and their contained OS event objects.</p> + </note> + <p>Returns a non-negative value on success where the following bits can be set:</p> + <taglist> + <tag><c>ERL_NIF_SELECT_STOP_CALLED</c></tag> + <item>The stop callback was called directly by <c>enif_select</c>.</item> + <tag><c>ERL_NIF_SELECT_STOP_SCHEDULED</c></tag> + <item>The stop callback was scheduled to run on some other thread + or later by this thread.</item> + </taglist> + <p>Returns a negative value if the call failed where the follwing bits can be set:</p> + <taglist> + <tag><c>ERL_NIF_SELECT_INVALID_EVENT</c></tag> + <item>Argument <c>event</c> is not a valid OS event object.</item> + <tag><c>ERL_NIF_SELECT_FAILED</c></tag> + <item>The system call failed to add the event object to the poll set.</item> + </taglist> + <note> + <p>Use bitwise AND to test for specific bits in the return vaue. + New significant bits may be added in future releases to give more detailed + information for both failed and successful calls. Do NOT use equallity tests + like <c>==</c>, as that may cause your application to stop working.</p> + <p>Example:</p> + <code type="none"> +retval = enif_select(env, fd, ERL_NIF_SELECT_STOP, resource, ref); +if (retval < 0) { + /* handle error */ +} +/* Success! */ +if (retval & ERL_NIF_SELECT_STOP_CALLED) { + /* ... */ +} +</code> + </note> + </desc> + </func> + + <func> <name><ret>ErlNifPid *</ret> <nametext>enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)</nametext> </name> @@ -2761,6 +3276,63 @@ enif_map_iterator_destroy(env, &iter);</code> <c>erl_drv_tsd_set</c></seealso>.</p> </desc> </func> + + <func> + <name><ret>int</ret> + <nametext>enif_whereis_pid(ErlNifEnv *env, + ERL_NIF_TERM name, ErlNifPid *pid)</nametext></name> + <fsummary>Looks up a process by its registered name.</fsummary> + <desc> + <p>Looks up a process by its registered name.</p> + <taglist> + <tag><c>env</c></tag> + <item>The environment of the calling process. Must be <c>NULL</c> + only if calling from a created thread.</item> + <tag><c>name</c></tag> + <item>The name of a registered process, as an atom.</item> + <tag><c>*pid</c></tag> + <item>The <seealso marker="#ErlNifPid"><c>ErlNifPid</c></seealso> + in which the resolved process id is stored.</item> + </taglist> + <p>On success, sets <c>*pid</c> to the local process registered with + <c>name</c> and returns <c>true</c>. If <c>name</c> is not a + registered process, or is not an atom, <c>false</c> is returned and + <c>*pid</c> is unchanged.</p> + <p>Works as <seealso marker="erlang#whereis-1"> + <c>erlang:whereis/1</c></seealso>, but restricted to processes. See + <seealso marker="#enif_whereis_port"><c>enif_whereis_port</c></seealso> + to resolve registered ports.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_whereis_port(ErlNifEnv *env, + ERL_NIF_TERM name, ErlNifPort *port)</nametext></name> + <fsummary>Looks up a port by its registered name.</fsummary> + <desc> + <p>Looks up a port by its registered name.</p> + <taglist> + <tag><c>env</c></tag> + <item>The environment of the calling process. Must be <c>NULL</c> + only if calling from a created thread.</item> + <tag><c>name</c></tag> + <item>The name of a registered port, as an atom.</item> + <tag><c>*port</c></tag> + <item>The <seealso marker="#ErlNifPort"><c>ErlNifPort</c></seealso> + in which the resolved port id is stored.</item> + </taglist> + <p>On success, sets <c>*port</c> to the port registered with + <c>name</c> and returns <c>true</c>. If <c>name</c> is not a + registered port, or is not an atom, <c>false</c> is returned and + <c>*port</c> is unchanged.</p> + <p>Works as <seealso marker="erlang#whereis-1"> + <c>erlang:whereis/1</c></seealso>, but restricted to ports. See + <seealso marker="#enif_whereis_pid"><c>enif_whereis_pid</c></seealso> + to resolve registered processes.</p> + </desc> + </func> + </funcs> <section> diff --git a/erts/doc/src/erl_tracer.xml b/erts/doc/src/erl_tracer.xml index 83eef374ca..fd3c17f337 100644 --- a/erts/doc/src/erl_tracer.xml +++ b/erts/doc/src/erl_tracer.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2016</year><year>2016</year> + <year>2016</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -103,7 +103,7 @@ <item>If set the tracer has been requested to include a time stamp.</item> <tag><c>extra</c></tag> - <item>If set the tracepoint has included additonal data about + <item>If set the tracepoint has included additional data about the trace event. What the additional data is depends on which <c>TraceTag</c> has been triggered. The <c>extra</c> trace data corresponds to the fifth element in the trace tuples described in @@ -653,7 +653,7 @@ ok <0.37.0> 3> erlang:trace(new, true, [send,{tracer, erl_msg_tracer, Tracer}]). 0 -{<0.39.0>,<0.27.0>} +{trace,<0.39.0>,<0.27.0>} 4> {ok, D} = file:open("/tmp/tmp.data",[write]). {trace,#Port<0.486>,<0.40.0>} {trace,<0.40.0>,<0.21.0>} @@ -684,7 +684,7 @@ trace(_, _, _, _, _) -> <p><c>erl_msg_tracer.c</c>:</p> <pre> -#include "erl_nif.h" +#include <erl_nif.h> /* NIF interface declarations */ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); @@ -758,18 +758,21 @@ static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) /* * argv[0]: TraceTag, should only be 'send' - * argv[1]: TracerState, process to send {argv[2], argv[4]} to + * argv[1]: TracerState, process to send {Tracee, Recipient} to * argv[2]: Tracee - * argv[3]: Recipient - * argv[4]: Options, ignored + * argv[3]: Message + * argv[4]: Options, map containing Recipient */ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifPid to_pid; + ERL_NIF_TERM recipient, msg; if (enif_get_local_pid(env, argv[1], &to_pid)) { - ERL_NIF_TERM msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], argv[4]); + if (enif_get_map_value(env, argv[4], enif_make_atom(env, "extra"), &recipient)) { + msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], recipient); enif_send(env, &to_pid, NULL, msg); + } } return enif_make_atom(env, "ok"); diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 24a091073d..5afac46d21 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -60,6 +60,14 @@ </desc> </datatype> <datatype> + <name>iovec()</name> + <desc> + <p>A list of binaries. This datatype is useful to use + together with <seealso marker="erl_nif#enif_inspect_iovec"> + <c>enif_inspect_iovec</c></seealso>.</p> + </desc> + </datatype> + <datatype> <name name="message_queue_data"></name> <desc> <p>See <seealso marker="#process_flag_message_queue_data"> @@ -325,16 +333,11 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> is <c>latin1</c>, one byte exists for each character in the text representation. If <c><anno>Encoding</anno></c> is <c>utf8</c> or - <c>unicode</c>, the characters are encoded using UTF-8 - (that is, characters from 128 through 255 are - encoded in two bytes).</p> + <c>unicode</c>, the characters are encoded using UTF-8 where + characters may require multiple bytes.</p> <note> - <p><c>atom_to_binary(<anno>Atom</anno>, latin1)</c> never - fails, as the text representation of an atom can only - contain characters from 0 through 255. In a future release, - the text representation - of atoms can be allowed to contain any Unicode character and - <c>atom_to_binary(<anno>Atom</anno>, latin1)</c> then fails if the + <p>As from Erlang/OTP 20, atoms can contain any Unicode character + and <c>atom_to_binary(<anno>Atom</anno>, latin1)</c> may fail if the text representation for <c><anno>Atom</anno></c> contains a Unicode character > 255.</p> </note> @@ -402,13 +405,11 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> translation of bytes in the binary is done. If <c><anno>Encoding</anno></c> is <c>utf8</c> or <c>unicode</c>, the binary must contain - valid UTF-8 sequences. Only Unicode characters up - to 255 are allowed.</p> + valid UTF-8 sequences.</p> <note> - <p><c>binary_to_atom(<anno>Binary</anno>, utf8)</c> fails if - the binary contains Unicode characters > 255. - In a future release, such Unicode characters can be allowed and - <c>binary_to_atom(<anno>Binary</anno>, utf8)</c> does then not fail. + <p>As from Erlang/OTP 20, <c>binary_to_atom(<anno>Binary</anno>, utf8)</c> + is capable of encoding any Unicode character. Earlier versions would + fail if the binary contained Unicode characters > 255. For more information about Unicode support in atoms, see the <seealso marker="erl_ext_dist#utf8_atoms">note on UTF-8 encoded atoms</seealso> @@ -419,9 +420,7 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> > <input>binary_to_atom(<<"Erlang">>, latin1).</input> 'Erlang' > <input>binary_to_atom(<<1024/utf8>>, utf8).</input> -** exception error: bad argument - in function binary_to_atom/2 - called as binary_to_atom(<<208,128>>,utf8)</pre> +'Ѐ'</pre> </desc> </func> @@ -733,6 +732,19 @@ hello </func> <func> + <name name="ceil" arity="1"/> + <fsummary>Returns the smallest integer not less than the argument</fsummary> + <desc> + <p>Returns the smallest integer not less than + <c><anno>Number</anno></c>. + For example:</p> + <pre> +> <input>ceil(5.5).</input> +6</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> <name name="check_old_code" arity="1"/> <fsummary>Check if a module has old code.</fsummary> <desc> @@ -1480,6 +1492,20 @@ true</pre> </func> <func> + <name name="floor" arity="1"/> + <fsummary>Returns the largest integer not greater than the argument</fsummary> + <desc> + <p>Returns the largest integer not greater than + <c><anno>Number</anno></c>. + For example:</p> + <pre> +> <input>floor(-10.5).</input> +-11</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + + <func> <name name="fun_info" arity="1"/> <fsummary>Information about a fun.</fsummary> <desc> @@ -1667,6 +1693,12 @@ true</pre> the form <c>{garbage_collect, <anno>RequestId</anno>, <anno>GCResult</anno>}</c>. </item> + + <tag><c>{type, 'major' | 'minor'}</c></tag> + <item>Triggers garbage collection of requested type. Default value is + <c>'major'</c>, which would trigger a fullsweep GC. + The option <c>'minor'</c> is considered a hint and may lead to + either minor or major GC run.</item> </taglist> <p>If <c><anno>Pid</anno></c> equals <c>self()</c>, and no <c>async</c> option has been passed, the garbage @@ -1789,8 +1821,9 @@ true</pre> <fsummary>Get the call stack back-trace of the last exception.</fsummary> <type name="stack_item"/> <desc> - <p>Gets the call stack back-trace (<em>stacktrace</em>) of the - last exception in the calling process as a list of + <p>Gets the call stack back-trace (<em>stacktrace</em>) for an + exception that has just been caught + in the calling process as a list of <c>{<anno>Module</anno>,<anno>Function</anno>,<anno>Arity</anno>,<anno>Location</anno>}</c> tuples. Field <c><anno>Arity</anno></c> in the first tuple can be the argument list of that function call instead of an arity integer, @@ -1798,6 +1831,29 @@ true</pre> <p>If there has not been any exceptions in a process, the stacktrace is <c>[]</c>. After a code change for the process, the stacktrace can also be reset to <c>[]</c>.</p> + <p><c>erlang:get_stacktrace/0</c> is only guaranteed to return + a stacktrace if called (directly or indirectly) from within the + scope of a <c>try</c> expression. That is, the following call works:</p> +<pre> +try Expr +catch + C:R -> + {C,R,erlang:get_stacktrace()} +end</pre> + <p>As does this call:</p> +<pre> +try Expr +catch + C:R -> + {C,R,helper()} +end + +helper() -> + erlang:get_stacktrace().</pre> + + <warning><p>In a future release, + <c>erlang:get_stacktrace/0</c> will return <c>[]</c> if called + from outside a <c>try</c> expression.</p></warning> <p>The stacktrace is the same data as operator <c>catch</c> returns, for example:</p> <pre> @@ -1895,23 +1951,26 @@ os_prompt%</pre> <item>The runtime system exits with integer value <c><anno>Status</anno></c> as status code to the calling environment (OS). + <note> + <p>On many platforms, the OS supports only status + codes 0-255. A too large status code is truncated by clearing + the high bits.</p> + </note> </item> <tag>string()</tag> <item>An Erlang crash dump is produced with <c><anno>Status</anno></c> as slogan. Then the runtime system exits with status code <c>1</c>. - Note that only code points in the range 0-255 may be used - and the string will be truncated if longer than 200 characters. + The string will be truncated if longer than 200 characters. + <note> + <p>Before ERTS 9.1 (OTP-20.1) only code points in the range 0-255 + was accepted in the string. Now any unicode string is valid.</p> + </note> </item> <tag><c>abort</c></tag> <item>The runtime system aborts producing a core dump, if that is enabled in the OS. </item> </taglist> - <note> - <p>On many platforms, the OS supports only status - codes 0-255. A too large status code is truncated by clearing - the high bits.</p> - </note> <p>For integer <c><anno>Status</anno></c>, the Erlang runtime system closes all ports and allows async threads to finish their operations before exiting. To exit without such flushing, use @@ -1922,26 +1981,6 @@ os_prompt%</pre> </func> <func> - <name name="hash" arity="2"/> - <fsummary>Hash function (deprecated).</fsummary> - <desc> - <p>Returns a hash value for <c><anno>Term</anno></c> within the range - <c>1..<anno>Range</anno></c>. The maximum range is 1..2^27-1.</p> - <warning> - <p><em>This BIF is deprecated, as the hash value can differ on - different architectures.</em> The hash values for integer - terms > 2^27 and large binaries are - poor. The BIF is retained for backward compatibility - reasons (it can have been used to hash records into a file), - but all new code is to use one of the BIFs - <seealso marker="#phash/2"><c>erlang:phash/2</c></seealso> or - <seealso marker="#phash2/1"><c>erlang:phash2/1,2</c></seealso> - instead.</p> - </warning> - </desc> - </func> - - <func> <name name="hd" arity="1"/> <fsummary>Head of a list.</fsummary> <desc> @@ -2097,6 +2136,15 @@ os_prompt%</pre> </func> <func> + <name name="iolist_to_iovec" arity="1"/> + <fsummary>Converts an iolist to a iovec.</fsummary> + <desc> + <p>Returns an iovec that is made from the integers and binaries in + <c><anno>IoListOrBinary</anno></c>.</p> + </desc> + </func> + + <func> <name name="is_alive" arity="0"/> <fsummary>Check whether the local node is alive.</fsummary> <desc> @@ -2368,10 +2416,10 @@ os_prompt%</pre> <desc> <p>Returns the atom whose text representation is <c><anno>String</anno></c>.</p> - <p><c><anno>String</anno></c> can only contain ISO-latin-1 - characters (that is, numbers < 256) as the implementation does not - allow Unicode characters equal to or above 256 in atoms. - For more information on Unicode support in atoms, see + <p>As from Erlang/OTP 20, <c><anno>String</anno></c> may contain + any Unicode character. Earlier versions allowed only ISO-latin-1 + characters as the implementation did not allow Unicode characters + above 255. For more information on Unicode support in atoms, see <seealso marker="erl_ext_dist#utf8_atoms">note on UTF-8 encoded atoms</seealso> in section "External Term Format" in the User's Guide.</p> @@ -2495,6 +2543,42 @@ os_prompt%</pre> </func> <func> + <name name="list_to_port" arity="1"/> + <fsummary>Convert from text representation to a port.</fsummary> + <desc> + <p>Returns a port identifier whose text representation is a + <c><anno>String</anno></c>, for example:</p> + <pre> +> <input>list_to_port("#Port<0.4>").</input> +#Port<0.4></pre> + <p>Failure: <c>badarg</c> if <c><anno>String</anno></c> contains a bad + representation of a port identifier.</p> + <warning> + <p>This BIF is intended for debugging and is not to be used + in application programs.</p> + </warning> + </desc> + </func> + + <func> + <name name="list_to_ref" arity="1"/> + <fsummary>Convert from text representation to a ref.</fsummary> + <desc> + <p>Returns a reference whose text representation is a + <c><anno>String</anno></c>, for example:</p> + <pre> +> <input>list_to_ref("#Ref<0.4192537678.4073193475.71181>").</input> +#Ref<0.4192537678.4073193475.71181></pre> + <p>Failure: <c>badarg</c> if <c><anno>String</anno></c> contains a bad + representation of a reference.</p> + <warning> + <p>This BIF is intended for debugging and is not to be used + in application programs.</p> + </warning> + </desc> + </func> + + <func> <name name="list_to_tuple" arity="1"/> <fsummary>Convert a list to a tuple.</fsummary> <desc> @@ -2544,13 +2628,6 @@ os_prompt%</pre> <name name="load_nif" arity="2"/> <fsummary>Load NIF library.</fsummary> <desc> - <note> - <p>Before Erlang/OTP R14B, NIFs were an - experimental feature. Versions before Erlang/OTP R14B can - have different and possibly incompatible NIF semantics and - interfaces. For example, in Erlang/OTP R13B03 the return value on - failure was <c>{error,Reason,Text}</c>.</p> - </note> <p>Loads and links a dynamic library containing native implemented functions (NIFs) for a module. <c><anno>Path</anno></c> is a file path to the shareable object/dynamic library file minus @@ -2580,14 +2657,22 @@ os_prompt%</pre> <item>The library did not fulfill the requirements as a NIF library of the calling module. </item> - <tag><c>load | reload | upgrade</c></tag> + <tag><c>load | upgrade</c></tag> <item>The corresponding library callback was unsuccessful. </item> + <tag><c>reload</c></tag> + <item>A NIF library is already loaded for this module instance. + The previously deprecated <c>reload</c> feature was removed in OTP 20. + </item> <tag><c>old_code</c></tag> <item>The call to <c>load_nif/2</c> was made from the old code of a module that has been upgraded; this is not allowed. </item> + <tag><c>notsup</c></tag> + <item>Lack of support. Such as loading NIF library for a + HiPE compiled module. + </item> </taglist> </desc> </func> @@ -3784,9 +3869,6 @@ RealSystem = system + MissedSystem</code> <c><anno>Term</anno></c> within the range <c>1..<anno>Range</anno></c>. The maximum value for <c><anno>Range</anno></c> is 2^32.</p> - <p>This BIF can be used instead of the old deprecated BIF - <c>erlang:hash/2</c>, as it calculates better hashes for - all data types, but consider using <c>phash2/1,2</c> instead.</p> </desc> </func> @@ -3821,10 +3903,6 @@ RealSystem = system + MissedSystem</code> <desc> <p>Returns a string corresponding to the text representation of <c><anno>Pid</anno></c>.</p> - <warning> - <p>This BIF is intended for debugging and is not to be used - in application programs.</p> - </warning> </desc> </func> @@ -4397,10 +4475,6 @@ RealSystem = system + MissedSystem</code> <desc> <p>Returns a string corresponding to the text representation of the port identifier <c><anno>Port</anno></c>.</p> - <warning> - <p>This BIF is intended for debugging. It is not to be used - in application programs.</p> - </warning> </desc> </func> @@ -4597,7 +4671,7 @@ RealSystem = system + MissedSystem</code> <p>If the process potentially can get many messages, you are advised to set the flag to <c>off_heap</c>. This because a garbage collection with many messages placed on - the heap can become extremly expensive and the process can + the heap can become extremely expensive and the process can consume large amounts of memory. Performance of the actual message passing is however generally better when not using flag <c>off_heap</c>.</p> @@ -6094,28 +6168,60 @@ true</pre> <fsummary>Information about active processes and ports.</fsummary> <desc> <marker id="statistics_active_tasks"></marker> + <p>Returns the same as + <seealso marker="#statistics_active_tasks_all"> + <c>statistics(active_tasks_all)</c></seealso> + with the exception that no information about the dirty + IO run queue and its associated schedulers is part of + the result. That is, only tasks that are expected to be + CPU bound are part of the result.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="2"/> + <fsummary>Information about active processes and ports.</fsummary> + <desc> + <marker id="statistics_active_tasks_all"></marker> <p>Returns a list where each element represents the amount of active processes and ports on each run queue and its - associated scheduler. That is, the number of processes and - ports that are ready to run, or are currently running. The - element location in the list corresponds to the scheduler - and its run queue. The first element corresponds to scheduler - number 1 and so on. The information is <em>not</em> gathered - atomically. That is, the result is not necessarily a - consistent snapshot of the state, but instead quite - efficiently gathered.</p> + associated schedulers. That is, the number of processes and + ports that are ready to run, or are currently running. + Values for normal run queues and their associated schedulers + are located first in the resulting list. The first element + corresponds to scheduler number 1 and so on. If support for + dirty schedulers exist, an element with the value for the + dirty CPU run queue and its associated dirty CPU schedulers + follow and then as last element the value for the the dirty + IO run queue and its associated dirty IO schedulers follow. + The information is <em>not</em> gathered atomically. That is, + the result is not necessarily a consistent snapshot of the + state, but instead quite efficiently gathered.</p> + <note><p>Each normal scheduler has one run queue that it + manages. If dirty schedulers schedulers are supported, all + dirty CPU schedulers share one run queue, and all dirty IO + schedulers share one run queue. That is, we have multiple + normal run queues, one dirty CPU run queue and one dirty + IO run queue. Work can <em>not</em> migrate between the + different types of run queues. Only work in normal run + queues can migrate to other normal run queues. This has + to be taken into account when evaluating the result.</p></note> <p>See also <seealso marker="#statistics_total_active_tasks"> <c>statistics(total_active_tasks)</c></seealso>, <seealso marker="#statistics_run_queue_lengths"> - <c>statistics(run_queue_lengths)</c></seealso>, and + <c>statistics(run_queue_lengths)</c></seealso>, + <seealso marker="#statistics_run_queue_lengths_all"> + <c>statistics(run_queue_lengths_all)</c></seealso>, <seealso marker="#statistics_total_run_queue_lengths"> - <c>statistics(total_run_queue_lengths)</c></seealso>.</p> + <c>statistics(total_run_queue_lengths)</c></seealso>, and + <seealso marker="#statistics_total_run_queue_lengths_all"> + <c>statistics(total_run_queue_lengths_all)</c></seealso>.</p> </desc> </func> <func> - <name name="statistics" arity="1" clause_i="2"/> + <name name="statistics" arity="1" clause_i="3"/> <fsummary>Information about context switches.</fsummary> <desc> <p>Returns the total number of context switches since the @@ -6124,7 +6230,7 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="3"/> + <name name="statistics" arity="1" clause_i="4"/> <fsummary>Information about exact reductions.</fsummary> <desc> <marker id="statistics_exact_reductions"></marker> @@ -6140,7 +6246,7 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="4"/> + <name name="statistics" arity="1" clause_i="5"/> <fsummary>Information about garbage collection.</fsummary> <desc> <p>Returns information about garbage collection, for example:</p> @@ -6152,7 +6258,7 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="5"/> + <name name="statistics" arity="1" clause_i="6"/> <fsummary>Information about I/O.</fsummary> <desc> <p>Returns <c><anno>Input</anno></c>, @@ -6163,7 +6269,7 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="6"/> + <name name="statistics" arity="1" clause_i="7"/> <fsummary>Information about microstate accounting.</fsummary> <desc> <marker id="statistics_microstate_accounting"></marker> @@ -6299,7 +6405,7 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="7"/> + <name name="statistics" arity="1" clause_i="8"/> <fsummary>Information about reductions.</fsummary> <desc> <marker id="statistics_reductions"></marker> @@ -6318,12 +6424,13 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="8"/> + <name name="statistics" arity="1" clause_i="9"/> <fsummary>Information about the run-queues.</fsummary> <desc><marker id="statistics_run_queue"></marker> - <p>Returns the total length of the run-queues. That is, the number + <p>Returns the total length of all normal run-queues. That is, the number of processes and ports that are ready to run on all available - run-queues. The information is gathered atomically. That + normal run-queues. Dirty run queues are not part of the + result. The information is gathered atomically. That is, the result is a consistent snapshot of the state, but this operation is much more expensive compared to <seealso marker="#statistics_total_run_queue_lengths"> @@ -6333,29 +6440,63 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="9"/> + <name name="statistics" arity="1" clause_i="10"/> <fsummary>Information about the run-queue lengths.</fsummary> <desc><marker id="statistics_run_queue_lengths"></marker> + <p>Returns the same as + <seealso marker="#statistics_run_queue_lengths_all"> + <c>statistics(run_queue_lengths_all)</c></seealso> + with the exception that no information about the dirty + IO run queue is part of the result. That is, only + run queues with work that is expected to be CPU bound + is part of the result.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="11"/> + <fsummary>Information about the run-queue lengths.</fsummary> + <desc><marker id="statistics_run_queue_lengths_all"></marker> <p>Returns a list where each element represents the amount - of processes and ports ready to run for each run queue. The - element location in the list corresponds to the run queue - of a scheduler. The first element corresponds to the run - queue of scheduler number 1 and so on. The information is - <em>not</em> gathered atomically. That is, the result is - not necessarily a consistent snapshot of the state, but - instead quite efficiently gathered.</p> + of processes and ports ready to run for each run queue. + Values for normal run queues are located first in the + resulting list. The first element corresponds to the + normal run queue of scheduler number 1 and so on. If + support for dirty schedulers exist, values for the dirty + CPU run queue and the dirty IO run queue follow (in that + order) at the end. The information is <em>not</em> + gathered atomically. That is, the result is not + necessarily a consistent snapshot of the state, but + instead quite efficiently gathered.</p> + <note><p>Each normal scheduler has one run queue that it + manages. If dirty schedulers schedulers are supported, all + dirty CPU schedulers share one run queue, and all dirty IO + schedulers share one run queue. That is, we have multiple + normal run queues, one dirty CPU run queue and one dirty + IO run queue. Work can <em>not</em> migrate between the + different types of run queues. Only work in normal run + queues can migrate to other normal run queues. This has + to be taken into account when evaluating the result.</p></note> <p>See also + <seealso marker="#statistics_run_queue_lengths"> + <c>statistics(run_queue_lengths)</c></seealso>, + <seealso marker="#statistics_total_run_queue_lengths_all"> + <c>statistics(total_run_queue_lengths_all)</c></seealso>, <seealso marker="#statistics_total_run_queue_lengths"> <c>statistics(total_run_queue_lengths)</c></seealso>, <seealso marker="#statistics_active_tasks"> - <c>statistics(active_tasks)</c></seealso>, and + <c>statistics(active_tasks)</c></seealso>, + <seealso marker="#statistics_active_tasks_all"> + <c>statistics(active_tasks_all)</c></seealso>, and <seealso marker="#statistics_total_active_tasks"> - <c>statistics(total_active_tasks)</c></seealso>.</p> + <c>statistics(total_active_tasks)</c></seealso>, + <seealso marker="#statistics_total_active_tasks_all"> + <c>statistics(total_active_tasks_all)</c></seealso>.</p> </desc> </func> <func> - <name name="statistics" arity="1" clause_i="10"/> + <name name="statistics" arity="1" clause_i="12"/> <fsummary>Information about runtime.</fsummary> <desc> <p>Returns information about runtime, in milliseconds.</p> @@ -6373,7 +6514,7 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="11"/> + <name name="statistics" arity="1" clause_i="13"/> <fsummary>Information about each schedulers work time.</fsummary> <desc> <marker id="statistics_scheduler_wall_time"></marker> @@ -6386,12 +6527,17 @@ lists:map( <c><anno>TotalTime</anno></c> is the total time duration since <seealso marker="#system_flag_scheduler_wall_time"> <c>scheduler_wall_time</c></seealso> - activation. The time unit is undefined and can be subject - to change between releases, OSs, and system restarts. - <c>scheduler_wall_time</c> is only to be used to - calculate relative values for scheduler-utilization. - <c><anno>ActiveTime</anno></c> can never exceed - <c><anno>TotalTime</anno></c>.</p> + activation for the specific scheduler. Note that + activation time can differ significantly between + schedulers. Currently dirty schedulers are activated + at system start while normal schedulers are activated + some time after the <c>scheduler_wall_time</c> + functionality is enabled. The time unit is undefined + and can be subject to change between releases, OSs, + and system restarts. <c>scheduler_wall_time</c> is only + to be used to calculate relative values for scheduler + utilization. <c><anno>ActiveTime</anno></c> can never + exceed <c><anno>TotalTime</anno></c>.</p> <p>The definition of a busy scheduler is when it is not idle and is not scheduling (selecting) a process or port, that is:</p> @@ -6409,15 +6555,37 @@ lists:map( <c>scheduler_wall_time</c></seealso> is turned off.</p> <p>The list of scheduler information is unsorted and can appear in different order between calls.</p> + <p>As of ERTS version 9.0, also dirty CPU schedulers will + be included in the result. That is, all scheduler threads + that are expected to handle CPU bound work. If you also + want information about dirty I/O schedulers, use + <seealso marker="#statistics_scheduler_wall_time_all"><c>statistics(scheduler_wall_time_all)</c></seealso> + instead.</p> + + <p>Normal schedulers will have scheduler identifiers in + the range <c>1 =< <anno>SchedulerId</anno> =< + </c><seealso marker="#system_info_schedulers"><c>erlang:system_info(schedulers)</c></seealso>. + Dirty CPU schedulers will have scheduler identifiers in + the range <c>erlang:system_info(schedulers) < + <anno>SchedulerId</anno> =< erlang:system_info(schedulers) + + + </c><seealso marker="#system_info_dirty_cpu_schedulers"><c>erlang:system_info(dirty_cpu_schedulers)</c></seealso>. + </p> + <note><p>The different types of schedulers handle + specific types of jobs. Every job is assigned to a specific + scheduler type. Jobs can migrate between different schedulers + of the same type, but never between schedulers of different + types. This fact has to be taken under consideration when + evaluating the result returned.</p></note> <p>Using <c>scheduler_wall_time</c> to calculate - scheduler-utilization:</p> + scheduler utilization:</p> <pre> > <input>erlang:system_flag(scheduler_wall_time, true).</input> false > <input>Ts0 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.</input> ok</pre> <p>Some time later the user takes another snapshot and calculates - scheduler-utilization per scheduler, for example:</p> + scheduler utilization per scheduler, for example:</p> <pre> > <input>Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.</input> ok @@ -6432,11 +6600,32 @@ ok {7,0.973237033077876}, {8,0.9741297293248656}]</pre> <p>Using the same snapshots to calculate a total - scheduler-utilization:</p> + scheduler utilization:</p> <pre> > <input>{A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai,Ti}) -> - {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0,Ts1)), A/T.</input> + {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0,Ts1)), + TotalSchedulerUtilization = A/T.</input> 0.9769136803764825</pre> + <p>Total scheduler utilization will equal <c>1.0</c> when + all schedulers have been active all the time between the + two measurements.</p> + <p>Another (probably more) useful value is to calculate + total scheduler utilization weighted against maximum amount + of available CPU time:</p> + <pre> +> <input>WeightedSchedulerUtilization = (TotalSchedulerUtilization + * (erlang:system_info(schedulers) + + erlang:system_info(dirty_cpu_schedulers))) + / erlang:system_info(logical_processors_available).</input> +0.9769136803764825</pre> + <p>This weighted scheduler utilization will reach <c>1.0</c> + when schedulers are active the same amount of time as + maximum available CPU time. If more schedulers exist + than available logical processors, this value may + be greater than <c>1.0</c>.</p> + <p>As of ERTS version 9.0, the Erlang runtime system + with SMP support will as default have more schedulers + than logical processors. This due to the dirty schedulers.</p> <note> <p><c>scheduler_wall_time</c> is by default disabled. To enable it, use @@ -6446,47 +6635,72 @@ ok </func> <func> - <name name="statistics" arity="1" clause_i="12"/> + <name name="statistics" arity="1" clause_i="14"/> + <fsummary>Information about each schedulers work time.</fsummary> + <desc> + <marker id="statistics_scheduler_wall_time_all"></marker> + <p>The same as + <seealso marker="#statistics_scheduler_wall_time"><c>statistics(scheduler_wall_time)</c></seealso>, + except that it also include information about all dirty I/O + schedulers.</p> + <p>Dirty IO schedulers will have scheduler identifiers in + the range + <seealso marker="#system_info_schedulers"><c>erlang:system_info(schedulers)</c></seealso><c> + + + </c><seealso marker="#system_info_dirty_cpu_schedulers"><c>erlang:system_info(dirty_cpu_schedulers)</c></seealso><c> < + <anno>SchedulerId</anno> =< erlang:system_info(schedulers) + + erlang:system_info(dirty_cpu_schedulers) + + + </c><seealso marker="#system_info_dirty_io_schedulers"><c>erlang:system_info(dirty_io_schedulers)</c></seealso>.</p> + <note><p>Note that work executing on dirty I/O schedulers + are expected to mainly wait for I/O. That is, when you + get high scheduler utilization on dirty I/O schedulers, + CPU utilization is <em>not</em> expected to be high due to + this work.</p></note> + </desc> + </func> + <func> + <name name="statistics" arity="1" clause_i="15"/> <fsummary>Information about active processes and ports.</fsummary> <desc><marker id="statistics_total_active_tasks"></marker> - <p>Returns the total amount of active processes and ports in - the system. That is, the number of processes and ports that - are ready to run, or are currently running. The information - is <em>not</em> gathered atomically. That is, the result - is not necessarily a consistent snapshot of the state, but - instead quite efficiently gathered.</p> - <p>See also - <seealso marker="#statistics_active_tasks"> - <c>statistics(active_tasks)</c></seealso>, - <seealso marker="#statistics_run_queue_lengths"> - <c>statistics(run_queue_lengths)</c></seealso>, and - <seealso marker="#statistics_total_run_queue_lengths"> - <c>statistics(total_run_queue_lengths)</c></seealso>.</p> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_active_tasks"><c>statistics(active_tasks)</c></seealso><c>)</c>, + but more efficient.</p> </desc> </func> <func> - <name name="statistics" arity="1" clause_i="13"/> + <name name="statistics" arity="1" clause_i="16"/> + <fsummary>Information about active processes and ports.</fsummary> + <desc><marker id="statistics_total_active_tasks_all"></marker> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_active_tasks_all"><c>statistics(active_tasks_all)</c></seealso><c>)</c>, + but more efficient.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="17"/> <fsummary>Information about the run-queue lengths.</fsummary> <desc><marker id="statistics_total_run_queue_lengths"></marker> - <p>Returns the total length of the run queues. That is, the number - of processes and ports that are ready to run on all available - run queues. The information is <em>not</em> gathered atomically. - That is, the result is not necessarily a consistent snapshot of - the state, but much more efficiently gathered compared to - <seealso marker="#statistics_run_queue"> - <c>statistics(run_queue)</c></seealso>.</p> - <p>See also <seealso marker="#statistics_run_queue_lengths"> - <c>statistics(run_queue_lengths)</c></seealso>, - <seealso marker="#statistics_total_active_tasks"> - <c>statistics(total_active_tasks)</c></seealso>, and - <seealso marker="#statistics_active_tasks"> - <c>statistics(active_tasks)</c></seealso>.</p> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_run_queue_lengths"><c>statistics(run_queue_lengths)</c></seealso><c>)</c>, + but more efficient.</p> </desc> </func> <func> - <name name="statistics" arity="1" clause_i="14"/> + <name name="statistics" arity="1" clause_i="18"/> + <fsummary>Information about the run-queue lengths.</fsummary> + <desc><marker id="statistics_total_run_queue_lengths_all"></marker> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_run_queue_lengths_all"><c>statistics(run_queue_lengths_all)</c></seealso><c>)</c>, + but more efficient.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="19"/> <fsummary>Information about wall clock.</fsummary> <desc> <p>Returns information about wall clock. <c>wall_clock</c> can @@ -6692,11 +6906,6 @@ ok down to 3. Similarly, the number of dirty CPU schedulers online increases proportionally to increases in the number of schedulers online.</p> - <note> - <p>The dirty schedulers functionality is experimental. - Enable support for dirty schedulers when building OTP to - try out the functionality.</p> - </note> <p>For more information, see <seealso marker="#system_info_dirty_cpu_schedulers"> <c>erlang:system_info(dirty_cpu_schedulers)</c></seealso> and @@ -7199,8 +7408,8 @@ ok </func> <func> - <name name="system_info" arity="1" clause_i="10"/> - <name name="system_info" arity="1" clause_i="11"/> + <name name="system_info" arity="1" clause_i="12"/> + <name name="system_info" arity="1" clause_i="13"/> <fsummary>Information about the CPU topology of the system.</fsummary> <type name="cpu_topology"/> <type name="level_entry"/> @@ -7300,12 +7509,12 @@ ok </func> <func> - <name name="system_info" arity="1" clause_i="27"/> - <name name="system_info" arity="1" clause_i="28"/> - <name name="system_info" arity="1" clause_i="36"/> - <name name="system_info" arity="1" clause_i="37"/> + <name name="system_info" arity="1" clause_i="29"/> + <name name="system_info" arity="1" clause_i="30"/> <name name="system_info" arity="1" clause_i="38"/> <name name="system_info" arity="1" clause_i="39"/> + <name name="system_info" arity="1" clause_i="40"/> + <name name="system_info" arity="1" clause_i="41"/> <fsummary>Information about the default process heap settings.</fsummary> <type name="message_queue_data"/> <type name="max_heap_size"/> @@ -7348,12 +7557,6 @@ ok see <seealso marker="#process_flag_max_heap_size"> <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> </item> - <tag><c>min_heap_size</c></tag> - <item> - <p>Returns <c>{min_heap_size, <anno>MinHeapSize</anno>}</c>, - where <c><anno>MinHeapSize</anno></c> is the current - system-wide minimum heap size for spawned processes.</p> - </item> <tag><marker id="system_info_message_queue_data"/> <c>message_queue_data</c></tag> <item> @@ -7366,6 +7569,12 @@ ok <seealso marker="#process_flag_message_queue_data"> <c>process_flag(message_queue_data, MQD)</c></seealso>.</p> </item> + <tag><c>min_heap_size</c></tag> + <item> + <p>Returns <c>{min_heap_size, <anno>MinHeapSize</anno>}</c>, + where <c><anno>MinHeapSize</anno></c> is the current + system-wide minimum heap size for spawned processes.</p> + </item> <tag><c>min_bin_vheap_size</c></tag> <item> <p>Returns <c>{min_bin_vheap_size, @@ -7382,8 +7591,8 @@ ok <name name="system_info" arity="1" clause_i="7"/> <name name="system_info" arity="1" clause_i="8"/> <name name="system_info" arity="1" clause_i="9"/> - <name name="system_info" arity="1" clause_i="12"/> - <name name="system_info" arity="1" clause_i="13"/> + <name name="system_info" arity="1" clause_i="10"/> + <name name="system_info" arity="1" clause_i="11"/> <name name="system_info" arity="1" clause_i="14"/> <name name="system_info" arity="1" clause_i="15"/> <name name="system_info" arity="1" clause_i="16"/> @@ -7397,15 +7606,15 @@ ok <name name="system_info" arity="1" clause_i="24"/> <name name="system_info" arity="1" clause_i="25"/> <name name="system_info" arity="1" clause_i="26"/> - <name name="system_info" arity="1" clause_i="29"/> - <name name="system_info" arity="1" clause_i="30"/> + <name name="system_info" arity="1" clause_i="27"/> + <name name="system_info" arity="1" clause_i="28"/> <name name="system_info" arity="1" clause_i="31"/> <name name="system_info" arity="1" clause_i="32"/> <name name="system_info" arity="1" clause_i="33"/> <name name="system_info" arity="1" clause_i="34"/> <name name="system_info" arity="1" clause_i="35"/> - <name name="system_info" arity="1" clause_i="40"/> - <name name="system_info" arity="1" clause_i="41"/> + <name name="system_info" arity="1" clause_i="36"/> + <name name="system_info" arity="1" clause_i="37"/> <name name="system_info" arity="1" clause_i="42"/> <name name="system_info" arity="1" clause_i="43"/> <name name="system_info" arity="1" clause_i="44"/> @@ -7434,16 +7643,28 @@ ok <name name="system_info" arity="1" clause_i="67"/> <name name="system_info" arity="1" clause_i="68"/> <name name="system_info" arity="1" clause_i="69"/> + <name name="system_info" arity="1" clause_i="70"/> + <name name="system_info" arity="1" clause_i="71"/> <fsummary>Information about the system.</fsummary> <desc> <p>Returns various information about the current system (emulator) as specified by <c><anno>Item</anno></c>:</p> <taglist> - <tag><c>allocated_areas</c>, <c>allocator</c>, - <c>alloc_util_allocators</c>, <c>allocator_sizes</c></tag> + <tag><c>atom_count</c></tag> + <item> + <marker id="system_info_atom_count"></marker> + <p>Returns the number of atoms currently existing at the + local node. The value is given as an integer.</p> + </item> + <tag><c>atom_limit</c></tag> <item> - <p>See <seealso marker="#system_info_allocator_tags"> - above</seealso>.</p> + <marker id="system_info_atom_limit"></marker> + <p>Returns the maximum number of atoms allowed. + This limit can be increased at startup by passing + command-line flag + <seealso marker="erts:erl#+t"><c>+t</c></seealso> to + <c>erl(1)</c>. + </p> </item> <tag><c>build_type</c></tag> <item> @@ -7529,9 +7750,6 @@ ok <seealso marker="erts:erl#+SDcpu"><c>+SDcpu</c></seealso> or <seealso marker="erts:erl#+SDPcpu"><c>+SDPcpu</c></seealso> in <c>erl(1)</c>.</p> - <p>Notice that the dirty schedulers functionality is - experimental. Enable support for dirty schedulers when - building OTP to try out the functionality.</p> <p>See also <seealso marker="#system_flag_dirty_cpu_schedulers_online"> <c>erlang:system_flag(dirty_cpu_schedulers_online, @@ -7561,9 +7779,6 @@ ok startup by passing command-line flag <seealso marker="erts:erl#+SDcpu"><c>+SDcpu</c></seealso> in <c>erl(1)</c>.</p> - <p>Notice that the dirty schedulers functionality is - experimental. Enable support for dirty schedulers when - building OTP to try out the functionality.</p> <p>For more information, see <seealso marker="#system_info_dirty_cpu_schedulers"> <c>erlang:system_info(dirty_cpu_schedulers)</c></seealso>, @@ -7585,9 +7800,6 @@ ok <p>This value can be set at startup by passing command-line argument <seealso marker="erts:erl#+SDio"><c>+SDio</c></seealso> in <c>erl(1)</c>.</p> - <p>Notice that the dirty schedulers functionality is - experimental. Enable support for dirty schedulers when - building OTP to try out the functionality.</p> <p>For more information, see <seealso marker="#system_info_dirty_cpu_schedulers"> <c>erlang:system_info(dirty_cpu_schedulers)</c></seealso>, @@ -8671,18 +8883,36 @@ hello <p>Option <c>{minor_version, <anno>Version</anno>}</c> can be used to control some encoding details. This option was introduced in Erlang/OTP R11B-4. - The valid values for <c><anno>Version</anno></c> are - <c>0</c> and <c>1</c>.</p> - <p>As from Erlang/OTP 17.0, <c>{minor_version, 1}</c> is the default. It - forces any floats in the term to be encoded in a more - space-efficient and exact way (namely in the 64-bit IEEE format, - rather than converted to a textual representation).</p> - <p>As from Erlang/OTP R11B-4, <c>binary_to_term/1</c> can decode this - representation.</p> - <p><c>{minor_version, 0}</c> means that floats are encoded - using a textual representation. This option is useful to - ensure that releases before Erlang/OTP R11B-4 can decode resulting - binary.</p> + The valid values for <c><anno>Version</anno></c> are:</p> + <taglist> + <tag><c>0</c></tag> + <item> + <p>Floats are encoded using a textual representation. + This option is useful to ensure that releases before Erlang/OTP + R11B-4 can decode resulting binary.</p> + <p>This version encode atoms that can be represented by a + latin1 string using latin1 encoding while only atoms that + cannot be represented by latin1 are encoded using utf8.</p> + </item> + <tag><c>1</c></tag> + <item> + <p>This is as of Erlang/OTP 17.0 the default. It forces any floats + in the term to be encoded in a more space-efficient and exact way + (namely in the 64-bit IEEE format, rather than converted to a + textual representation). As from Erlang/OTP R11B-4, + <c>binary_to_term/1</c> can decode this representation.</p> + <p>This version encode atoms that can be represented by a + latin1 string using latin1 encoding while only atoms that + cannot be represented by latin1 are encoded using utf8.</p> + </item> + <tag><c>2</c></tag> + <item> + <p>Drops usage of the latin1 atom encoding and unconditionally + use utf8 encoding for all atoms. This will be changed to the + default in a future major release of Erlang/OTP. Erlang/OTP + systems as of R16B can decode this representation.</p> + </item> + </taglist> <p>See also <seealso marker="#binary_to_term/1"> <c>binary_to_term/1</c></seealso>.</p> </desc> diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml index 8ab35851c1..d3f725ef99 100644 --- a/erts/doc/src/erts_alloc.xml +++ b/erts/doc/src/erts_alloc.xml @@ -4,7 +4,7 @@ <cref> <header> <copyright> - <year>2002</year><year>2016</year> + <year>2002</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -452,7 +452,7 @@ utilization value > 0 is used, allocator instances are allowed to abandon multiblock carriers. If <c>de</c> (default enabled) is passed instead of a <c><![CDATA[<utilization>]]></c>, - a recomended non-zero utilization value is used. The value + a recommended non-zero utilization value is used. The value chosen depends on the allocator type and can be changed between ERTS versions. Defaults to <c>de</c>, but this can be changed in the future.</p> @@ -595,7 +595,7 @@ </item> <tag><marker id="M_sbct"/><c><![CDATA[+M<S>sbct <size>]]></c></tag> <item> - <p>Singleblock carrier threshold. Blocks larger than this + <p>Singleblock carrier threshold (in kilobytes). Blocks larger than this threshold are placed in singleblock carriers. Blocks smaller than this threshold are placed in multiblock carriers. On 32-bit Unix style OS this threshold cannot be set diff --git a/erts/doc/src/escript.xml b/erts/doc/src/escript.xml index 1d5d280338..9b0d42185e 100644 --- a/erts/doc/src/escript.xml +++ b/erts/doc/src/escript.xml @@ -4,7 +4,7 @@ <comref> <header> <copyright> - <year>2007</year><year>2016</year> + <year>2007</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -35,6 +35,28 @@ <p><c>escript</c> provides support for running short Erlang programs without having to compile them first, and an easy way to retrieve the command-line arguments.</p> + + <p>It is possible to bundle <c>escript</c>(s) with an Erlang + runtime system to make it self-sufficient and relocatable. In such + a standalone system, the <c>escript</c>(s) should be located in + the top <c>bin</c> directory of the standalone system and given + <c>.escript</c> as file extension. Further the (built-in) + <c>escript</c> program should be copied to the same directory and + given the scripts original name (without the <c>.escript</c> + extension). This will enable use of the bundled Erlang runtime + system.</p> + + <p>The (built-in) <c>escript</c> program first determines which + Erlang runtime system to use and then starts it to execute your + script. Usually the runtime system is located in the same Erlang + installation as the <c>escript</c> program itself. But for + standalone systems with one or more escripts it may be the case + that the <c>escript</c> program in your path actually starts the + runtime system bundled with the escript. This is intentional, and + typically happens when the standalone system <c>bin</c> directory is not + in the execution path (as it may cause its <c>erl</c> program to + override the desired one) and the <c>escript</c>(s) are referred to via + symbolic links from a <c>bin</c> directory in the path.</p> </description> <funcs> diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index 99736c1641..f6bc6e984b 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,19 +31,65 @@ </header> <p>This document describes the changes made to the ERTS application.</p> -<section><title>Erts 8.3.5.2</title> +<section><title>Erts 9.0.4</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> <p> - Fix performance bug in pre-allocators that could cause - them to permanently fall back on normal more expensive - memory allocation. Pre-allocators are used for quick - allocation of short lived meta data used by messages and - other scheduled tasks. Bug exists since OTP_R15B02.</p> + A timer internal bit-field used for storing scheduler id + was too small. As a result, VM internal timer data + structures could become inconsistent when using 1024 + schedulers on the system. Note that systems with less + than 1024 schedulers are not effected by this bug.</p> <p> - Own Id: OTP-14491</p> + This bug was introduced in ERTS version 7.0 (OTP 18.0).</p> + <p> + Own Id: OTP-14548 Aux Id: OTP-11997, ERL-468 </p> + </item> + <item> + <p> + Automatic cleanup of a BIF timer, when the owner process + terminated, could race with the timeout of the timer. + This could cause the VM internal data structures to + become inconsistent which very likely caused a VM crash.</p> + <p> + This bug was introduced in ERTS version 9.0 (OTP 20.0).</p> + <p> + Own Id: OTP-14554 Aux Id: OTP-14356, ERL-468 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.0.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Binary append operations did not check for overflow, + resulting in nonsensical results when huge binaries were + appended.</p> + <p> + Own Id: OTP-14524</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.0.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Added missing release notes for OTP-14491 ("performance + bug in pre-allocators") which was included in erts-9.0.1 + (OTP-20.0.1).</p> + <p> + Own Id: OTP-14494</p> </item> <item> <p>Fixed a bug that prevented TCP sockets from being @@ -67,7 +113,7 @@ </section> -<section><title>Erts 8.3.5.1</title> +<section><title>Erts 9.0.1</title> <section><title>Fixed Bugs and Malfunctions</title> <list> @@ -99,6 +145,652 @@ <p> Own Id: OTP-14484</p> </item> + <item> + <p> + Fix performance bug in pre-allocators that could cause + them to permanently fall back on normal more expensive memory + allocation. Pre-allocators are used for quick allocation + of short lived meta data used by messages and other + scheduled tasks. Bug exists since OTP_R15B02. + [this release note was missing in erts-9.0.1]</p> + <p> + Own Id: OTP-14491</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.0</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fix various bugs regarding loading, upgrade and purge + of HiPE compiled code:</p> <list> <item>The native code + memory for a purged module was never deallocated.</item> + <item>Wrong functions could in some cases be called after + a module upgrade.</item> + <item><c>erlang:check_process_code</c> did not check for + recursive calls made from native code.</item> </list> + <p> + Own Id: OTP-13968</p> + </item> + <item> + <p> + Hipe optional LLVM backend does require LLVM version 3.9 + or later as older versions forced strong dependencies on + erts internals structures.</p> + <p> + Own Id: OTP-14238</p> + </item> + <item> + <p>When an exception such as '<c>throw(HugeTerm)</c>' was + caught, <c>HugeTerm</c> term would be kept in the process + until the next exception occurred, potentially increasing + the heap size for the process. That has been + corrected.</p> + <p> + Own Id: OTP-14255 Aux Id: OTP-14400, OTP-14401 </p> + </item> + <item> + <p> + Slogans in crash dumps have been extended to print more + complex terms.</p> + <p> + Own Id: OTP-14303</p> + </item> + <item> + <p> + Fixed bug when using <c>enif_inspect_binary</c> in + combination with <c>enif_copy</c>. In some circumstances + the inspected binary could be reallocated by the + <c>enif_copy</c> call when it shouldn't have been.</p> + <p> + Own Id: OTP-14304</p> + </item> + <item> + <p> + The address family <c>local</c> (AF_UNIX / AF_LOCAL) now + does not ensure zero termination of Linux Abstract + Addresses so they can use all bytes.</p> + <p> + Own Id: OTP-14305</p> + </item> + <item> + <p> + Use <c>-fno-PIE</c> for Gentoo Hardened and others that + don't accept linker flag <c>-no-pie</c>.</p> + <p> + Own Id: OTP-14307 Aux Id: PR-1379 </p> + </item> + <item> + <p> + Disable hipe for <c>ppc64le</c> architecture (little + endian) as it is not, and has never been, supported. It + was earlier equated with <c>ppc64</c> (big endian) which + lead to broken build without <c>--disable-hipe</c>.</p> + <p> + Own Id: OTP-14314 Aux Id: ERL-369, PR-1394 </p> + </item> + <item> + <p> + Fix 'epmd -kill' to return a failure exit status code if + epmd was not killed because of some error.</p> + <p> + Own Id: OTP-14324</p> + </item> + <item> + <p>Fixed the following dirty scheduler related bugs:</p> + <list> <item><p>the <c>+SDPcpu</c> command line argument + could cause the amount of dirty CPU schedulers to be set + to zero</p></item> + <item><p><c>erlang:system_flag(multi_scheduling, _)</c> + failed when only one normal scheduler was used together + with dirty scheduler support</p></item> </list> + <p> + Own Id: OTP-14335</p> + </item> + <item> + <p> + Fix erlexec to handle mismatch in sysconf and proc fs + when figuring out the cpu topology. This behaviour has + been seen when using docker together with + <c>--cpuset-cpus</c>.</p> + <p> + Own Id: OTP-14352</p> + </item> + <item> + <p> + Fixed memory segment cache used for multiblock carriers. + Huge (> 2GB) memory segments could cause a VM crash. + Creation of such huge memory segments used for multiblock + carriers is however very uncommon.</p> + <p> + Own Id: OTP-14360 Aux Id: ERL-401, PR-1417 </p> + </item> + <item> + <p> + Fix bug causing <c>code:is_module_native</c> to falsely + return true when <c>local</c> call trace is enabled for + the module.</p> + <p> + Own Id: OTP-14390</p> + </item> + <item> + <p> + Fix emulator crash when receive tracing on a + <c>trace_delivered</c> message.</p> + <p> + Own Id: OTP-14411</p> + </item> + <item> + <p> + Fix file:sendfile error handling on SunOS when a + connection is closed during transmission.</p> + <p> + Own Id: OTP-14424</p> + </item> + <item> + <p> + <c>escript</c> did not handle paths with spaces correct.</p> + <p> + Own Id: OTP-14433</p> + </item> + <item> + <p> + Fix erroneous lock check assertion when <c>wx</c> is run + on MacOS X.</p> + <p> + Own Id: OTP-14437 Aux Id: ERL-360 </p> + </item> + <item> + <p>Active-mode TCP sockets are now cleaned up properly on + send/shutdown errors.</p> + <p> + Own Id: OTP-14441 Aux Id: ERL-430 </p> + </item> + <item> + <p> + Fix compilation of hipe_mkliterals when the LIBS + configure variable had to be set.</p> + <p> + Own Id: OTP-14447</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Added <c>erlang:garbage_collect/2</c> that takes an + option list as the last argument that can be used to + control whether a minor or a major garbage collection is + to be done. Doing a minor collection only collects terms + that have recently died, but is cheaper than a major + collection.</p> + <p> + Own Id: OTP-11695</p> + </item> + <item> + <p> + Optimized test for tuples with an atom as first element.</p> + <p> + Own Id: OTP-12148</p> + </item> + <item> + <p> + Erlang literals are no longer copied during process to + process messaging.</p> + <p> + Own Id: OTP-13529</p> + </item> + <item> + <p>Add support in the <c>erl_nif</c> API for asynchronous + message notifications when sockets or other file + descriptors are ready to accept read or write operations. + The following functions have been added:</p> <list> + <item><p>enif_select</p></item> + <item><p>enif_monitor_process</p></item> + <item><p>enif_demonitor_process</p></item> + <item><p>enif_compare_monitors</p></item> + <item><p>enif_open_resource_type_x</p></item> </list> + <p> + Own Id: OTP-13684</p> + </item> + <item> + <p>There are two new guard BIFs '<c>floor/1</c>' and + '<c>ceil/1</c>'. They both return integers. In the + '<c>math</c>' module, there are two new BIFs with the + same names that return floating point values.</p> + <p> + Own Id: OTP-13692</p> + </item> + <item> + <p> + Remove deprecated <c>erlang:hash/2</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13827</p> + </item> + <item> + <p>Replaced usage of deprecated symbolic <seealso + marker="erts:erlang#type-time_unit"><c>time + unit</c></seealso> representations.</p> + <p> + Own Id: OTP-13831 Aux Id: OTP-13735 </p> + </item> + <item> + <p> + Added support in zlib for extraction of the inflation + dictionary.</p> + <p> + Own Id: OTP-13842</p> + </item> + <item> + <p> + The previously used purge strategy has been removed. The + optional purge strategy introduced in ERTS version 8.1 is + now the only strategy available.</p> + <p> + The new purge strategy is slightly incompatible with the + old strategy. Previously processes holding <c>fun</c>s + that referred to the module being purged either failed a + soft purge, or was killed during a hard purge. The new + strategy completely ignores <c>fun</c>s. If <c>fun</c>s + referring to the code being purged exist, and are used + after a purge, an exception will be raised upon usage. + That is, the behavior will be exactly the same as the + case when a <c>fun</c> is received by a process after the + purge.</p> + <p> + For more information see the documentation of <seealso + marker="erts:erlang#check_process_code/3"><c>erlang:check_process_code/3</c></seealso>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13844 Aux Id: OTP-13833 </p> + </item> + <item> + <p> + Dirty schedulers are now enabled by default when the + runtime system is built with SMP support.</p> + <p> + Own Id: OTP-13860</p> + </item> + <item> + <p> + Improved ETS lookup/insert/delete speed for large + <c>set</c>, <c>bag</c> and <c>duplicate_bag</c> by a + significant reduction of the hash load factor. This speed + improvement comes at the expense of less than one word + per table entry. Tables with less than 256 entries are + not affected at all.</p> + <p> + Own Id: OTP-13903</p> + </item> + <item> + <p> + The NIF library <c>reload</c> feature is not supported + anymore. It has been marked as deprecated since OTP R15B. + This means that you are only allowed to do one successful + call to <c>erlang:load_nif/2</c> for each module + instance. A second call to <c>erlang:load_nif/2</c> will + return <c>{error, {reload, _}}</c> even if the NIF + library implements the <c>reload</c> callback.</p> + <p> + Runtime upgrade of a NIF library is still supported by + using the Erlang module upgrade mechanics with a current + and an old module instance existing at the same time with + their corresponding NIF libraries.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13908</p> + </item> + <item> + <p> + Add <c>erlang:system_info(atom_count)</c> and + <c>erlang:system_info(atom_limit)</c> to provide a way to + retrieve the current and maximum number of atoms.</p> + <p> + Own Id: OTP-13976</p> + </item> + <item> + <p>The function <c>fmod/2</c> has been added to the + <c>math</c> module.</p> + <p> + Own Id: OTP-14000</p> + </item> + <item> + <p> + <c>erlang:load_nif/2</c> returns new error type + <c>notsup</c> when called for a HiPE compiled module, + which is not supported.</p> + <p> + Own Id: OTP-14002</p> + </item> + <item> + <p> + Add driver and nif lock instrumentation to lcnt</p> + <p> + Own Id: OTP-14069</p> + </item> + <item> + <p> + Reduce memory pressure by converting sub-binaries to + heap-binaries when possible. This is done during garbage + collection.</p> + <p> + Own Id: OTP-14149</p> + </item> + <item> + <p> + Dirty schedulers are now enabled and supported on Erlang + runtime systems with SMP support.</p> + <p> + Besides support for dirty NIFs also support for dirty + BIFs and dirty garbage collection have been introduced. + All garbage collections that potentially will take a long + time to complete are now performed on dirty schedulers if + enabled.</p> + <p> + <seealso + marker="erts:erlang#statistics/1"><c>erlang:statistics/1</c></seealso> + with arguments inspecting scheduler and run queue states + have been changed due to the dirty scheduler support. + Code using this functionality may have to be rewritten + taking these incompatibilities into consideration. + Examples of such uses are calls to <seealso + marker="erts:erlang#statistics_scheduler_wall_time"><c>erlang:statistics(scheduler_wall_time)</c></seealso>, + <seealso + marker="erts:erlang#statistics_total_run_queue_lengths"><c>statistics(total_run_queue_lengths)</c></seealso>, + <seealso + marker="erts:erlang#statistics_total_active_tasks"><c>statistics(total_active_tasks)</c></seealso>, + etc.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14152</p> + </item> + <item> + <p>Atoms may now contain arbitrary Unicode + characters.</p> + <p> + Own Id: OTP-14178</p> + </item> + <item> + <p> + Introduce an event manager in Erlang to handle OS + signals. A subset of OS signals may be subscribed to and + those are described in the Kernel application.</p> + <p> + Own Id: OTP-14186</p> + </item> + <item> + <p> + The <c>escript</c> program now handles symbolic links to + escripts.</p> + <p> + This is useful for standalone systems with + <c>escript</c>s residing on a bin directory not included + in the execution path (as it may cause their <c>erl</c> + program(s) to override the desired one). Instead the + <c>escript</c>s can be referred to via symbolic links + from a bin directory in the path.</p> + <p> + Own Id: OTP-14201 Aux Id: PR-1293 </p> + </item> + <item> + <p> + All uses of the magic binary kludge has been replaced by + uses of erlang references.</p> + <p> + A magic binary was presented as an empty binary, but + actually referred other data internally in the Erlang VM. + Since they were presented as empty binaries, different + magic binaries compared as equal, and also lost their + internal data when passed out of an erlang node.</p> + <p> + The new usage of references has not got any of these + strange semantic issues, and the usage of these + references has been optimized to give the same + performance benefits as well as memory usage benefits as + magic binaries had.</p> + <p> + A couple of examples of previous uses of magic binaries + are match specifications and NIF resources.</p> + <p> + Own Id: OTP-14205</p> + </item> + <item> + <p> + The non-smp emulators have been deprecated and are + scheduled for removal in OTP-21.</p> + <p> + In preparation for this, the threaded non-smp emulator is + no longer built by default and has to be enabled using + the --enable-plain-emulator to configure.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14272</p> + </item> + <item> + <p> + Allow HiPE to run on VM built with + <c>--enable-m32-build</c>.</p> + <p> + Own Id: OTP-14330 Aux Id: PR-1397 </p> + </item> + <item> + <p> + Upgraded the OTP internal PCRE library from version 8.33 + to version 8.40. This library is used for implementation + of the <seealso marker="stdlib:re"><c>re</c></seealso> + regular expressions module.</p> + <p> + Besides various bug fixes, the new version allows for + better stack protection. In order to utilize this + feature, the stack size of normal scheduler threads is + now by default set to 128 kilo words on all platforms. + The stack size of normal scheduler threads can be set + upon system start by passing the <seealso + marker="erts:erl#sched_thread_stack_size"><c>+sss</c></seealso> + command line argument to the <seealso + marker="erts:erl"><c>erl</c></seealso> command.</p> + <p> + See <url + href="http://pcre.org/original/changelog.txt"><c>http://pcre.org/original/changelog.txt</c></url> + for information about changes made to PCRE between the + versions 8.33 and 8.40.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14331 Aux Id: ERL-208 </p> + </item> + <item> + <p> + Remove generation of atoms in old latin1 external format + in the distribution between erlang nodes, + <c>erl_interface</c>, and <c>jinterface</c>. The new utf8 + format for atoms was introduced in OTP R16. An OTP 20 + node can therefore not connect to nodes older than R16.</p> + <p> + Atoms that can be encoded using latin1 are still encoded + by <c>term_to_binary()</c> using latin1 encoding. Note + that all atoms will by default be encoded using utf8 in a + future Erlang/OTP release. For more information see the + documentation of <seealso + marker="erts:erlang#term_to_binary/2"><c>erlang:term_to_binary/2</c></seealso>.</p> + <p> + Own Id: OTP-14337</p> + </item> + <item> + <p> + Added function <c>re:version/0</c> which returns + information about the OTP internal PCRE version used for + implementation of the <c>re</c> module.</p> + <p> + Own Id: OTP-14347 Aux Id: PR-1412 </p> + </item> + <item> + <p> + Added new debug bif <c>erlang:list_to_port/1</c>.</p> + <p> + Own Id: OTP-14348</p> + </item> + <item> + <p> + Various improvements of timer management internally in + the VM. These improvements both reduced memory + consumption of timer wheels as well as reduce the amount + of work that has to be performed in order to handle + timers.</p> + <p> + Own Id: OTP-14356</p> + </item> + <item> + <p> Sockets can now be bound to device (SO_BINDTODEVICE) + on platforms where it is supported. </p> <p> This has + been implemented e.g to support VRF-Lite under Linux; see + <url + href="https://www.kernel.org/doc/Documentation/networking/vrf.txt"> + VRF </url>, and GitHub pull request <url + href="https://github.com/erlang/otp/pull/1326">#1326</url>. + </p> + <p> + Own Id: OTP-14357 Aux Id: PR-1326 </p> + </item> + <item> + <p>Added the following <seealso + marker="erl"><c>erl</c></seealso> command line arguments + with which you can set suggested stack for dirty + schedulers:</p> <taglist> <tag><seealso + marker="erl#dcpu_sched_thread_stack_size"><c>+sssdcpu</c></seealso></tag> + <item><p>for dirty CPU schedulers</p></item> + <tag><seealso + marker="erl#dio_sched_thread_stack_size"><c>+sssdio</c></seealso></tag> + <item><p>for dirty IO schedulers</p></item> </taglist> + <p>The default suggested stack size for dirty schedulers + is 40 kilo words.</p> + <p> + Own Id: OTP-14380</p> + </item> + <item> + <p> + Changed erts startup program name, argv 0, to use the + environment variable <c>ESCRIPT_NAME</c> so that + <c>erlc</c>, <c>dialyzer</c>, <c>typer</c>, + <c>ct_run</c>, or the escript name can be seen with + external programs, such as ps and htop (depending on + options), on unix.</p> + <p> + Own Id: OTP-14381</p> + </item> + <item> + <p> + Improvements of <c>escript</c> documentation.</p> + <p> + Own Id: OTP-14384 Aux Id: OTP-14201 </p> + </item> + <item> + <p> + Add function <c>enif_hash</c> for NIFs to calculate hash + values of arbitrary terms.</p> + <p> + Own Id: OTP-14385 Aux Id: PR-1413 </p> + </item> + <item> + <p>'<c>./configure --enable-lock-counter</c>' will + enabling building of an additional emulator that has + support for lock counting. (The option previously + existed, but would turn on lock counting in the default + emulator being built.) To start the lock-counting + emulator, use '<c>erl -emu_type lcnt</c>'.</p> + <p>On Windows, <c>erl</c> recognized the undocumented + option <c>-debug</c> for starting a debug-compiled + emulator. That option has been removed. Use '<c>erl + -emu_type debug</c>' instead.</p> + <p> + Own Id: OTP-14407</p> + </item> + <item> + <p> + Warnings have been added to the relevant documentation + about not using un-secure distributed nodes in exposed + environments.</p> + <p> + Own Id: OTP-14425</p> + </item> + <item> + <p> + Improvement of the documentation of the environment + variable <c>ERL_CRASH_DUMP_SECONDS</c> as well as the + default behavior when it is not set.</p> + <p> + Own Id: OTP-14434</p> + </item> + <item> + <p> + Enabled off-heap message queue for some system processes + that might receive large amounts of messages.</p> + <p> + Own Id: OTP-14438</p> + </item> + <item> + <p>ETS lock indexes have been replaced with the table + name in LCNT results.</p> + <p> + Own Id: OTP-14442 Aux Id: ERIERL-22 </p> + </item> + <item> + <p> + Introduced the new functions <seealso + marker="erl_nif#enif_whereis_pid"><c>enif_whereis_pid()</c></seealso> + and <seealso + marker="erl_nif#enif_whereis_port"><c>enif_whereis_port()</c></seealso>.</p> + <p> + Own Id: OTP-14453 Aux Id: PR-1400 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.5.1</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a bug in gen_tcp:send where it never returned when + repeatedly called on a remotely closed TCP socket.</p> + <p> + Own Id: OTP-13939 Aux Id: ERL-193 </p> + </item> + <item> + <p> + Fixed segfault that could happen during cleanup of + aborted erlang:port_command/3 calls. A port_command is + aborted if the port is closed at the same time as the + port_command was issued. This bug was introduced in + erts-8.0.</p> + <p> + Own Id: OTP-14481</p> + </item> + <item> + <p> + Fixed implementation of <c>statistics(wall_clock)</c> and + <c>statistics(runtime)</c> so that values do not + unnecessarily wrap due to the emulator. Note that the + values returned by <c>statistics(runtime)</c> may still + wrap due to limitations in the underlying functionality + provided by the operating system.</p> + <p> + Own Id: OTP-14484</p> + </item> </list> </section> @@ -982,7 +1674,7 @@ <list> <item> <p> - Fixed a VM crash that occured in a garbage collection of + Fixed a VM crash that occurred in a garbage collection of a process when it had received binaries. This bug was introduced in ERTS version 8.0 (OTP 19.0).</p> <p> @@ -999,7 +1691,7 @@ <list> <item> <p> - Fixed a VM crash that occured in garbage collection of a + Fixed a VM crash that occurred in garbage collection of a process when it had received maps over the distribution. This bug was introduced in ERTS version 8.0 (OTP 19.0).</p> <p> @@ -1810,6 +2502,96 @@ </section> +<section><title>Erts 7.3.1.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A bug has been fixed where if erlang was started +B on a + unix platform it would be killed by a SIGUSR2 signal when + creating a crash dump.</p> + <p> + Own Id: OTP-13425 Aux Id: ERL-94 </p> + </item> + <item> + <p> + Calls to <c>erl_drv_send_term()</c> or + <c>erl_drv_output_term()</c> from a non-scheduler thread + while the corresponding port was invalid caused the + emulator to enter an inconsistent state which eventually + caused an emulator crash.</p> + <p> + Own Id: OTP-13866</p> + </item> + <item> + <p>Driver and NIF operations accessing processes or ports + could cause an emulator crash when used from + non-scheduler threads. Those operations are:</p> <list> + <item><c>erl_drv_send_term()</c></item> + <item><c>driver_send_term()</c></item> + <item><c>erl_drv_output_term()</c></item> + <item><c>driver_output_term()</c></item> + <item><c>enif_send()</c></item> + <item><c>enif_port_command()</c></item> </list> + <p> + Own Id: OTP-13869</p> + </item> + <item> + <p> + Fix bug in <c>binary_to_term</c> for binaries created by + <c>term_to_binary </c> with option <c>compressed</c>. The + bug can cause <c>badarg</c> exception for a valid binary + when Erlang VM is linked against a <c>zlib</c> library of + version 1.2.9 or newer. Bug exists since OTP 17.0.</p> + <p> + Own Id: OTP-14159 Aux Id: ERL-340 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 7.3.1.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a race that could cause a lost wakeup of a process + that timed out in a <c>receive ... after</c>. This bug + was introduced in ERTS version 7.0.</p> + <p> + Own Id: OTP-13798 Aux Id: OTP-11997 </p> + </item> + <item> + <p> + Fixed segfault after writing an erl crash dump.</p> + <p> + Own Id: OTP-13799</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 7.3.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix scheduler deadlock bug in <c>ets:update_counter/4</c> + when key is not found and inserting the default object + causes the table to grow.</p> + <p> + Own Id: OTP-13731 Aux Id: ERL-188 </p> + </item> + </list> + </section> + +</section> + <section><title>Erts 7.3.1</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -2061,6 +2843,31 @@ </section> +<section><title>Erts 7.2.1.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Introduced new statistics functionality in order to + more efficiently retrieve information about run able and + active processes and ports. For more information see:</p> + <list> <item><seealso + marker="erlang#statistics_total_run_queue_lengths"><c>statistics(total_run_queue_lengths)</c></seealso></item> + <item><seealso + marker="erlang#statistics_run_queue_lengths"><c>statistics(run_queue_lengths)</c></seealso></item> + <item><seealso + marker="erlang#statistics_total_active_tasks"><c>statistics(total_active_tasks)</c></seealso></item> + <item><seealso + marker="erlang#statistics_active_tasks"><c>statistics(active_tasks)</c></seealso></item> + </list> + <p> + Own Id: OTP-13201</p> + </item> + </list> + </section> + +</section> + <section><title>Erts 7.2.1</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -6100,7 +6907,7 @@ dependent, so applications aiming to be portable should consider using <c>{ipv6_v6only,true}</c> when creating an <c>inet6</c> listening/destination socket, and if - neccesary also create an <c>inet</c> socket on the same + necessary also create an <c>inet</c> socket on the same port for IPv4 traffic. See the documentation.</p> <p> Own Id: OTP-8928 Aux Id: kunagi-193 [104] </p> @@ -6481,7 +7288,7 @@ This change of default value will reduce lock contention on ETS tables using the <c>read_concurrency</c> option at the expense of memory consumption when the amount of - schedulers and logical processors are beween 8 and 64. + schedulers and logical processors are between 8 and 64. For more information, see documentation of the <c>+rg</c> command line argument of <c>erl(1)</c>.</p> <p> @@ -7458,7 +8265,7 @@ <p> For the subsection about process_flag(save_calls, N) there's an unrelated paragraph about process priorities - which was copied from the preceeding subsection regarding + which was copied from the preceding subsection regarding process_flag(priority, Level). (Thanks to Filipe David Manana)</p> <p> @@ -8673,7 +9480,7 @@ <item> <p> Wx on MacOS X generated complains on stderr about certain - cocoa functions not beeing called from the "Main thread". + cocoa functions not being called from the "Main thread". This is now corrected.</p> <p> Own Id: OTP-9081</p> @@ -9664,7 +10471,7 @@ </item> <item> <p>The <c>empd</c> program could loop and consume 100% - CPU time if an unexpected error ocurred in + CPU time if an unexpected error occurred in <c>listen()</c> or <c>accept()</c>. Now <c>epmd</c> will terminate if a non-recoverable error occurs. (Thanks to Michael Santos.)</p> diff --git a/erts/doc/src/zlib.xml b/erts/doc/src/zlib.xml index f8140544b7..f5cc1b1e64 100644 --- a/erts/doc/src/zlib.xml +++ b/erts/doc/src/zlib.xml @@ -65,13 +65,17 @@ list_to_binary([Compressed|Last])</pre> <tag><c>badarg</c></tag> <item>Bad argument. </item> + <tag><c>not_initialized</c></tag> + <item>The stream hasn't been initialized, eg. if + <seealso marker="#inflateInit/1"><c>inflateInit/1</c></seealso> wasn't + called prior to a call to + <seealso marker="#inflate/2"><c>inflate/2</c></seealso>. + </item> <tag><c>data_error</c></tag> <item>The data contains errors. </item> <tag><c>stream_error</c></tag> <item>Inconsistent stream state.</item> - <tag><c>einval</c></tag> - <item>Bad value or wrong function called.</item> <tag><c>{need_dictionary,Adler32}</c></tag> <item>See <seealso marker="#inflate/2"><c>inflate/2</c></seealso>. </item> @@ -90,6 +94,9 @@ list_to_binary([Compressed|Last])</pre> <name name="zlevel"/> </datatype> <datatype> + <name name="zflush"/> + </datatype> + <datatype> <name name="zmemlevel"/> </datatype> <datatype> @@ -112,6 +119,11 @@ list_to_binary([Compressed|Last])</pre> <fsummary>Calculate the Adler checksum.</fsummary> <desc> <p>Calculates the Adler-32 checksum for <c><anno>Data</anno></c>.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#adler32/1"> + <c>erlang:adler32/1</c></seealso> instead.</p> + </warning> </desc> </func> @@ -127,6 +139,11 @@ list_to_binary([Compressed|Last])</pre> Crc = lists:foldl(fun(Data,Crc0) -> zlib:adler32(Z, Crc0, Data), end, zlib:adler32(Z,<< >>), Datas)</pre> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#adler32/2"> + <c>erlang:adler32/2</c></seealso> instead.</p> + </warning> </desc> </func> @@ -141,6 +158,11 @@ Crc = lists:foldl(fun(Data,Crc0) -> <p>This function returns the <c><anno>Adler</anno></c> checksum of <c>[Data1,Data2]</c>, requiring only <c><anno>Adler1</anno></c>, <c><anno>Adler2</anno></c>, and <c><anno>Size2</anno></c>.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#adler32_combine/3"> + <c>erlang:adler32_combine/3</c></seealso> instead.</p> + </warning> </desc> </func> @@ -165,6 +187,12 @@ Crc = lists:foldl(fun(Data,Crc0) -> <fsummary>Get current CRC.</fsummary> <desc> <p>Gets the current calculated CRC checksum.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#crc32/1"> + <c>erlang:crc32/1</c></seealso> on the uncompressed data + instead.</p> + </warning> </desc> </func> @@ -173,6 +201,11 @@ Crc = lists:foldl(fun(Data,Crc0) -> <fsummary>Calculate CRC.</fsummary> <desc> <p>Calculates the CRC checksum for <c><anno>Data</anno></c>.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#crc32/1"> + <c>erlang:crc32/1</c></seealso> instead.</p> + </warning> </desc> </func> @@ -188,6 +221,11 @@ Crc = lists:foldl(fun(Data,Crc0) -> Crc = lists:foldl(fun(Data,Crc0) -> zlib:crc32(Z, Crc0, Data), end, zlib:crc32(Z,<< >>), Datas)</pre> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#crc32/2"> + <c>erlang:crc32/2</c></seealso> instead.</p> + </warning> </desc> </func> @@ -202,6 +240,11 @@ Crc = lists:foldl(fun(Data,Crc0) -> <p>This function returns the <c><anno>CRC</anno></c> checksum of <c>[Data1,Data2]</c>, requiring only <c><anno>CRC1</anno></c>, <c><anno>CRC2</anno></c>, and <c><anno>Size2</anno></c>.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#crc32_combine/3"> + <c>erlang:crc32_combine/3</c></seealso> instead.</p> + </warning> </desc> </func> @@ -407,8 +450,8 @@ list_to_binary([B1,B2])</pre> <seealso marker="#deflateInit/1"><c>deflateInit/1,2,6</c></seealso> or <seealso marker="#deflateReset/1"><c>deflateReset/1</c></seealso>, before any call of - <seealso marker="#deflate/3"><c>deflate/3</c></seealso>. - The compressor and decompressor must use the same dictionary (see + <seealso marker="#deflate/3"><c>deflate/3</c></seealso>.</p> + <p>The compressor and decompressor must use the same dictionary (see <seealso marker="#inflateSetDictionary/2"> <c>inflateSetDictionary/2</c></seealso>).</p> <p>The Adler checksum of the dictionary is returned.</p> @@ -420,6 +463,10 @@ list_to_binary([B1,B2])</pre> <fsummary>Get buffer size.</fsummary> <desc> <p>Gets the size of the intermediate buffer.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release.</p> + </warning> </desc> </func> @@ -443,14 +490,31 @@ list_to_binary([B1,B2])</pre> <name name="inflate" arity="2"/> <fsummary>Decompress data.</fsummary> <desc> - <p>Decompresses as much data as possible. - It can introduce some output latency (reading - input without producing any output).</p> - <p>If a preset dictionary is needed at this point (see - <seealso marker="#inflateSetDictionary/2"> - <c>inflateSetDictionary/2</c></seealso>), <c>inflate/2</c> throws a - <c>{need_dictionary,Adler}</c> exception, where <c>Adler</c> is - the Adler-32 checksum of the dictionary chosen by the compressor.</p> + <p>Equivalent to + <seealso marker="#inflate/3"><c>inflate(Z, Data, [])</c></seealso> + </p> + </desc> + </func> + + <func> + <name name="inflate" arity="3"/> + <fsummary>Decompress data.</fsummary> + <desc> + <p>Decompresses as much data as possible. It can introduce some output + latency (reading input without producing any output).</p> + <p>Currently the only available option is + <c>{exception_on_need_dict,boolean()}</c> which controls whether the + function should throw an exception when a preset dictionary is + required for decompression. When set to false, a + <c>need_dictionary</c> tuple will be returned instead. See + <seealso marker="#inflateSetDictionary/2"> + <c>inflateSetDictionary/2</c></seealso> for details.</p> + <warning> + <p>This option defaults to <c>true</c> for backwards compatibility + but we intend to remove the exception behavior in a future + release. New code that needs to handle dictionaries manually + should always specify <c>{exception_on_need_dict,false}</c>.</p> + </warning> </desc> </func> @@ -458,6 +522,11 @@ list_to_binary([B1,B2])</pre> <name name="inflateChunk" arity="1"/> <fsummary>Read next uncompressed chunk.</fsummary> <desc> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="#safeInflate/2"><c>safeInflate/2</c> + </seealso> instead.</p> + </warning> <p>Reads the next chunk of uncompressed data, initialized by <seealso marker="#inflateChunk/2"><c>inflateChunk/2</c></seealso>.</p> <p>This function is to be repeatedly called, while it returns @@ -469,23 +538,27 @@ list_to_binary([B1,B2])</pre> <name name="inflateChunk" arity="2"/> <fsummary>Decompress data with limited output size.</fsummary> <desc> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="#safeInflate/2"><c>safeInflate/2</c> + </seealso> instead.</p> + </warning> <p>Like <seealso marker="#inflate/2"><c>inflate/2</c></seealso>, - but decompresses no more data than will fit in the buffer configured - through <seealso marker="#setBufSize/2"><c>setBufSize/2</c></seealso>. - Is is useful when decompressing a stream with a high compression - ratio, such that a small amount of compressed input can expand up to - 1000 times.</p> + but decompresses no more data than will fit in the buffer configured + through <seealso marker="#setBufSize/2"><c>setBufSize/2</c> + </seealso>. Is is useful when decompressing a stream with a high + compression ratio, such that a small amount of compressed input can + expand up to 1000 times.</p> <p>This function returns <c>{more, Decompressed}</c>, when there is - more output available, and - <seealso marker="#inflateChunk/1"><c>inflateChunk/1</c></seealso> - is to be used to read it.</p> - <p>This function can introduce some output latency (reading - input without producing any output).</p> - <p>If a preset dictionary is needed at this point (see - <seealso marker="#inflateSetDictionary/2"> - <c>inflateSetDictionary/2</c></seealso>), this function throws a - <c>{need_dictionary,Adler}</c> exception, where <c>Adler</c> is - the Adler-32 checksum of the dictionary chosen by the compressor.</p> + more output available, and + <seealso marker="#inflateChunk/1"><c>inflateChunk/1</c></seealso> + is to be used to read it.</p> + <p>This function can introduce some output latency (reading input + without producing any output).</p> + <p>An exception will be thrown if a preset dictionary is required for + further decompression. See + <seealso marker="#inflateSetDictionary/2"> + <c>inflateSetDictionary/2</c></seealso> for details.</p> <p>Example:</p> <pre> walk(Compressed, Handler) -> @@ -517,6 +590,18 @@ loop(Z, Handler, Uncompressed) -> </func> <func> + <name name="inflateGetDictionary" arity="1"/> + <fsummary>Return the decompression dictionary.</fsummary> + <desc> + <p>Returns the decompression dictionary currently in use + by the stream. This function must be called between + <seealso marker="#inflateInit/1"><c>inflateInit/1,2</c></seealso> + and <seealso marker="#inflateEnd/1"><c>inflateEnd</c></seealso>.</p> + <p>Only supported if ERTS was compiled with zlib >= 1.2.8.</p> + </desc> + </func> + + <func> <name name="inflateInit" arity="1"/> <fsummary>Initialize a session for decompression.</fsummary> <desc> @@ -562,25 +647,38 @@ loop(Z, Handler, Uncompressed) -> <fsummary>Initialize the decompression dictionary.</fsummary> <desc> <p>Initializes the decompression dictionary from the specified - uncompressed byte sequence. This function must be called - immediately after a call of - <seealso marker="#inflate/2"><c>inflate/2</c></seealso> - if this call threw a <c>{need_dictionary,Adler}</c> exception. - The dictionary chosen by the compressor can be determined from the - Adler value thrown by the call to <c>inflate/2</c>. - The compressor and decompressor must use the same dictionary (see - <seealso marker="#deflateSetDictionary/2"> - <c>deflateSetDictionary/2</c></seealso>).</p> + uncompressed byte sequence. This function must be called as a + response to an inflate operation (eg. + <seealso marker="#safeInflate/2"><c>safeInflate/2</c></seealso>) + returning <c>{need_dictionary,Adler,Output}</c> or in the case of + deprecated functions, throwing an + <c>{'EXIT',{{need_dictionary,Adler},_StackTrace}}</c> exception.</p> + <p>The dictionary chosen by the compressor can be determined from the + Adler value returned or thrown by the call to the inflate function. + The compressor and decompressor must use the same dictionary (See + <seealso marker="#deflateSetDictionary/2"> + <c>deflateSetDictionary/2</c></seealso>).</p> + <p>After setting the dictionary the inflate operation should be + retried without new input.</p> <p>Example:</p> <pre> -unpack(Z, Compressed, Dict) -> +deprecated_unpack(Z, Compressed, Dict) -> case catch zlib:inflate(Z, Compressed) of - {'EXIT',{{need_dictionary,DictID},_}} -> - zlib:inflateSetDictionary(Z, Dict), + {'EXIT',{{need_dictionary,_DictID},_}} -> + ok = zlib:inflateSetDictionary(Z, Dict), Uncompressed = zlib:inflate(Z, []); Uncompressed -> Uncompressed - end.</pre> + end. + +new_unpack(Z, Compressed, Dict) -> + case zlib:inflate(Z, Compressed, [{exception_on_need_dict, false}]) of + {need_dictionary, _DictId, Output} -> + ok = zlib:inflateSetDictionary(Z, Dict), + [Output | zlib:inflate(Z, [])]; + Uncompressed -> + Uncompressed + end.</pre> </desc> </func> @@ -593,10 +691,51 @@ unpack(Z, Compressed, Dict) -> </func> <func> + <name name="safeInflate" arity="2"/> + <fsummary>Decompress data with limited output size.</fsummary> + <desc> + <p>Like <seealso marker="#inflate/2"><c>inflate/2</c></seealso>, + but returns once it has expanded beyond a small + implementation-defined threshold. It's useful when decompressing + untrusted input which could have been maliciously crafted to expand + until the system runs out of memory.</p> + <p>This function returns <c>{continue | finished, Output}</c>, where + <anno>Output</anno> is the data that was decompressed in this call. + New input can be queued up on each call if desired, and the function + will return <c>{finished, Output}</c> once all queued data has been + decompressed.</p> + <p>This function can introduce some output latency (reading + input without producing any output).</p> + <p>If a preset dictionary is required for further decompression, this + function returns a <c>need_dictionary</c> tuple. See + <seealso marker="#inflateSetDictionary/2"> + <c>inflateSetDictionary/2</c></seealso>) for details.</p> + <p>Example:</p> + <pre> +walk(Compressed, Handler) -> + Z = zlib:open(), + zlib:inflateInit(Z), + loop(Z, Handler, zlib:safeInflate(Z, Compressed)), + zlib:inflateEnd(Z), + zlib:close(Z). + +loop(Z, Handler, {continue, Output}) -> + Handler(Output), + loop(Z, Handler, zlib:safeInflate(Z, [])); +loop(Z, Handler, {finished, Output}) -> + Handler(Output).</pre> + </desc> + </func> + + <func> <name name="setBufSize" arity="2"/> <fsummary>Set buffer size.</fsummary> <desc> <p>Sets the intermediate buffer size.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release.</p> + </warning> </desc> </func> |