kernel

v11.0-rc0

Kernel Application

Description

The Kernel application has all the code necessary to run the Erlang runtime system: file servers, code servers, and so on.

The Kernel application is the first application started. It is mandatory in the sense that the minimal system based on Erlang/OTP consists of Kernel and STDLIB. Kernel contains the following functional areas:

Start, stop, supervision, configuration, and distribution of applications

Code loading

Logging

Global name service

Supervision of Erlang/OTP

Communication with sockets

Operating system interface

Logger Handlers

Two standard logger handlers are defined in the Kernel application. These are described in the Kernel User's Guide, and in the logger_std_h and logger_disk_log_h manual pages.

OS Signal Event Handler

Asynchronous OS signals may be subscribed to via the Kernel applications event manager (see OTP Design Principles and gen_event) registered as erl_signal_server. A default signal handler is installed which handles the following signals:

sigusr1 - The default handler will halt Erlang and produce a crashdump with slogan "Received SIGUSR1". This is equivalent to calling erlang:halt("Received SIGUSR1").

sigquit - The default handler will halt Erlang immediately. This is equivalent to calling erlang:halt().

sigterm - The default handler will terminate Erlang normally. This is equivalent to calling init:stop().

Events

Any event handler added to erl_signal_server must handle the following events.

sighup - Hangup detected on controlling terminal or death of controlling process

sigquit - Quit from keyboard

sigabrt - Abort signal from abort

sigalrm - Timer signal from alarm

sigterm - Termination signal

sigusr1 - User-defined signal 1

sigusr2 - User-defined signal 2

sigchld - Child process stopped or terminated

sigstop - Stop process

sigtstp - Stop typed at terminal

sigcont - Continue after stop

sigwinch - Window size change

siginfo - Status request from keyboard. Note several operating systems (Linux in particular) do not support this signal. os:set_signal/2 will thow a badarg exception if support is missing.

Setting OS signals are described in os:set_signal/2.

Configuration

The following configuration parameters are defined for the Kernel application. For more information about configuration parameters, see file app.

connect_all = true | false - If enabled (true), which also is the default, global will actively connect to all nodes that becomes known to it. Note that you also want to enable prevent_overlapping_partitions in order for global to ensure that a fully connected network is maintained. prevent_overlapping_partitions will also prevent inconsistencies in global's name registration and locking.

The now deprecated command line argument -connect_all <boolean> has the same effect as the connect_all configuration parameter. If this configuration parameter is defined, it will override the command line argument.

distributed = [Distrib] - Specifies which applications that are distributed and on which nodes they are allowed to execute. In this parameter:

Distrib = {App,Nodes} | {App,Time,Nodes}

App = atom()

Time = integer()>0

Nodes = [node() | {node(),...,node()}]

The parameter is described in application:load/2.

dist_auto_connect = Value - Specifies when nodes are automatically connected. If this parameter is not specified, a node is always automatically connected, for example, when a message is to be sent to that node. Value is one of:

never - Connections are never automatically established, they must be explicitly connected. See net_kernel.

once - Connections are established automatically, but only once per node. If a node goes down, it must thereafter be explicitly connected. See net_kernel.

epmd_module = module() - Configures the module responsible for communication with epmd. If this parameter is undefined, it defaults to erl_epmd.

The now deprecated command line argument -epmd_module <module> has the same effect as the epmd_module configuration parameter. If this configuration parameter is defined, it will override the command line argument.

erl_epmd_node_listen_port = integer() - Configures the port used by erl_epmd to listen for connection and connect to other nodes. If this flag is set, the Erlang VM will boot in distributed mode even if EPMD is not available. If not set, a port is chosen automatically (equivalent to port 0). See erl_epmd for more details.

The now deprecated command line argument erl_epmd_port <module> has the same effect as the erl_epmd_node_listen_port configuration parameter. If this configuration parameter is defined, it will override the command line argument.

permissions = [Perm] - Specifies the default permission for applications when they are started. In this parameter:

Perm = {ApplName,Bool}

ApplName = atom()

Bool = boolean()

Permissions are described in application:permit/2.

logger = [Config] - Specifies the configuration for Logger, except the primary log level, which is specified with logger_level, and the compatibility with SASL Error Logging, which is specified with logger_sasl_compatible.

The loggerparameter is described in section Logging in the Kernel User's Guide.

logger_level = Level - Specifies the primary log level for Logger. Log events with the same, or a more severe level, pass through the primary log level check. See section Logging in the Kernel User's Guide for more information about Logger and log levels.

Level = emergency | alert | critical | error | warning | notice | info | debug | all | none

To change the primary log level at runtime, use logger:set_primary_config(level, Level).

Defaults to notice.

logger_metadata = Metadata - Specifies primary metadata for log events.

Metadata = map()

Defaults to #{}.

logger_sasl_compatible = true | false - Specifies if Logger behaves backwards compatible with the SASL error logging functionality from releases prior to Erlang/OTP 21.0.

If this parameter is set to true, the default Logger handler does not log any progress-, crash-, or supervisor reports. If the SASL application is then started, it adds a Logger handler named sasl, which logs these events according to values of the SASL configuration parameter sasl_error_logger and sasl_errlog_type.

See section Deprecated Error Logger Event Handlers and Configuration in the sasl(6) manual page for information about the SASL configuration parameters.

See section SASL Error Logging in the SASL User's Guide, and section Backwards Compatibility with error_logger in the Kernel User's Guide for information about the SASL error logging functionality, and how Logger can be backwards compatible with this.

Defaults to false.

Note

If this parameter is set to true, sasl_errlog_type indicates that progress reports shall be logged, and the configured primary log level is notice or more severe, then SASL automatically sets the primary log level to info. That is, this setting can potentially overwrite the value of the Kernel configuration parameter logger_level. This is to allow progress reports, which have log level info, to be forwarded to the handlers.

global_groups = [GroupTuple] - Defines global groups, see global_group. In this parameter:

GroupTuple = {GroupName, [Node]} | {GroupName, PublishType, [Node]}

GroupName = atom()

PublishType = normal | hidden

Node = node()

inet_default_connect_options = [{Opt, Val}] - Specifies default options for connect sockets, see inet.

inet_default_listen_options = [{Opt, Val}] - Specifies default options for listen (and accept) sockets, see inet.

inet_dist_use_interface = ip_address() - If the host of an Erlang node has many network interfaces, this parameter specifies which one to listen on. For the type definition of ip_address(), see inet.

inet_dist_listen_min = First
inet_dist_listen_max = Last
Defines the First..Last port range for the listener socket of a distributed Erlang node.

inet_dist_listen_options = Opts - Defines a list of extra socket options to be used when opening the listening socket for a distributed Erlang node. See gen_tcp:listen/2.

inet_dist_connect_options = Opts - Defines a list of extra socket options to be used when connecting to other distributed Erlang nodes. See gen_tcp:connect/4.

inet_parse_error_log = silent - If set, no log events are issued when erroneous lines are found and skipped in the various Inet configuration files.

inetrc = Filename - The name (string) of an Inet user configuration file. For details, see section Inet Configuration in the ERTS User's Guide.

net_setuptime = SetupTime - SetupTime must be a positive integer or floating point number, and is interpreted as the maximum allowed time for each network operation during connection setup to another Erlang node. The maximum allowed value is 120. If higher values are specified, 120 is used. Default is 7 seconds if the variable is not specified, or if the value is incorrect (for example, not a number).

Notice that this value does not limit the total connection setup time, but rather each individual network operation during the connection setup and handshake.

log_missed_net_ticks = true | false - Controls whether a warning is logged for each missed sub-tick on a distribution connection. A sub-tick is missed when no data has been received from a connected node during one tick interval. A warning is emitted on every subsequent missed sub-tick until the node is declared down after net_tickintensity consecutive missed sub-ticks, at which point a final timeout warning is always logged regardless of this setting. Defaults to false.

net_ticker_spawn_options = Opts - Defines a list of extra spawn options for net ticker processes. There exist one such process for each connection to another node. A net ticker process is responsible for supervising the connection it is associated with. These processes also execute the distribution handshake protocol when setting up connections. When there is a large number of distribution connections, setting up garbage collection options can be helpful to reduce memory usage. Default is [link, {priority, max}], and these two options cannot be changed. The monitor and {monitor, MonitorOpts} options are not allowed and will be dropped if present. See the documentation of the erlang:spawn_opt/4 BIF for information about valid options. If the Opts list is not a proper list, or containing invalid options the setup of connections will fail.

Note that the behavior described above is only true if the distribution carrier protocol used is implemented as described in ERTS User's Guide ➜ How to implement an Alternative Carrier for the Erlang Distribution ➜ Distribution Module without further alterations. The implementer of the distribution carrier protocol used, may have chosen to ignore the net_ticker_spawn_options parameter or altered its behavior. Currently all distribution modules shipped with OTP do, however, behave as described above.

net_tickintensity = NetTickIntensity - Net tick intensity specifies how many ticks to send during a net tick time period when no other data is sent over a connection to another node. This also determines how often to check for data from the other node. The higher net tick intensity, the closer to the chosen net tick time period the node will detect an unresponsive node. The net tick intensity defaults to 4. The value of NetTickIntensity should be an integer in the range 4..1000. If the NetTickIntensity is not an integer or an integer less than 4, 4 will silently be used. If NetTickIntensity is an integer larger than 1000, 1000 will silently be used.

Note

Note that all communicating nodes are expected to use the same net tick intensity as well as the same net tick time.

Warning

Be careful not to set a too high net tick intensity, since you can overwhelm the node with work if it is set too high.

net_ticktime = NetTickTime - Specifies the net tick time in seconds. This is the approximate time a connected node may be unresponsive until it is considered down and thereby disconnected.

Net tick time together with net tick intensity determines an interval TickInterval = NetTickTime/NetTickIntensity. Once every TickInterval seconds, each connected node is ticked if nothing has been sent to it during that last TickInterval seconds. A tick is a small package sent on the connection. A connected node is considered to be down if no ticks or payload packages have been received during the last NetTickIntensity number of TickInterval seconds intervals. This ensures that nodes that are not responding, for reasons such as hardware errors, are considered to be down.

As the availability is only checked every TickInterval seconds, the actual time T a node have been unresponsive when detected may vary between MinT and MaxT, where:

MinT = NetTickTime - NetTickTime / NetTickIntensity
MaxT = NetTickTime + NetTickTime / NetTickIntensity

NetTickTime defaults to 60 seconds and NetTickIntensity defaults to 4. Thus, 45 < T < 75 seconds.

Note

Notice that all communicating nodes are to have the same NetTickTime and NetTickIntensity values specified, as it determines both the frequency of outgoing ticks and the expected frequency of incominging ticks.

NetTickTime needs to be a multiple of NetTickIntensity. If the configured values are not, NetTickTime will internally be rounded up to the nearest millisecond. net_kernel:get_net_ticktime() will, however, report net tick time truncated to the nearest second.

Normally, a terminating node is detected immediately by the transport protocol (like TCP/IP).

prevent_overlapping_partitions = true | false - If enabled (true), global will actively prevent overlapping partitions from forming when connections are lost between nodes. This fix is enabled by default. If you are about to disable this fix, make sure to read the global documentation about this fix for more important information about this.

shutdown_timeout = integer() | infinity - Specifies the time application_controller waits for an application to terminate during node shutdown. If the timer expires, application_controller brutally kills application_master of the hanging application. If this parameter is undefined, it defaults to infinity.

sync_nodes_mandatory = [NodeName] - Specifies which other nodes that must be alive for this node to start properly. If some node in the list does not start within the specified time, this node does not start either. If this parameter is undefined, it defaults to [].

sync_nodes_optional = [NodeName] - Specifies which other nodes that can be alive for this node to start properly. If some node in this list does not start within the specified time, this node starts anyway. If this parameter is undefined, it defaults to the empty list.

sync_nodes_timeout = integer() | infinity - Specifies the time (in milliseconds) that this node waits for the mandatory and optional nodes to start. If this parameter is undefined, no node synchronization is performed. This option ensures that global is synchronized.

start_distribution = true | false - Starts all distribution services, such as rpc, global, and net_kernel if the parameter is true. This parameter is to be set to false for systems who want to disable all distribution functionality.

Defaults to true.

start_dist_ac = true | false - Starts the dist_ac server if the parameter is true. This parameter is to be set to true for systems using distributed applications.

Defaults to false. If this parameter is undefined, the server is started if parameter distributed is set.

start_boot_server = true | false - Starts the boot_server if the parameter is true (see erl_boot_server). This parameter is to be set to true in an embedded system using this service.

Defaults to false.

boot_server_slaves = [SlaveIP] - If configuration parameter start_boot_server is true, this parameter can be used to initialize boot_server with a list of slave IP addresses:

SlaveIP = string() | atom | {integer(),integer(),integer(),integer()},

where 0 <= integer() <=255.

Examples of SlaveIP in atom, string, and tuple form:

'150.236.16.70', "150,236,16,70", {150,236,16,70}.

Defaults to [].

start_disk_log = true | false - Starts the disk_log_server if the parameter is true (see disk_log). This parameter is to be set to true in an embedded system using this service.

Defaults to false.

start_pg = true | false - Starts the default pg scope server (see pg) if the parameter is true. This parameter is to be set to true in an embedded system that uses this service.

Defaults to false.

start_timer = true | false - Starts the timer_server if the parameter is true (see timer). This parameter is to be set to true in an embedded system using this service.

Defaults to false.

shell_docs_ansi = boolean() - Specifies whether the documentation rendered in the shell should use ANSI escape codes.

See also shell_docs:config/0.

shell_history = enabled | disabled | module() - Specifies whether shell history should be logged to disk between usages of erl (enabled), not logged at all (disabled), or a user-specified module will be used to log shell history. This module should export load() -> [string()] returning a list of strings to load in the shell when it starts, and add(iodata()) -> ok. called every time new line is entered in the shell. By default logging is disabled.

shell_history_drop = [string()] - Specific log lines that should not be persisted. For example ["q().", "init:stop()."] will allow to ignore commands that shut the node down. Defaults to [].

shell_history_file_bytes = integer() - How many bytes the shell should remember. By default, the value is set to 512kb, and the minimal value is 50kb.

shell_history_path = string() - Specifies where the shell history files will be stored. defaults to the user's cache directory as returned by filename:basedir(user_cache, "erlang-history").

shutdown_func = {Mod :: atom(), Func :: atom()} - Sets a function that application_controller calls when it starts to terminate. The function is called as Mod:Func(Reason), where Reason is the terminate reason for application_controller, and it must return as soon as possible for application_controller to terminate properly.

source_search_rules = [DirRule] | [SuffixRule]

Where:

DirRule = {ObjDirSuffix,SrcDirSuffix}

SuffixRule = {ObjSuffix,SrcSuffix,[DirRule]}

ObjDirSuffix = string()

SrcDirSuffix = string()

ObjSuffix = string()

SrcSuffix = string()

Specifies a list of rules for use by filelib:find_file/2 filelib:find_source/2 If this is set to some other value than the empty list, it replaces the default rules. Rules can be simple pairs of directory suffixes, such as {"ebin", "src"}, which are used by filelib:find_file/2, or triples specifying separate directory suffix rules depending on file name extensions, for example [{".beam", ".erl", [{"ebin", "src"}]}, which are used by filelib:find_source/2. Both kinds of rules can be mixed in the list.

The interpretation of ObjDirSuffix and SrcDirSuffix is as follows: if the end of the directory name where an object is located matches ObjDirSuffix, then the name created by replacing ObjDirSuffix with SrcDirSuffix is expanded by calling filelib:wildcard/1, and the first regular file found among the matches is the source file.

standard_io_encoding = Encoding - Set whether bytes sent or received via standard_io should be interpreted as unicode or latin1. By default input and output is interpreted as Unicode if it is supported on the host. With this flag you may configure the encoding on startup.

This works similarly to io:setopts(standard_io, {encoding, Encoding}) but is applied before any bytes on standard_io may have been read.

Encoding is one of:

unicode - Configure standard_io to use unicode mode.

latin1 - Configure standard_io to use latin1 mode.

_ - Anything other than unicode or latin1 will be ignored and the system will configure the encoding by itself, typically unicode on modern systems.

See Escripts and non-interactive I/O in Unicode Usage in Erlang for more details.

os_cmd_shell = string() - Specifies which shell to use when invoking system commands via os:cmd/2. By default the shell is detected automatically.

Deprecated Configuration Parameters

In Erlang/OTP 21.0, a new API for logging was added. The old error_logger event manager, and event handlers running on this manager, still work, but they are no longer used by default.

The following application configuration parameters can still be set, but they are only used if the corresponding configuration parameters for Logger are not set.

error_logger - Replaced by setting the type, and possibly file and modes parameters of the default logger_std_h handler. Example:

erl -kernel logger '[{handler,default,logger_std_h,#{config=>#{file=>"/tmp/erlang.log"}}}]'

error_logger_format_depth - Replaced by setting the depth parameter of the default handlers formatter. Example:

erl -kernel logger '[{handler,default,logger_std_h,#{formatter=>{logger_formatter,#{legacy_header=>true,template=>[{logger_formatter,header},"\n",msg,"\n"],depth=>10}}}]'

See Backwards compatibility with error_logger for more information.

Kernel Release Notes

This document describes the changes made to the Kernel application.

Kernel 11.0

Fixed Bugs and Malfunctions

Fixed (inet) module selection when calling (gen_tcp) listen and connect and (gen_udp) open. Depending on the order of the options, the module option (tcp_module or udp_module) was sometimes ignored.

POTENTIAL INCOMPATIBILITY

Own Id: OTP-19695 Aux Id: GH-9822, PR-10013

The TCP/UDP compatibility layer has been fixed so that inet_backend = socket now supports socket options reuseport and reuseport_lb for gen_tcp and gen_udp.

Own Id: OTP-19917 Aux Id: PR-10514

Some errors in config files for the application controller would result in very cryptic crashes. Error handling has been improved to ensure that the file name and line number of the offending token are now printed.

Own Id: OTP-20054 Aux Id: GH-10214, PR-10259

The TOS handling on socket has been significantlyupdated and improved. Socket did not properly handle set, get and recv (cmsg) of TOS.

Note that the returned TOS value has been changed. It was previously an atom or an integer. Now it is a map with different interpretations of the TOS octet. See the documentation.

POTENTIAL INCOMPATIBILITY

Own Id: OTP-20102 Aux Id: GH-10968, PR-11059

Replaced a sleep clause in user_drv shutdown with a flush of the output buffer.

Own Id: OTP-20124 Aux Id: PR-10808

Improvements and New Features

Added an option to set the erl_boot_server listen port.

Own Id: OTP-19708 Aux Id: PR-9894

The memory footprint of some supervisors has been reduced by purging obsoleted data when the supervisor is transitioning to and from hibernation.

Own Id: OTP-19713 Aux Id: PR-9866

Improved name consistency of EPMD protocol messages in documentation and code. Renamed PORT_PLEASE2_REQ to PORT2_REQ and added prefix EPMD_.

Own Id: OTP-19734 Aux Id: GH-10071, PR-10078

The legacy and and or operators have been replaced with other language constructs.

Own Id: OTP-19744 Aux Id: PR-10114, PR-10554, PR-10568, PR-10579, PR-10585, PR-10598, PR-10710, PR-10718, PR-10580, PR-10730

Refactored a kernel_load_completed clause in the init module for conciseness.

Own Id: OTP-19786 Aux Id: PR-10134

Full support for SCTP in socket. Not (yet) supported for FreeBSD.

Own Id: OTP-19834

In the default code path for the Erlang system, the current working directory (.) is now in the last position instead of the first.

POTENTIAL INCOMPATIBILITY

Own Id: OTP-19842

It was previously not possible to check on the socket nif load result. A successful load was self-evident, but a failure was only visible from the fact that most socket functions failed with notsup. This has now been improved such that the (socket nif) load result is visible in the info map (from socket:info/0).

Own Id: OTP-20003

Added support for socket functions recvmmsg() and sendmmsg().

Own Id: OTP-20015 Aux Id: PR-10564

Added a new module called io_ansi that allows the user to emit Virtual Terminal Sequences (a.k.a. ANSI sequences) to the terminal in order to add colors/styling to text or create fully-fledged terminal applications.

io_ansi uses the local terminfo database in order to be as cross-platform compatible as possible.

It also works across nodes so that if functions on a remote node call io_ansi:fwrite/1 it will use the destination terminal's terminfo database to determine which sequences to emit. In practice, this means that you can call functions in a remote shell session that use io_ansi and it will properly detect the terminal sequences the target terminal can handle and will print using them correctly.

Own Id: OTP-20028 Aux Id: PR-9940, PR-10905

Polished the documentation groups, essentially removed groups that did nothing but obscure the documentation.

Own Id: OTP-20029 Aux Id: PR-10755

Added a new behavior, data_publisher, for building eventually consistent, replicated data stores across distributed nodes. This is a generalization of the pg module.

Own Id: OTP-20055 Aux Id: PR-10426

Added support for -unsafe attributes, which is used to mark functions as unsafe to use.

This is similar to but separate from deprecation, and the compiler will by default now generate warnings for calls to functions in Erlang/OTP that are known to be always unsafe.

Furthermore, xref can now be used to find calls to functions in another application that lack a -doc attribute (undocumented_function_calls), calls to functions in another application marked -doc false. (private_function_calls), as well as calls to unsafe functions (unsafe_function_calls).

Own Id: OTP-20066 Aux Id: PR-10839

When implementing an alternate distribution implementors can now use an alternate handshake complete fun of arity 4 if needed.

Own Id: OTP-20090 Aux Id: PR-10478

Added support for socket option SO_TIMESTAMPNS (not available on all platforms).

Own Id: OTP-20115 Aux Id: PR-10929

Added a flag log_missed_net_ticks = true | false that controls whether a warning is logged for each missed sub-tick on a distribution connection. A sub-tick is missed when no data has been received from a connected node during one tick interval. A warning is emitted on every subsequent missed sub-tick until the node is declared down after net_tickintensity consecutive missed sub-ticks, at which point a final timeout warning is always logged regardless of this setting. Defaults to false.

Own Id: OTP-20117 Aux Id: PR-11031

Kernel 10.6.3

Fixed Bugs and Malfunctions

On Windows, sockets has to be bound when using 'socket'. Therefor when using gen_tcp with inet_backend = socket, gen_tcp_socket bind even if the caller has not provided an explicit bind address. In that case it attempts to locate a "proper" address on its own. But if the connect address is the loopback address, this could lead to an attempt to bind to an external interface. So, this has now been changed so that if the connect address is the loopback address, the loopback address will also be used when binding.

Own Id: OTP-20104 Aux Id: #10968

Kernel 10.6.2

Fixed Bugs and Malfunctions

Before this patch, the Erlang/OTP built-in DNS resolver (inet_res) used a sequential, process-global 16-bit transaction ID for UDP queries and did not implement source port randomization. Response validation relied almost entirely on this ID. Together, this made DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. The design conflicted with RFC 5452 recommendations for mitigating forged DNS answers.

inet_res is intended for use in trusted network environments and with trusted recursive resolvers. Earlier documentation did not clearly state this deployment assumption, which could lead users to deploy the resolver in environments where faked DNS responses are possible.

Therefore, the documentation is been updated to clarify that inet_res should only be used in trusted networks and with trusted recursive resolvers.

The implementation is also improved to use strong random DNS transaction IDs and source ports for every DNS transaction. This should give ample protection against brute forcing fake DNS replies, known as DNS cache poisoning, but it still does not protect against, for example, an adversary in the path of the DNS transaction that can observe the random values before faking malicious replies, an attack known as DNS spoofing.

For randomization to happen, the Crypto application has to be loaded, which most probably already should be the case for an Erlang node in an exposed network.

If performance should become an issue, for applications within safe network environments, the previous light weight behaviour can be configured by setting the resolver option random to false.

Own Id: OTP-20037 Aux Id: CVE-2026-28810, PR-10864

Kernel 10.6.1

Fixed Bugs and Malfunctions

A vulnerability has been resolved in the (undocumented, unsupported and unused in OTP) inet_dns_tsig module that leads to a validation bypass.

If a request contained an error code (forbidden by spec), it was treated as a response and skipped the verification of the MAC. The user of the module would then receive an "all ok" response, depending on the use case, this could lead to such things as AXFR or UPDATE being allowed.

The code has also been tightening up of the client side to make sure too large (bad) MAC sizes cannot be selected and the limit is the output size of the algorithm chosen.

Own Id: OTP-20012 Aux Id: PR-10825

Kernel 10.6

Fixed Bugs and Malfunctions

The built in DNS resolver inet_res has been fixed to do a final request assuming that the request name is absolute, as customary for many DNS resolver client libraries.

Own Id: OTP-19937 Aux Id: GH-10494, PR-10576

Improvements and New Features

Added support for zstd compression in the file module.

Own Id: OTP-19860 Aux Id: PR-10385

Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

make release_docs places the documentation in the released code under the doc folder.

make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

Improves the source Software-Bill-of-Materials

The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.

The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.

All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

Own Id: OTP-19886 Aux Id: PR-10434

Kernel 10.5

Fixed Bugs and Malfunctions

Fixed a shell crash when calling io:getopts() when user_drv process is not responding/terminating

Own Id: OTP-19812 Aux Id: PR-10283

logger:get_handler_config/0 will no longer crash if a logger handler is removed concurrently with that call.

Own Id: OTP-19837 Aux Id: PR-10308, GH-9997

Fixed a bug in the shell that made it incorrectly output a newline after the output already containing a newline but followed by an asci escape sequence.

Own Id: OTP-19847 Aux Id: GH-10299

Improvements and New Features

Receive buffer allocation has been optimized for socket socket in that an underutilized buffers' content is copied to a freshly allocated binary of the right size instead of being reallocated.

This optimization was already implemented for the socket:recv/1 functions, but now the same buffer stragegy is shared between all socket receive operations.

Own Id: OTP-19794 Aux Id: PR-10231

Option(s) to create gen_tcp and socket sockets with protocol IPPROTO_MPTCP has been implemented.

See functions gen_tcp:listen/2, gen_tcp:connect/4 and the type socket:protocol/0.

Own Id: OTP-19814

Support for the socket options TCP_KEEPCNT, TCP_KEEPIDLE, and TCP_KEEPINTVL have been implemented for gen_tcp, as well as TCP_USER_TIMEOUT for both gen_tcp and socket.

Own Id: OTP-19857 Aux Id: OTP-19814, PR-10390

Limit size of sctp_event_subscribe on Linux

Own Id: OTP-19863 Aux Id: PR-10321

Kernel 10.4.2

Fixed Bugs and Malfunctions

Fixed a race condition when registering the standard error process.

Own Id: OTP-19832 Aux Id: PR-10290

Kernel 10.4.1

Fixed Bugs and Malfunctions

With this change group.erl will not crash when receiving unknown message.

Own Id: OTP-19796 Aux Id: ERIERL-1264, PR-10248

Kernel 10.4

Fixed Bugs and Malfunctions

A remote shell can now exit by closing the input stream, without terminating the remote node.

Own Id: OTP-19667 Aux Id: PR-9912

The internal inet_dns_tsig and inet_res modules have been fixed to TSIG verify the correct timestamp.

In the process two undocumented error code atoms have been corrected to notauth and notzone to adhere to the DNS RFCs. Code that relied on the previous incorrect values may have to be corrected.

POTENTIAL INCOMPATIBILITY

Own Id: OTP-19756 Aux Id: PR-10146

Improvements and New Features

The rudimentary DNS resolver inet_res has aqcuired 3 new functions inet_res:gethostbyname/4, inet_res;getbyname/4 and inet_res:gethostbyaddr/3, that all take an option list argument.

This option list can be used to override the Kernel application's resolver options when calling the inet_res function directly.

Own Id: OTP-19737 Aux Id: ERIERL-1209, PR-10112

Kernel 10.3.2

Fixed Bugs and Malfunctions

socket:sendv/3 with 'nowait' sometimes return 'completion' without 'CompletionInfo' (Windows only).

Own Id: OTP-19661

prim_net nif used incorrect encoding for family resulting in non-functional address selection.

Own Id: OTP-19674

socket:accept can return unexpected 'select_sent'.

Own Id: OTP-19684 Aux Id: ERIERL-1242

net_kernel could be blocked for a very long time when selecting distribution module for a connection if the DNS service was slow. This prevented any new connections to be set up during that time.

Own Id: OTP-19702 Aux Id: ERIERL-1241, PR-10029

Improvements and New Features

Improved documentation of CompletionStatus for asynchronous (nowait) socket operations.

Own Id: OTP-19670 Aux Id: PR-9930

Kernel 10.3.1

Fixed Bugs and Malfunctions

Fix bug where calling io:setopts/1 in a shell without the line_history option would always disable line_history. This bug was introduced in Erlang/OTP 28.0.

Own Id: OTP-19645 Aux Id: GH-9863, PR-9870

Kernel 10.3

Fixed Bugs and Malfunctions

Fixed an issue where output to the shell would not print the prompt on a new line.

Own Id: OTP-19228 Aux Id: PR-8820

When in shell is in -noshell mode, and in latin1 encoding mode, io requests in latin1 encoding will not be translated to unicode and back to latin1.

Own Id: OTP-19296 Aux Id: PR-9013

Fixed a bug where a composing unicode character would bind to a character not available to the user and deleting that character would cause a crash.

Own Id: OTP-19297 Aux Id: PR-9005

The -noshell mode has been updated to read data lazily from standard input. Before this fix any data would be read greedily which meant that Erlang could consume data not meant for it. It also meant that in order for shell:start_interactive/0 to work on Windows an API that did not support reading of Unicode characters had to be used.

Own Id: OTP-19313 Aux Id: PR-8962, GH-8113

The Erlang shell no longer crashes when a shell prompt ends with an escape sequence.

Own Id: OTP-19414 Aux Id: PR-9272

code:get_doc/1 now works for cover-compiled modules.

Own Id: OTP-19513 Aux Id: PR-9433

An infinite loop in CNAME loop detection that can cause Out Of Memory has been fixed. This affected CNAME lookup with the internal DNS resolver.

Own Id: OTP-19544 Aux Id: PR-9587, OTP-19545

The internal resolver framework has been fixed to wait with the first resolver lookup until the ERL_INETRC environment variable has been applied.

Previously, on some platform(s) (Linux) a first lookup when figuring out the domain name was always placed on the native resolver even if ERL_INETRC was used to disable it.

Own Id: OTP-19555 Aux Id: PR-9543

Fix logger:add_handler(default, ...) to correctly replay events generated during startup when the default logger is set to undefined in logger's configuration parameters.

Own Id: OTP-19588 Aux Id: PR-9595, GH-9436

Enhance specs of timeout for improving documentation and dialyzer analysis.

Own Id: OTP-19604 Aux Id: PR-9574

Removed the default values for SCTP send (sndbuf) and receive (recbuf) buffers.

Own Id: OTP-19627 Aux Id: OTP-19576, GH-9722

Improvements and New Features

application:load/1 slows down as the number of directories in the code path increases because the call to code:where_is_file/1 for the '.app' file must scan each directory for the app.

code_server maintains a cache of the contents of directories in the path. Re-using that cache when searching for '.app' files in application:load/1 may improve its runtime, especially when loading multiple applications.

Own Id: OTP-19194 Aux Id: PR-8078

The Erlang SSH daemon now uses the same backend to handle multiline functionality as the Erlang shell.

Own Id: OTP-19226 Aux Id: PR-8805

Added support for SIGWINCH, SIGCONT, and SIGINFO signals to os:set_signal/2 where available.

Own Id: OTP-19278 Aux Id: PR-8887, PR-8938

Add net_kernel:allowed/0, it returns a list of nodes that are explicitly allowed to connect to the node by calling net_kernel:allow/1

Own Id: OTP-19287 Aux Id: PR-8207

Documentation chunks (EEP-48) has been updated to include the following reserved metadata fields: behaviours, group, source_path, and source_annos. The compiler has also been updated to emit this metadata. See the EEP-48 documentation for more details.

Own Id: OTP-19306 Aux Id: PR-8945, PR-8975

The erpc:call/3, erpc:call/5, erpc:multicall/3, and erpc:multicall/5 functions now also accept an option map as last argument containing the timeout and always_spawn options. The always_spawn option can be used in order to ensure that the call operation will use a newly spawned process when executing the remote call.

Own Id: OTP-19343 Aux Id: PR-8642

EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

-type meter() :: integer().
-type foot() :: integer().

Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

-nominal meter() :: integer().
-nominal foot() :: integer().

More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

Own Id: OTP-19364 Aux Id: PR-9079

Improved open debug for gen_tcp_socket (connect and listen) and gen_udp_socket (open).

Own Id: OTP-19386

io:standard_error/0 has been updated to write via a NIF API instead of a port. This allows it to access the dirty-scheduler pool and make sure that writes have been written to the OSs stderr when io:format/3 and equivalent return.

Own Id: OTP-19401 Aux Id: PR-9116

Added the option exception_on_failure to os:cmd/2 to make os:cmd/2 raise an exception if the command fails to execute.

Own Id: OTP-19404 Aux Id: PR-9082

A socket option {otp,select_read} has been added that enables keeping a socket in the VM select/poll set between calls to recv functions.

This increases throughput by reducing the number of calls to said functions.

Own Id: OTP-19451 Aux Id: PR-9344

Add a configure chapter to the socket usage guide

Own Id: OTP-19522 Aux Id: PR-9508

The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

Own Id: OTP-19575 Aux Id: PR-9670

Increase the default inet-driver buffer size(s). Also introduce kernel parameters for UDP and SCTP to change the sizes when creating (those) sockets.

Own Id: OTP-19576

An experimental API for a native debugger has been added. The main components are the following:

A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

Kernel 10.2.7.4

Fixed Bugs and Malfunctions

Before this patch, the Erlang/OTP built-in DNS resolver (inet_res) used a sequential, process-global 16-bit transaction ID for UDP queries and did not implement source port randomization. Response validation relied almost entirely on this ID. Together, this made DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. The design conflicted with RFC 5452 recommendations for mitigating forged DNS answers.

inet_res is intended for use in trusted network environments and with trusted recursive resolvers. Earlier documentation did not clearly state this deployment assumption, which could lead users to deploy the resolver in environments where faked DNS responses are possible.

Therefore, the documentation is been updated to clarify that inet_res should only be used in trusted networks and with trusted recursive resolvers.

The implementation is also improved to use strong random DNS transaction IDs and source ports for every DNS transaction. This should give ample protection against brute forcing fake DNS replies, known as DNS cache poisoning, but it still does not protect against, for example, an adversary in the path of the DNS transaction that can observe the random values before faking malicious replies, an attack known as DNS spoofing.

For randomization to happen, the Crypto application has to be loaded, which most probably already should be the case for an Erlang node in an exposed network.

If performance should become an issue, for applications within safe network environments, the previous light weight behaviour can be configured by setting the resolver option random to false.

Own Id: OTP-20037 Aux Id: CVE-2026-28810, PR-10864

Kernel 10.2.7.3

Improvements and New Features

Option(s) to create gen_tcp and socket sockets with protocol IPPROTO_MPTCP has been implemented.

See functions gen_tcp:listen/2, gen_tcp:connect/4 and the type socket:protocol/0.

Own Id: OTP-19814

Kernel 10.2.7.2

Fixed Bugs and Malfunctions

socket:sendv/3 with 'nowait' sometimes return 'completion' without 'CompletionInfo' (Windows only).

Own Id: OTP-19661

socket:accept can return unexpected 'select_sent'.

Own Id: OTP-19684 Aux Id: ERIERL-1242

net_kernel could be blocked for a very long time when selecting distribution module for a connection if the DNS service was slow. This prevented any new connections to be set up during that time.

Own Id: OTP-19702 Aux Id: ERIERL-1241, PR-10029

Improvements and New Features

Improved documentation of CompletionStatus for asynchronous (nowait) socket operations.

Own Id: OTP-19670 Aux Id: PR-9930

Kernel 10.2.7.1

Fixed Bugs and Malfunctions

A remote shell can now exit by closing the input stream, without terminating the remote node.

Own Id: OTP-19667 Aux Id: PR-9912

Improvements and New Features

Document default buffer sizes

Own Id: OTP-19640 Aux Id: GH-9722

Kernel 10.2.7

Fixed Bugs and Malfunctions

With this change, disk_log will not crash when using chunk_step/3 after log size was decreased.

Own Id: OTP-19605 Aux Id: GH-9720, PR-9765

With this change, disk_log will not run into infinite loop when using chunk/2,3 after log size was decreased.

Own Id: OTP-19608 Aux Id: GH-9707, PR-9767

Kernel 10.2.6

Fixed Bugs and Malfunctions

Fixed bug in call_memory tracing that could cause wildly incorrect reported memory values. Bug exists since OTP 27.1.

Also fixed return type spec of trace:info/3.

Own Id: OTP-19581 Aux Id: ERIERL-1219, PR-9706

Kernel 10.2.5

Fixed Bugs and Malfunctions

On Windows, using socket:sendv, a large IOV (size > MAX), the tail was not sent.

Own Id: OTP-19482

gen_tcp connect with a sockaddr with loopback address failed.

Own Id: OTP-19560 Aux Id: GH-9541

Remove debug printouts from gen_tcp_socket

Own Id: OTP-19564

Kernel 10.2.4

Fixed Bugs and Malfunctions

Behavior for socket:recv/3 has been improved. The behavior has also been clarified in the documentation.

Own Id: OTP-19469 Aux Id: #9172

An infinite loop in CNAME loop detection that can cause Out Of Memory has been fixed. This affected CNAME lookup with the internal DNS resolver.

Own Id: OTP-19545 Aux Id: PR-9587, OTP-19544

Kernel 10.2.3

Fixed Bugs and Malfunctions

Clarify inet:setopts documentation

Own Id: OTP-19416 Aux Id: PR-9248

Fix bug where log printouts would go missing when application_controller is stopping while log messages are being sent.

This bug was introduced by OTP-19078 in Erlang/OTP 26.2.5.

Own Id: OTP-19418 Aux Id: GH-9163, PR-9274

Fixes a bug in the socket type spec, which caused Dialyzer to reject some valid programs.

Own Id: OTP-19429 Aux Id: PR-9295, PR-9379

Kernel 10.2.2

Fixed Bugs and Malfunctions

Fixed a couple of bugs that could make global's internal state inconsistent when a connection was reconnected.

Own Id: OTP-19381 Aux Id: PR-9377, GH-9112, GH-9117

Kernel 10.2.1

Fixed Bugs and Malfunctions

Fix the default group_leader to reply {error,request} on invalid I/O requests instead of crashing.

This bug was introduced in Erlang/OTP 27.2.

Own Id: OTP-19444 Aux Id: GH-9237, PR-9318

Kernel 10.2

Fixed Bugs and Malfunctions

gen_sctp:peeloff/2 has been fixed to inherit socket options to the peeled off socket more like gen_tcp:accept/1, for example the options tos or tclass.

When setting SCTP options that are unsupported on the platform, some should be silently ignored, but a bug caused the option parsing to derail so the options after could bail out and cause an error instead. This has been fixed.

Own Id: OTP-19225 Aux Id: PR-8789

Made it possible to expand help text displayed by pressing ^[h by pressing ^[h again.

Own Id: OTP-19260 Aux Id: PR-8884

inet:getifaddrs/0,1 is improved when using inet_backend = socket.

Own Id: OTP-19264

Fixed logger:report/0 to mandate at least one element in the report. This fixes an issue with overlapping spec domains in all logger functions that use logger:report/0.

Own Id: OTP-19302 Aux Id: PR-8959

Fixed deadlock on code_server. Multiple calls loading the same module with an on_load function loading call would create a deadlock.

Own Id: OTP-19305 Aux Id: PR-8744, GH-7466, GH-8510

Improvements and New Features

The Kernel application now recognizes the epmd_module and erl_epmd_listen_port parameters, similar to -kernel:connect_all.

Own Id: OTP-19253 Aux Id: PR-8671

The inetrc kernel argument will now tolerate atoms again to improve compatibility with old configurations that relied on atoms working by accident.

The expected type always was, and still remains, a string.

Own Id: OTP-19280 Aux Id: GH-8899, PR-8902

The file:io_device/0 type has been updated to clearly show the difference between a raw and cooked IoDevice.

Own Id: OTP-19301 Aux Id: PR-8956

Erlang/OTP type specifications has been updated to eliminate overlapping domains.

Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

Added the kernel parameter os_cmd_shell that controls which shell should be used by os:cmd/1.

Own Id: OTP-19342 Aux Id: PR-8972

Added logging support to io:user/0, io:standard_io/0 and io:standard_error/0. See io:setopts/2 for more details.

Own Id: OTP-19372 Aux Id: PR-8947

Kernel 10.1.2

Fixed Bugs and Malfunctions

On windows the socket:recv could return with success ({ok, Data}) even though not all data had been read.

Own Id: OTP-19328

gen_udp:send on domain local can leak inet_reply messages.

Own Id: OTP-19332 Aux Id: #8989

Failure to create an UDP IPv6 socket when inet_backend = socket with certain IPv6 socket options.

Own Id: OTP-19357

net:getifaddrs does not properly report the running flag on windows.

Own Id: OTP-19366 Aux Id: OTP-19061, ERIERL-1134

Kernel 10.1.1

Fixed Bugs and Malfunctions

A bug has been fixed where receiving an SCTP message with gen_sctp could waste the first fragments of a message and only deliver the last fragment.

This happened with low probability when the OS signaled that the socket was ready for reading in combination with an internal time-out retry.

A bug has been fixed with a lingering time-out from after an SCTP connect that could stop the flow of incoming messages on an active gen_tcp socket.

Own Id: OTP-19235 Aux Id: ERIERL-1133, PR-8837

An boolean option non_block_send for SCTP, has ben added to be able to achieve the old behaviour to avoid blocking send operations by passing the OS network stack error message ({error,eagain} through.

Own Id: OTP-19258 Aux Id: OTP-19061, ERIERL-1134

Kernel 10.1

Fixed Bugs and Malfunctions

A faulty assertion was corrected in the prim_tty module. This assertion could trigger when invalid UTF-8 was read from stdin just as the mode was changed from unicode to latin1.

Own Id: OTP-19097 Aux Id: PR-8503

Opening a disk_log file and combining head_func with rotate options did not work.

Own Id: OTP-19104 Aux Id: ERIERL-870

Fixed an error info printout for erlang:is_process_alive/1 on non-local pids.

Own Id: OTP-19134 Aux Id: PR-8560

A race in the kTLS flavour of SSL distribution has been fixed so that inet_drv.c doesn't read ahead too much data, which could cause the kTLS encryption to be activated too late when some encrypted data had already been read into the inet_drv.c buffer as unencrypted.

Own Id: OTP-19175 Aux Id: GH-8561, PR-8690

Fixed a deadlock when an application crashes during startup and log messages were sent to standard out. Logger would fail to print the messages to standard out and instead print them to standard error.

Own Id: OTP-19205

The -proto_dist init parameter will no longer be ignored when specified multiple times. It will now log a warning and use the first specified value.

Own Id: OTP-19208 Aux Id: PR-8672

Corrected socket:ioctl for genaddr (SIOCGENADDR).

Own Id: OTP-19216

Improvements and New Features

Added functions getservbyname and getservbyport to the net module.

Own Id: OTP-19101 Aux Id: OTP-18835

Introduced enet | esock variants of inet functions, either when called with sockets, with explicit inet_backend config or with the e inet_backend kernel config option.

Own Id: OTP-19132 Aux Id: OTP-19101

The function socket:i/0 now uses the net module (instead of the inet module) for service translation.

Own Id: OTP-19138 Aux Id: OTP-19101

A boolean option read_ahead has been implemented for gen_tcp, default true, to facilitate not reading past (caching data) the end of a packet. In particular, for kTLS, caching data could read in data that was supposed to be decrypted by the platform's network stack, before crypto parameters could be activated.

Own Id: OTP-19199 Aux Id: OTP-19175, GH-8561, GH-8690, GH-8785

Kernel 10.0.1

Improvements and New Features

Polish the logger documentation.

Own Id: OTP-19118 Aux Id: PR-8534

Kernel 10.0

Fixed Bugs and Malfunctions

Fixed a crash when calling file:delete/2 with an empty option list.

Own Id: OTP-18590 Aux Id: PR-7220

New functions have been added to the undocumented module m:inet_dns that take a flag to specify if encode/decode is for mDNS. This affects how CLASS values in the private range, with the top bit set, are handled.

Own Id: OTP-18878 Aux Id: GH-7718, OTP-17734

The error information for erlang:phash/2 has been corrected.

Own Id: OTP-18904 Aux Id: PR-7960

get_until requests using the I/O protocol now correctly return a binary or list when eof is the last item returned by the callback.

Own Id: OTP-18930 Aux Id: PR-7993, GH-4992

Calling logger:add_handlers/1 with config option now works.

Own Id: OTP-18954 Aux Id: GH-8061, PR-8076

The code:del_path/1 function now also works on paths added through -pa, -pz , -path and the boot script.

Own Id: OTP-18959 Aux Id: GH-6692, PR-7697

A call to socket:[recv|recvfrom|recvmsg]/* with Timeout = 0 on Windows could cause a (case clause) crash if data is immediately available.

Own Id: OTP-19063 Aux Id: OTP-18835

Improve heuristic for when a characters is wide in the shell for systems with old libc versions.

Own Id: OTP-19087 Aux Id: PR-8382

Fix reading a line when reading from io:user/0 to not consider \r without \n to be a new line when erl is started with -noshell.

Own Id: OTP-19088 Aux Id: PR-8396, GH-8360

Improvements and New Features

Added file:read_file/2 with a raw option for reading files without going through the file server.

Own Id: OTP-18589 Aux Id: PR-7220

The undocumented Erlang DNS resolver library (inet_dns and inet_res) has been augmented to handle IXFR, NOTIFY, UPDATE and TSIG records. With this some bug fixes and code cleanup has been done, and the resolver used in the test suite has been changed to Knot DNS. See the source code.

Kudos to Alexander Clouter that did almost all the work!

Own Id: OTP-18713 Aux Id: PR-6985, GH-6985

The ebin directories for escripts are now cached.

Own Id: OTP-18778 Aux Id: PR-7556

-callback attributes haven been added to application, logger_handler, and logger_formatter.

Own Id: OTP-18795 Aux Id: PR-7703

Progress reports from before logger is started are now logged when log level is set to debug.

Own Id: OTP-18807 Aux Id: PR-7732 ERIERL-985

The code:where_is_file/2 and code:which/1 functions now check for existence of the file directly instead of listing the content of each directory in the code path.

Own Id: OTP-18816 Aux Id: PR-7711

Type specs has been added to the logger:Level/1,2,3 functions.

Own Id: OTP-18820 Aux Id: PR-7779

For inet_backend = socket, setting the active socket option alone, to once, true or N has been optimized, as well as the corresponding data delivery.

Own Id: OTP-18835

New functions socket:sendv/* for sending I/O vectors have been added.

Own Id: OTP-18845

The shell now pages long output from the documentation help command (h(Module)), auto completions and the search command.

Own Id: OTP-18846 Aux Id: PR-7845

Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

There are also new APIs to support native coverage without using the cover tool.

To instrument code for native coverage it must be compiled with the line_coverage option.

To enable native coverage in the runtime system, start it like so:

$ erl +JPcover true

There are also the following new functions for supporting native coverage:

code:coverage_support/0

code:get_coverage/2

code:reset_coverage/1

code:get_coverage_mode/0

code:get_coverage_mode/1

code:set_coverage_mode/1

Own Id: OTP-18856 Aux Id: PR-7856

Optimized code loading by moving certain operations from the code server to the caller.

Own Id: OTP-18941 Aux Id: PR-7981

The documentation has been migrated to use Markdown and ExDoc.

Own Id: OTP-18955 Aux Id: PR-8026

Application startup has been optimized by removing an intermediary process.

Own Id: OTP-18963 Aux Id: PR-8042

The existing experimental support for archive files will be changed in a future release. The support for having an archive in an escript will remain, but the support for using archives in a release will either become more limited or completely removed.

As of Erlang/OTP 27, the function code:lib_dir/2, the -code_path_choice flag, and using erl_prim_loader for reading members of an archive are deprecated.

To remain compatible with future version of Erlang/OTP escript scripts that need to retrieve data files from its archive should use escript:extract/2 instead of erl_prim_loader and code:lib_dir/2.

POTENTIAL INCOMPATIBILITY

Own Id: OTP-18966 Aux Id: PR-8091

The undocumented and deprecated file:pid2name function has been removed.

Own Id: OTP-18967 Aux Id: PR-8092

There is a new module trace in Kernel providing the same trace functionality as erlang:trace/3 and erlang:trace_pattern/3, but with the addition of dynamic isolated trace sessions.

Own Id: OTP-18980

Error logging has been improved when the io:standard_io/0 reader and/or writer terminates with an error.

Own Id: OTP-18989 Aux Id: PR-8103

inet_backend = socket has been optimized and reworked to be more compatible with the original inet_backend = inet.

Own Id: OTP-19004 Aux Id: OTP-18835

Add an simple example (echo server) )to the socket users guide.

Own Id: OTP-19042

inet:i/0,1,2 has been improved to allow port numbers to be shown explicitly.

Own Id: OTP-19053 Aux Id: #6724

The socket documentation has been reworked, and due to that a few details were fixed:

socket:is_supported/1 now returns true for example for protocols that is a "category", not an item.

socket:cancel_monitor/1 no longer badargs for a monitor that was set by another process, instead it returns false as for other unknown reference()s.

Own Id: OTP-19054

Add stdin, stdout and stderr keys to io:getopts/1 on io:standard_io/0 to indicate if the respective I/O device is backed by a terminal.

Own Id: OTP-19089 Aux Id: PR-8396

Kernel 9.2.4.11

Fixed Bugs and Malfunctions

Before this patch, the Erlang/OTP built-in DNS resolver (inet_res) used a sequential, process-global 16-bit transaction ID for UDP queries and did not implement source port randomization. Response validation relied almost entirely on this ID. Together, this made DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. The design conflicted with RFC 5452 recommendations for mitigating forged DNS answers.

inet_res is intended for use in trusted network environments and with trusted recursive resolvers. Earlier documentation did not clearly state this deployment assumption, which could lead users to deploy the resolver in environments where faked DNS responses are possible.

Therefore, the documentation is been updated to clarify that inet_res should only be used in trusted networks and with trusted recursive resolvers.

The implementation is also improved to use strong random DNS transaction IDs and source ports for every DNS transaction. This should give ample protection against brute forcing fake DNS replies, known as DNS cache poisoning, but it still does not protect against, for example, an adversary in the path of the DNS transaction that can observe the random values before faking malicious replies, an attack known as DNS spoofing.

For randomization to happen, the Crypto application has to be loaded, which most probably already should be the case for an Erlang node in an exposed network.

If performance should become an issue, for applications within safe network environments, the previous light weight behaviour can be configured by setting the resolver option random to false.

Own Id: OTP-20037 Aux Id: CVE-2026-28810, PR-10864

Kernel 9.2.4.10

Fixed Bugs and Malfunctions

net_kernel could be blocked for a very long time when selecting distribution module for a connection if the DNS service was slow. This prevented any new connections to be set up during that time.

Own Id: OTP-19702 Aux Id: ERIERL-1241, PR-10029

Kernel 9.2.4.9

Fixed Bugs and Malfunctions

A remote shell can now exit by closing the input stream, without terminating the remote node.

Own Id: OTP-19667 Aux Id: PR-9912

Kernel 9.2.4.8

Fixed Bugs and Malfunctions

With this change, disk_log will not crash when using chunk_step/3 after log size was decreased.

Own Id: OTP-19605 Aux Id: GH-9720, PR-9765

With this change, disk_log will not run into infinite loop when using chunk/2,3 after log size was decreased.

Own Id: OTP-19608 Aux Id: GH-9707, PR-9767

Kernel 9.2.4.7

Fixed Bugs and Malfunctions

Behavior for socket:recv/3 has been improved. The behavior has also been clarified in the documentation.

Own Id: OTP-19469 Aux Id: #9172

An infinite loop in CNAME loop detection that can cause Out Of Memory has been fixed. This affected CNAME lookup with the internal DNS resolver.

Own Id: OTP-19545 Aux Id: PR-9587, OTP-19544

Kernel 9.2.4.6

Fixed Bugs and Malfunctions

Fixed a couple of bugs that could make global's internal state inconsistent when a connection was reconnected.

Own Id: OTP-19381 Aux Id: PR-9377, GH-9112, GH-9117

Kernel 9.2.4.5

Fixed Bugs and Malfunctions

Fix bug where log printouts would go missing when application_controller is stopping while log messages are being sent.

This bug was introduced by OTP-19078 in Erlang/OTP 26.2.5.

Own Id: OTP-19418 Aux Id: GH-9163 PR-9274

Kernel 9.2.4.4

Fixed Bugs and Malfunctions

gen_udp:send on domain local can leak inet_reply messages.

Own Id: OTP-19332 Aux Id: #8989

Failure to create an UDP IPv6 socket when inet_backend = socket with certain IPv6 socket options.

Own Id: OTP-19357

net:getifaddrs does not properly report the running flag on windows.

Own Id: OTP-19366 Aux Id: OTP-19061, ERIERL-1134

Kernel 9.2.4.3

Fixed Bugs and Malfunctions

A bug has been fixed where receiving an SCTP message with `gen_sctp` could waste the first fragments of a message and only deliver the last fragment.

This happened with low probability when the OS signaled that the socket was ready for reading in combination with an internal time-out retry.

A bug has been fixed with a lingering time-out from after an SCTP connect that could stop the flow of incoming messages on an active `gen_tcp` socket.

Own Id: OTP-19235 Aux Id: ERIERL-1133, PR-8837

An boolean option `non_block_send` for SCTP, has ben added to be able to achieve the old behaviour to avoid blocking send operations by passing the OS network stack error message (`{error,eagain}` through.

Own Id: OTP-19258 Aux Id: OTP-19061, ERIERL-1134

Kernel 9.2.4.2

Fixed Bugs and Malfunctions

A race in the kTLS flavour of SSL distribution has been fixed so inet_drv.c doesn't read ahead too much data which could cause the kTLS encryption to be activated too late when some encrypted data had already been read into the inet_drv.c buffer as unencrypted.

Own Id: OTP-19175 Aux Id: GH-8561, PR-8690

Fix a deadlock when an application crashes during startup and log messages were sent to standard out. Logger would fail to print the messages to standard out and instead print them to standard error.

Own Id: OTP-19205

Add the stdlib application parameters shell_redraw_prompt_on_output which when set to false disables redrawing of the shell prompt if any other output is done.

Own Id: OTP-19213 Aux Id: PR-8763 ERIERL-1108

Kernel 9.2.4.1

Fixed Bugs and Malfunctions

A call to socket:[recv|recvfrom|recvmsg]/* with Timeout = 0 on Windows could cause a (case clause) crash if data is immediately available.

Own Id: OTP-19063 Aux Id: OTP-18835

Open a disk_log file and combining head_func with rotate options did not work.

Own Id: OTP-19104 Aux Id: ERIERL-870

Kernel 9.2.4

Fixed Bugs and Malfunctions

Fix the shell Job Control Mode to not crash when typing TAB or CTRL+R.

Own Id: OTP-19072 Aux Id: PR-8391

Fix calls to blocking application APIs to throw an exception with reason terminating if called when the system is terminating.

This is done in order to avoid deadlocks during shutdown or restart.

Own Id: OTP-19078 Aux Id: PR-8422

Kernel 9.2.3

Fixed Bugs and Malfunctions

When using IPv6, classic gen_udp failed to add (group) membership (drop was used instead).

Own Id: OTP-19049 Aux Id: #8176

The check in inet_res of the RD bit has been relaxed slightly.

Own Id: OTP-19056 Aux Id: PR-8312, OTP-17323

Kernel 9.2.2

Fixed Bugs and Malfunctions

Fix performance bug when using io:fread to read from standard_io. This regression was introduced in OTP 26.0.

Own Id: OTP-18910 Aux Id: PR-7933 GH-7924

A bug in the code server could cause it to crash in some concurrent scenarios. This bug was introduced in 26.1.

Own Id: OTP-18948 Aux Id: PR-8046

Fixed gen_udp:open/2 type spec to include already supported module socket address types.

Own Id: OTP-18990 Aux Id: GH-8158

Fix reading of password for ssh client when in user_interactive mode.

Own Id: OTP-19007 Aux Id: ERIERL-1049

Kernel 9.2.1

Fixed Bugs and Malfunctions

Fix group (that is the shell) to properly handle when an get_until callback function returned {done, eof, []} when an eof was detected.

Own Id: OTP-18901

Kernel 9.2

Fixed Bugs and Malfunctions

For inet_backend = socket, an unexpected receive error such as etimedout caused the receiving state machine server to crash. This bug has now been fixed.

Own Id: OTP-18749 Aux Id: GH-7608

Fix bug where reading using file from a unicode enabled standard_io, standard_error or any other group backed device would result in incorrect values being returned or a crash.

Now instead a no_translation error is returned to the caller when unicode data is read using file. See Using Unicode in the STDLIB User's Guide for more details on how to correctly read from standard_io.

Own Id: OTP-18800 Aux Id: PR-7714 GH-7591

The native resolver interface module has gotten a rewrite of its ETS table handling to minimize term copying, and also to move the handling of client time-outs to the clients, which helps the native resolver name server from digging itself into a tar pit when heavily loaded.

Own Id: OTP-18812 Aux Id: ERIERL-997

Replaced unintentional Erlang Public License 1.1 headers in some files with the intended Apache License 2.0 header.

Own Id: OTP-18815 Aux Id: PR-7780

Fix bug in pg if a client process both monitored a group/scope and joined a group. The termination of such process resulted in crash of the pg server process.

Own Id: OTP-18833 Aux Id: GH-7625, PR-7659

Fix crash when using file:consult and the underlying file read returns an error while reading.

Own Id: OTP-18873 Aux Id: PR-7831

Corrected gen_tcp_socket listen option handling.

Own Id: OTP-18883 Aux Id: #7764

Improvements and New Features

Add Windows support for DGRAM socket connect.

Own Id: OTP-18762

Document the, previously opaque, types select_tag() and completion_tag().

Own Id: OTP-18818 Aux Id: #7337

Kernel 9.1

Fixed Bugs and Malfunctions

Fixed an issue with truncated crash slogans on failed emulator start.

Own Id: OTP-18623 Aux Id: GH-7344

Fix shell:start_interactive function specification.

Own Id: OTP-18628 Aux Id: GH-7280

Fix code:get_doc/1 to return missing, when it can't find erts instead of crashing.

Own Id: OTP-18654 Aux Id: PR-7404

Function socket:close/1 could cause a VM crash on Windows.

Own Id: OTP-18669 Aux Id: OTP-18029

Fix deadlock when erl.exe is used as part of a pipe on Windows and trying to set the encoding of the standard_io device.

Own Id: OTP-18675 Aux Id: PR-7473 GH-7459

Expanded the documentation about how to use the standard_io, standard_error and user I/O devices.

Added the types io:standard_io/0, io:standard:error/0 and io:user/0.

Own Id: OTP-18676 Aux Id: PR-7473 GH-7459

Fix logger's overload protection mechanism to only fetch memory used by messages when needed.

Own Id: OTP-18677 Aux Id: PR-7418 GH-7417

Fixed a number of socket-related issues causing incompatibilities with gen_tcp and gen_udp respectively.

Own Id: OTP-18685

gen_tcp:connect with socket address and socket (inet-) backend fails because of missing callback function.

Own Id: OTP-18707 Aux Id: #7530

The DNS RR cache used by `inet_res` has been fixed to preserve insert order, which is beneficial when the DNS server returns RRs in some specific order for e.g load balancing purposes.

Own Id: OTP-18731 Aux Id: GH-7577, PR-7578

The options `reuseport`, `reuseport_lb` and `exclusiveaddruse` were accidentally not allowed for e.g `gen_udp:open/1,2`, which has now been corrected.

Own Id: OTP-18734 Aux Id: OTP-18344, PR-6522, GH-6461, GH-7569

gen_udp:recv/* for Unix Domain Socket in binary mode and passive mode has been fixed to not crash.

Own Id: OTP-18747 Aux Id: GH-7605

Fixed issue where cursor would not be placed at the end of the expression when navigating shell history.

Own Id: OTP-18757 Aux Id: PR-7631

Improvements and New Features

Update gen_tcp_socket and gen_udp_socket to handle 'completion' (socket on Windows).

Own Id: OTP-18586 Aux Id: OTP-18029

Add support for Unix Domain Sockets (only for STREAM sockets) on Windows for 'socket'.

Own Id: OTP-18611 Aux Id: OTP-18029, #5024

Add basic support for socket ioctl on Windows.

Own Id: OTP-18660

The file:location/0 type is now exported.

Own Id: OTP-18681

Add support for (Windows) socket option exclusiveaddruse.

Own Id: OTP-18686

[socket] Add support for the 'nopush' option.

Own Id: OTP-18687

Add support for socket option 'BSP STATE'.

Own Id: OTP-18693

Add tcp socket options 'keepcnt', 'keepidle' and 'keepintvl'.

Own Id: OTP-18698

Add support for misc (Windows) socket options ('max_msg_size' and 'maxdg').

Own Id: OTP-18710

The keyboard shortcuts for the shell are now configurable.

Own Id: OTP-18754 Aux Id: PR-7604 PR-7647

Optimized code_server to reduce repeated work when loading the same module concurrently.

Own Id: OTP-18755 Aux Id: PR-7503

Kernel 9.0.2

Fixed Bugs and Malfunctions

Fix bug where when you entered Alt+Enter in the terminal, the cursor would move to the last line, instead of moving to the next line.

Own Id: OTP-18580 Aux Id: PR-7242

Fix so that the shell does not crash on startup when termcap is not available.

Own Id: OTP-18624 Aux Id: GH-7296

Multiple socket:accept calls issue. When making multiple accept calls, only the last call is active.

Own Id: OTP-18635 Aux Id: #7328

Fix the shell to ignore terminal delay when the terminal capabilities report that they should be used.

Own Id: OTP-18636 Aux Id: PR-7352 GH-7308

Fix "oldshell" to echo characters while typing on Windows.

Own Id: OTP-18637 Aux Id: PR-7359 GH-7324

Fix eof handling when reading from stdin when erlang is started using -noshell.

Own Id: OTP-18640 Aux Id: PR-7384 GH-7368 GH-7286 GH-6881

On Windows, a call to the function socket:close, when there are waiting active calls to read, write or accept functions, could hang.

Own Id: OTP-18646

Fix issues when reading or configuring standard_io on Windows when erl.exe is started using -noshell flag.

Own Id: OTP-18649 Aux Id: GH-7261 PR-7400

gen_udp:connect with inet_backend = socket fails when the Address is a hostname (string or atom).

Own Id: OTP-18650

Fixed problem which would cause shell to crash if particular escape sequence was written to stdout.

Own Id: OTP-18651 Aux Id: PR-7242

Fixed problem where output would disappear if it was received after a prompt was written in the shell.

Own Id: OTP-18652 Aux Id: PR-7242

Fix a crash where the location of erts could not be found in rebar3 dev builds.

Own Id: OTP-18656 Aux Id: PR-7404 GH-7390

Introduce the KERNEL application parameter standard_io_encoding that can be used to set the default encoding for standard_io. This option needs to be set to latin1 if the application wants to treat all input data as bytes rather than utf-8 encoded characters.

Own Id: OTP-18657 Aux Id: GH-7230 PR-7384

Kernel 9.0.1

Fixed Bugs and Malfunctions

The POSIX error exdev was sometimes incorrectly described as "cross domain link" in some error messages.

Own Id: OTP-18578 Aux Id: GH-7213

Corrected the socket send function description (send with Timeout = nowait). The send function(s) could not return {ok, {RestData, SelectInfo}}

Own Id: OTP-18584 Aux Id: #7238

Kernel 9.0

Fixed Bugs and Malfunctions

Fixed a bug where duplicate keys were allowed in the .app file of an application. Duplicate keys are now rejected and the application will not start if they exist.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-18210 Aux Id: GH-5877 PR-5878

Fix inconsistent handling in logger_formatter of the branched values in conditional branches. For example using msg in a conditional branch would not be formatted as it should before this fix.

Own Id: OTP-18225 Aux Id: PR-6036

Fix the logger_std_h handler to log to standard_error if logging to standard_io fails for any reason.

Own Id: OTP-18226 Aux Id: PR-6253

Fix the TLS distribution to work when starting Erlang in embedded mode and a connection is done before kernel is fully started.

Own Id: OTP-18248 Aux Id: PR-6227 GH-6085

erl -remsh has been improved to provide better error reasons and work when using a shell without terminal support (that is an "oldshell").

Own Id: OTP-18271 Aux Id: PR-6279

Fix logging of log events generated before kernel is started to not fail if the code for formatting those log messaged have not yet been loaded.

Own Id: OTP-18286 Aux Id: PR-5955

proc_lib:start*/* has become synchronous when the started process fails. This requires that a failing process use a new function proc_lib:init_fail/2,3, or exits, to indicate failure. All OTP behaviours have been fixed to do this.

All these start functions now consume the 'EXIT' message from a process link for all error returns. Previously it was only the start_link/* functions that did this, and only when the started function exited, not when it used init_ack/1,2 or init_fail/2,3 to create the return value.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-18471 Aux Id: GH-6339, PR-6843

Fixed a bug where file:read(standard_io, ...) unexpectedly returned eof in binary mode.

Own Id: OTP-18486 Aux Id: PR-6881

Return type for seq_trace:get_token/1 fixed.

Own Id: OTP-18528 Aux Id: PR-7009

Looking up, connecting to and sending to a host with an empty name is now handled by trying to look up the address of the root domain, which fails. Previously some of these operations caused an internal exception, which contradicted type specifications.

Own Id: OTP-18543 Aux Id: GH-6353

Replaced a regex with a special case handling of ANSI Select Graphic Rendition escape characters, to speed up io output that make use of these escape sequences.

Own Id: OTP-18547 Aux Id: PR-7092

Improvements and New Features

The Erlang shell has been improved to support the following features:

Auto-complete variables, record names, record field names, map keys, function parameter types and filenames.

Open external editor in the shell (with C-o) to edit the current expression in an editor.

Support defining records (with types), functions and function typespecs, and custom types in the shell.

Do not save pager commands, and input to io:getline in history.

Own Id: OTP-14835 Aux Id: PR-5924

The TTY/terminal subsystem has been rewritten by moving more code to Erlang from the old linked-in driver and implementing all the I/O primitives needed in a NIF instead.

On Unix platforms the user should not notice a lot of difference, besides better handling of unicode characters and fixing of some long standing bugs.

Windows users will notice that erl.exe has the same functionality as a normal Unix shell and that werl.exe has been removed and replaced with a symlink to erl.exe. This makes the Windows Erlang terminal experience identical to that of Unix.

The re-write brings with it a number of bug fixes and feature additions:

The TTY is now reset when Erlang exits, fixing zsh to not break when terminating an Erlang session.

standard_error now uses the same unicode mode as standard_io.

Hitting backspace when searching the shell history with an empty search string no longer breaks the shell.

Tab expansion now works on remote nodes started using the JCL interface.

It is now possible to configure the shell slogan and the session slogans (that is the texts that appear when you start an Erlang shell). See the kernel documentation for more details.

Added shell:start_interactive for starting the interactive shell from a non-interactive Erlang session (for example an escript).

On Windows, when starting in detached mode the standard handler are now set to nul devices instead of being unset.

Standard I/O now always defaults to unicode mode if supported. Previously the default was latin1 if the runtime system had been started with -oldshell or -noshell (for example in an escript). To send raw bytes over standard out, one now explicitly has to specify io:setopts(standard_io, [{encoding, latin1}]).

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-17932 Aux Id: PR-6144 GH-3150 GH-3390 GH-4343 GH-4225

Add support for socket on Windows.

Pre release status.

Error codes not finalized.

No explicit support for Windows specific options (socket options, flags for read and write).

New async api for Windows (completion). See the Asynchronous calls chapter in the (Socket Usage) Users Guide.

To ensure platform independence, gentcp and gen_udp is _intended to be used (not yet updated).

Own Id: OTP-18029

As announced since the release of OTP 24, support for:

version 4 node container types in the external term format are now mandatory. That is, references supporting up to 5 32-bit integer identifiers, and process and port identifiers with support for 64-bit data storage. The distribution flag DFLAG_V4_NC is therefor now also mandatory. OTP has since OTP 24 supported this. Also note that the external format produced by term_to_binary() and term_to_iovec() will unconditionally produce pids, ports, and references supporting this larger format.

the new link protocol introduced in OTP 23.3 is now mandatory. The distribution flag DFLAG_UNLINK_ID is therefor now also mandatory.

Due to the above, OTP 26 nodes will refuse to connect to OTP nodes from releases prior to OTP 24.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-18140 Aux Id: PR-6072

Support for Kernel TLS (kTLS), has been added to the SSL application, for TLS distribution (-proto_dist inet_tls), the SSL option {ktls, true}. Using this for general SSL sockets is uncomfortable, undocumented and not recommended since it requires very platform dependent raw options.

This, for now, only works for some not too old Linux distributions. Roughly, a kernel 5.2.0 or later with support for UserLand Protocols and the kernel module tls is required.

Own Id: OTP-18235 Aux Id: PR-6104, PR-5840

Add code:get_doc/2 which adds support to fetch documentation skeletons of functions using debug_info chunks instead of eep48 doc chunks.

Own Id: OTP-18261 Aux Id: PR-5924

The Erlang shell's auto-completion when typing tab has been changed to happen after the editing current line instead of before it.

This behaviour can be configured using a the shell_expand_location STDLIB configuration parameter.

Own Id: OTP-18278 Aux Id: PR-6260

Typing Ctrl+L in a shell now clears the screen and redraws the current line instead of only redrawing the current line. To only redraw the current line, you must now type Alt+L. This brings the behaviour of Ctrl+L closer to how bash and other shells work.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-18285 Aux Id: PR-6262

gen_server optimized by caching callback functions

Own Id: OTP-18305 Aux Id: PR-5831

Prepare the pg communication protocol for upgrade. The plan is for OTP-28 nodes to be able to use an upgraded pg protocol while still being able to talk with OTP 26 nodes.

Own Id: OTP-18327 Aux Id: PR-6433

New disk_log log type rotate, where the log files are compressed upon rotation.

Own Id: OTP-18331 Aux Id: ERIERL-870

The following inet:setopts/2 options have been introduced:

reuseport - Reuse of local port. Load balancing may or may not be provided depending on underlying OS.

reuseport_lb - Reuse of local port. Load balancing provided.

exclusiveaddruse - Exclusive address/port usage on Windows. This socket option is Windows specific and will silently be ignored on other systems.

The behavior of setting reuseaddr on Windows have changed in a backwards incompatible way. The underlying SO_REUSEADDR socket option is now only set if both the reusaddr and the reuseport inet options have been set. This since the underlying SO_REUSEADDR socket option on Windows behaves similar to how BSD behaves if both the underlying socket options SO_REUSEADDR and SO_REUSEPORT have been set. See the documentation of the reuseaddr option for more information.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-18344 Aux Id: PR-6522, PR-6944, OTP-18324, PR-6481, GH-6461

Replace size/1 with either tuple_size/1 or byte_size/1

The size/1 BIF is not optimized by the JIT, and its use can result in worse types for Dialyzer.

When one knows that the value being tested must be a tuple, tuple_size/1 should always be preferred.

When one knows that the value being tested must be a binary, byte_size/1 should be preferred. However, byte_size/1 also accepts a bitstring (rounding up size to a whole number of bytes), so one must make sure that the call to byte_size/ is preceded by a call to is_binary/1 to ensure that bitstrings are rejected. Note that the compiler removes redundant calls to is_binary/1, so if one is not sure whether previous code had made sure that the argument is a binary, it does not harm to add an is_binary/1 test immediately before the call to byte_size/1.

Own Id: OTP-18405 Aux Id: GH-6672,PR-6702,PR-6768,PR-6700,PR-6769,PR-6812,PR-6814

The function file:pid2name/1 is deprecated and will be removed in Erlang/OTP 27.

Own Id: OTP-18419

The modules Erlang DNS resolver inet_res and helper modules have been updated for RFC6891; to handle OPT RR with DNSSEC OK (DO) bit.

Own Id: OTP-18442 Aux Id: PR-6786, GH-6606

Introduced application:get_supervisor/1.

Own Id: OTP-18444 Aux Id: PR-6035

Handling of on_load modules during boot has been improved by adding an extra step in the boot order for embedded mode that runs all on_load handlers, instead of relying on explicit invocation of them, later, when the kernel supervision tree starts.

This is mostly a code improvement and OTP internal simplification to avoid future bugs and to simplify code maintenance.

Own Id: OTP-18447

Reduce contention on the code_server by doing the code preparation on the client.

Own Id: OTP-18448 Aux Id: PR-6736

Added a mode to ensure_all_loaded, to start children application and their dependencies concurrently.

Own Id: OTP-18451 Aux Id: PR-6737

Cache OTP boot code paths, to limit how many folders that are being accessed during a module lookup. Can be disabled with -cache_boot_path false. OTP boot code paths consists of ERL_LIB environment variables. The various otp/*/ebin folders. And the {path, ...} clauses in the init script.

Own Id: OTP-18452 Aux Id: PR-6729

Erlang distribution code in Kernel and SSL has been refactored a bit to facilitate debugging and re-usability, which shouldn't have any noticeable effects on behaviour or performance.

Own Id: OTP-18456

Add cache attribute to code path apis.

Added an optional cache/nocache argument to all code:add_path, code:set_path, and code:replace_path* functions. These functions will then avoid doing file-accesses if they are cached. Cache can be cleared with code:clear_cache/0. Added code:del_paths/1 to make it easier to clear multiple paths.

Own Id: OTP-18466 Aux Id: PR-6832

Deprecates dbg:stop_clear/0 because it is simply a function alias to dbg:stop/0

Own Id: OTP-18478 Aux Id: GH-6903

Improvements to code:ensure_modules_loaded/1: Previously it would prepare modules and then abandon references to said modules if they had on_load callbacks. This pull request makes it so they keep the references around and then serially load them without having to fetch the object code and prepare them again.

Own Id: OTP-18484 Aux Id: PR-6844

The internal DNS resolver has been updated to handle DNS LOC RR:s (RFC 1876). This is an undocumented module, although still used by power users. See the source code.

Own Id: OTP-18510 Aux Id: GH-6098, PR-6982

Reduced memory consumption in global when informing other nodes about lost connections.

Own Id: OTP-18521 Aux Id: PR-7025

The net_kernel, global, and global_group servers now have fully asynchronous distributed signaling enabled all the time which prevents them from ever getting blocked on send of distributed signals.

Documentation about blocking distributed signals has also been improved.

Own Id: OTP-18533 Aux Id: PR-7061

Allow IPv6 addresses as host in http packets decoded by erlang:decode_packet/3 and gen_tcp packet option. The IPv6 address should be enclosed within [] according to RFC2732.

Own Id: OTP-18540 Aux Id: PR-6900

Remove deprecated functions in OTP-26

Own Id: OTP-18542

Removed code:is_module_native/1 since HiPE has been removed. It has since OTP 24 been deprecated and scheduled for removal in OTP 26.

Removed code:rehash/0 since the code path feature no longer is present. It has since OTP 19 been deprecated and has since OTP 24 been scheduled for removal in OTP 26.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-18551 Aux Id: PR-7106

Added support for multiple line expressions and navigation in the shell. Added new keybindings:

navigate up (ctrl+up)/(alt+up)

navigate down (ctrl+down)/(alt+down)

insert newline in middle of line (alt+enter)

navigate top (alt+<)/(alt+shift+up)

navigate bottom (alt+>)/(alt+shift+down)

clear current expression (alt+c)

cancel search (alt+c)

opening editor on mac (option+o)/(alt+o)

Modifies the prompt for new lines to make it clearer that the prompt has entered multi-line mode. Supports terminal with small window size, recommend not go lower than 7 rows and 40 columns. Modifies the search prompt to support multi-line statements. Redraw the prompt after continuing from JCL menu.

Own Id: OTP-18575 Aux Id: PR-7169

Kernel 8.5.4.6

Fixed Bugs and Malfunctions

With this change, disk_log will not crash when using chunk_step/3 after log size was decreased.

Own Id: OTP-19605 Aux Id: GH-9720, PR-9765

With this change, disk_log will not run into infinite loop when using chunk/2,3 after log size was decreased.

Own Id: OTP-19608 Aux Id: GH-9707, PR-9767

Kernel 8.5.4.5

Fixed Bugs and Malfunctions

An infinite loop in CNAME loop detection that can cause Out Of Memory has been fixed. This affected CNAME lookup with the internal DNS resolver.

Own Id: OTP-19545 Aux Id: PR-9587, OTP-19544

Kernel 8.5.4.4

Fixed Bugs and Malfunctions

Fixed a couple of bugs that could make global's internal state inconsistent when a connection was reconnected.

Own Id: OTP-19381 Aux Id: PR-9377, GH-9112, GH-9117

Kernel 8.5.4.3

Fixed Bugs and Malfunctions

Fixed gen_udp:open/2 type spec to include already supported module socket address types.

Own Id: OTP-19050 Aux Id: OTP-18990

Kernel 8.5.4.2

Fixed Bugs and Malfunctions

gen_tcp:connect with socket address and socket (inet-) backend fails because of missing callback function.

Own Id: OTP-18707 Aux Id: #7530

Kernel 8.5.4.1

Fixed Bugs and Malfunctions

Multiple socket:accept calls issue. When making multiple accept calls, only the last call is active.

Own Id: OTP-18635 Aux Id: #7328

gen_udp:connect with inet_backend = socket fails when the Address is a hostname (string or atom).

Own Id: OTP-18650

Kernel 8.5.4

Fixed Bugs and Malfunctions

Fixed a bug on Windows where file:read_file_info/1 would fail for files with corrupt metadata.

Own Id: OTP-18348 Aux Id: GH-6356

Accept connection setup from OTP 23 and 24 nodes that are not using epmd.

Own Id: OTP-18404 Aux Id: GH-6595, PR-6625

Kernel 8.5.3

Fixed Bugs and Malfunctions

The tcp connect option 'bind_to_device' could not be used with inet_backend = 'socket'. 'inet' requires value type binarry() and 'socket' requires value type 'string()'.

Own Id: OTP-18357 Aux Id: #6509

Minor issue processing options when calling gen_tcp:connect with a sockaddr() and inet_backend = socket.

Own Id: OTP-18358 Aux Id: #6528

Kernel 8.5.2

Fixed Bugs and Malfunctions

Fixed shutdown crash in gen_tcp socket backend, when the other end closed the socket.

Own Id: OTP-18270 Aux Id: #6331

erl_tar can now read gzip-compressed tar files that are padded. There is a new option compressed_one for file:open/2 that will read a single member from a gzip file,

Own Id: OTP-18289 Aux Id: PR-6343

Fix os:cmd to not translate all exceptions thrown to badarg. For example emfile from erlang:open_port was translated to badarg.

This bug has existed since Erlang/OTP 24.

Own Id: OTP-18291 Aux Id: PR-6382

Spec for function net:if_names/0 incorrect

Own Id: OTP-18296 Aux Id: OTP-16464

Missing ctrl option name transation for TOS and TTL (on FreeBSD) when using gen_udp with the 'socket' inet_backend.

Own Id: OTP-18315

gen_udp:open/2 with option(s) add_membership or drop_membership would drop earlier options.

Own Id: OTP-18323 Aux Id: #6476

The inet:setopts/2 {reuseaddr, true} option will now be ignored on Windows unless the socket is an UDP socket. For more information see the documentation of the reuseaddr option part of the documentation of inet:setopts/2.

Prior to OTP 25 the {reuseaddr, true} option was ignored for all sockets on Windows, but as of OTP 25.0 this was changed so that it was not ignored for any sockets.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-18324 Aux Id: GH-6461, PR-6481

Improvements and New Features

The distribution socket option handling in inet_tcp_dist has been cleaned up to clarify which were mandatory and which just had default values.

Own Id: OTP-18293

Improve warning message format for gen_tcp_socket.

Own Id: OTP-18317

Kernel 8.5.1

Fixed Bugs and Malfunctions

Listen sockets created with the socket module, leaked (erlang-) monitors.

Own Id: OTP-18240 Aux Id: #6285

peer nodes failed to halt when the process supervising the control connection crashed. When an alternative control connection was used, this supervision process also quite frequently crashed when the peer node was stopped by the node that started it which caused the peer node to linger without ever halting.

Own Id: OTP-18249 Aux Id: PR-6301

Kernel 8.5

Fixed Bugs and Malfunctions

Fixed inconsistency bugs in global due to nodeup/nodedown messages not being delivered before/after traffic over connections. Also fixed various other inconsistency bugs and deadlocks in both global_group and global.

As building blocks for these fixes, a new BIF erlang:nodes/2 has been introduced and net_kernel:monitor_nodes/2 has been extended.

The -hidden and -connect_all command line arguments did not work if multiple instances were present on the command line which has been fixed. The new kernel parameter connect_all has also been introduced in order to replace the -connect_all command line argument.

Own Id: OTP-17934 Aux Id: PR-6007

Fixed IPv6 multicast_if and membership socket options.

Own Id: OTP-18091 Aux Id: #5789

Fixed issue with inet:getifaddrs hanging on pure IPv6 Windows

Own Id: OTP-18102 Aux Id: #5904

The type specifications for inet:getopts/2 and inet:setopts/2 have been corrected regarding SCTP options.

Own Id: OTP-18115 Aux Id: PR-5939

The type specifications for inet:parse_* have been tightened.

Own Id: OTP-18121 Aux Id: PR-5972

Fix gen_tcp:connect/3 spec to include the inet_backend option.

Own Id: OTP-18171 Aux Id: PR-6131

Fix bug where using a binary as the format when calling logger:log(Level, Format, Args) (or any other logging function) would cause a crash or incorrect logging.

Own Id: OTP-18229 Aux Id: PR-6212

Improvements and New Features

Add rudimentary debug feature (option) for the inet-driver based sockets, such as gen_tcp and gen_udp.

Own Id: OTP-18032

Introduced the hidden and dist_listen options to net_kernel:start/2.

Also documented the -dist_listen command line argument which was erroneously documented as a kernel parameter and not as a command line argument.

Own Id: OTP-18107 Aux Id: PR-6009

Scope and group monitoring have been introduced in pg. For more information see the documentation of pg:monitor_scope(), pg:monitor(), and pg:demonitor().

Own Id: OTP-18163 Aux Id: PR-6058, PR-6275

A new function global:disconnect/0 has been introduced with which one can cleanly disconnect a node from all other nodes in a cluster of global nodes.

Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264

Kernel 8.4.2

Fixed Bugs and Malfunctions

A call to net_kernel:setopts(new, Opts) at the same time as a connection was being set up could cause a deadlock between the net_kernel process and the process setting up the connection.

Own Id: OTP-18198 Aux Id: GH-6129, PR-6216

Kernel 8.4.1

Fixed Bugs and Malfunctions

The DNS resolver inet_res has been fixed to ignore trailing dot difference in the request domain between the sent request and the received response, when validating a response.

Own Id: OTP-18112 Aux Id: ERIERL-811

A bug in inet_res has been fixed where a missing internal {ok,_} wrapper caused inet_res:resolve/* to return a calculated host name instead of an {ok,Msg} tuple, when resolving an IP address or a host name that is an IP address string.

Own Id: OTP-18122 Aux Id: GH-6015, PR-6020

The erlang:is_alive() BIF could return true before configured distribution service was available. This bug was introduced in OTP 25.0 ERTS version 13.0.

The erlang:monitor_node() and erlang:monitor() BIFs could erroneously fail even though configured distribution service was available. This occurred if these BIFs were called after the distribution had been started using dynamic node name assignment but before the name had been assigned.

Own Id: OTP-18124 Aux Id: OTP-17558, PR-6032

Added the missing mandatory address/0 callback in the gen_tcp_dist example.

Own Id: OTP-18136

Kernel 8.4

Fixed Bugs and Malfunctions

The DNS resolver implementation has been rewritten to validate replies more thoroughly, and a bit optimized to create less garbage.

Own Id: OTP-17323

The socket option 'reuseaddr' is no longer ignored on Windows.

Own Id: OTP-17447 Aux Id: GH-4819

Fix bug where using the atoms string or report as the format when calling logger:log(Level, Format, Args) (or any other logging function) would cause a crash or incorrect logging.

Own Id: OTP-17551 Aux Id: GH-5071 PR-5075

As of OTP 25, global will by default prevent overlapping partitions due to network issues by actively disconnecting from nodes that reports that they have lost connections to other nodes. This will cause fully connected partitions to form instead of leaving the network in a state with overlapping partitions.

Prevention of overlapping partitions can be disabled using the prevent_overlapping_partitions kernel(6) parameter, making global behave like it used to do. This is, however, problematic for all applications expecting a fully connected network to be provided, such as for example mnesia, but also for global itself. A network of overlapping partitions might cause the internal state of global to become inconsistent. Such an inconsistency can remain even after such partitions have been brought together to form a fully connected network again. The effect on other applications that expects that a fully connected network is maintained may vary, but they might misbehave in very subtle hard to detect ways during such a partitioning. Since you might get hard to detect issues without this fix, you are strongly advised not to disable this fix. Also note that this fix has to be enabled on all nodes in the network in order to work properly.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-17911 Aux Id: PR-5687, PR-5611, OTP-17843

Starting the helper program for name resolving; inet_gethost, has been improved to use an absolute file system path to ensure that the right program is started.

If the helper program can not be started - the system now halts, to avoid running with a silently broken name resolver.

Own Id: OTP-17958 Aux Id: OTP-17978

The type specification for inet_res:getbyname/2,3 has been corrected to reflect that it can return peculiar #hostent{} records.

Own Id: OTP-17986 Aux Id: PR-5412, PR-5803

code:module_status/1 would always report BEAM files loaded from an archive as modified, and code:modified_modules/0 would always return the name of all modules loaded from archives.

Own Id: OTP-17990 Aux Id: GH-5801

In logger fix file handler shutdown delay by using erlang timers instead of the timer module's timers.

Own Id: OTP-18001 Aux Id: GH-5780 PR-5829

Fix the meta data in log events generated by logger on failure to not contain the original log event's meta data.

Own Id: OTP-18003 Aux Id: PR-5771

Fix logger file backend to re-create the log folder if it has been deleted.

Own Id: OTP-18015 Aux Id: GH-5828 PR-5845

[socket] Encode of sockaddr has been improved.

Own Id: OTP-18020

Fix put_chars requests to the io server with incomplete unicode data to exit with no_translation error.

Own Id: OTP-18070 Aux Id: PR-5885

Improvements and New Features

The net module now works on Windows.

Own Id: OTP-16464

An Erlang installation directory is now relocatable on the file system given that the paths in the installation's RELEASES file are paths that are relative to the installations root directory. The `release_handler:create_RELEASES/4 function can generate a RELEASES file with relative paths if its RootDir parameter is set to the empty string.

Own Id: OTP-17304

The following distribution flags are now mandatory: DFLAG_BIT_BINARIES, DFLAG_EXPORT_PTR_TAG, DFLAG_MAP_TAGS, DFLAG_NEW_FLOATS, and DFLAG_FUN_TAGS. This mainly concerns libraries or application that implement the distribution protocol themselves.

Own Id: OTP-17318 Aux Id: PR-4972

Fix os:cmd to work on Android OS.

Own Id: OTP-17479 Aux Id: PR-4917

The configuration files .erlang, .erlang.cookie and .erlang.crypt can now be located in the XDG Config Home directory.

See the documentation for each file and filename:basedir/2 for more details.

Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821

Dynamic node name improvements: erlang:is_alive/0 changed to return true for pending dynamic node name and new function net_kernel:get_state/0.

Own Id: OTP-17558 Aux Id: OTP-17538, PR-5111, GH-5402

The types for callback result types in gen_statem has bee augmented with arity 2 types where it is possible for a callback module to specify the type of the callback data, so the callback module can get type validation of it.

Own Id: OTP-17589 Aux Id: PR-4926

The tagged tuple tests and fun-calls have been optimized and are now a little bit cheaper than previously.

These optimizations become possible after making sure that all boxed terms have at least one word allocated after the arity word. This has been accomplished by letting all empty tuples refer to the same empty tuple literal which also reduces memory usage for empty tuples.

Own Id: OTP-17608

A net_ticker_spawn_options kernel configuration parameter with which one can set spawn options for the distribution channel ticker processes has been introduced.

Own Id: OTP-17617 Aux Id: PR-5069

The most, or at least the most used, rpc operations now require erpc support in order to communicate with other Erlang nodes. erpc was introduced in OTP 23. That is, rpc operations against Erlang nodes of releases prior to OTP 23 will fail.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-17681 Aux Id: PR-5307

The new module peer supersedes the slave module. The slave module is now deprecated and will be removed in OTP 27.

peer contains an extended and more robust API for starting erlang nodes.

Own Id: OTP-17720 Aux Id: PR-5162

In order to make it easier for the user to manage multiple outstanding asynchronous call requests, new functionality utilizing request identifier collections have been introduced in erpc, gen_server, gen_statem, and gen_event.

Own Id: OTP-17784 Aux Id: PR-5792

Type specifications have been added to the gen_server, and the documentation has been updated to utilize this.

This surfaced a few type violations that has been corrected in global, logger_olp and rpc.

Own Id: OTP-17915 Aux Id: PR-5751, GH-2375, GH-2690

IP address validation functions is_ipv4_address/1, is_ipv6_address/1 and is_ip_address/1 have been added to the module inet in Kernel.

Own Id: OTP-17923 Aux Id: PR-5646

An API for multihomed SCTP connect has been added in the guise of gen_sctp:connectx_init/*

Own Id: OTP-17951 Aux Id: PR-5656

[socket] Add encoding of the field hatype of the type sockaddr_ll (family 'packet').

Own Id: OTP-17968 Aux Id: OTP-16464

Added support for configurable features as described in EEP-60. Features can be enabled/disabled during compilation with options (-enable-feature Feature, -disable-feature Feature and +{feature, Feature, enable|disable}) to erlc as well as with directives (-feature(Feature, enable|disable).) in the file. Similar options can be used to erl for enabling/disabling features allowed at runtime. The new maybe expression (EEP-49) is fully supported as the feature maybe_expr. The features support is documented in the reference manual.

Own Id: OTP-17988

Kernel 8.3.2.4

Fixed Bugs and Malfunctions

gen_tcp:connect with socket address and socket (inet-) backend fails because of missing callback function.

Own Id: OTP-18707 Aux Id: #7530

Kernel 8.3.2.3

Fixed Bugs and Malfunctions

Spec for function net:if_names/0 incorrect

Own Id: OTP-18296 Aux Id: OTP-16464

Missing ctrl option name transation for TOS and TTL (on FreeBSD) when using gen_udp with the 'socket' inet_backend.

Own Id: OTP-18315

The tcp connect option 'bind_to_device' could not be used with inet_backend = 'socket'. 'inet' requires value type binarry() and 'socket' requires value type 'string()'.

Own Id: OTP-18357 Aux Id: #6509

Minor issue processing options when calling gen_tcp:connect with a sockaddr() and inet_backend = socket.

Own Id: OTP-18358 Aux Id: #6528

Improvements and New Features

Improve warning message format for gen_tcp_socket.

Own Id: OTP-18317

Kernel 8.3.2.2

Improvements and New Features

A new function global:disconnect/0 has been introduced with which one can cleanly disconnect a node from all other nodes in a cluster of global nodes.

Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264

Kernel 8.3.2.1

Fixed Bugs and Malfunctions

A call to net_kernel:setopts(new, Opts) at the same time as a connection was being set up could cause a deadlock between the net_kernel process and the process setting up the connection.

Own Id: OTP-18198 Aux Id: GH-6129, PR-6216

Kernel 8.3.2

Fixed Bugs and Malfunctions

inet:getopts/2 for the 'raw' option for a socket created with inet-backend 'socket' failed.

Own Id: OTP-18078 Aux Id: GH-5930

Corrected the behaviour of the shutdown function when using with the inet_backend = socket. It was not sufficiently compatible with the "old" gen_tcp.

Own Id: OTP-18080 Aux Id: GH-5930

Kernel 8.3.1

Fixed Bugs and Malfunctions

Fix failed accepted connection setup after previous established connection from same node closed down silently.

Own Id: OTP-17979 Aux Id: ERIERL-780

Fixed a problem where typing Ctrl-R in the shell could hang if there were some problem with the history log file.

Own Id: OTP-17981 Aux Id: PR-5791

Kernel 8.3

Fixed Bugs and Malfunctions

Handling of send_timeout for gen_tcp has been corrected so that the timeout is honored also when sending 0 bytes.

Own Id: OTP-17840

By default global does not take any actions to restore a fully connected network when connections are lost due to network issues. This is problematic for all applications expecting a fully connected network to be provided, such as for example mnesia, but also for global itself. A network of overlapping partitions might cause the internal state of global to become inconsistent. Such an inconsistency can remain even after such partitions have been brought together to form a fully connected network again. The effect on other applications that expects that a fully connected network is maintained may vary, but they might misbehave in very subtle hard to detect ways during such a partitioning.

In order to prevent such issues, we have introduced a prevent overlapping partitions fix which can be enabled using the prevent_overlapping_partitions kernel(6) parameter. When this fix has been enabled, global will actively disconnect from nodes that reports that they have lost connections to other nodes. This will cause fully connected partitions to form instead of leaving the network in a state with overlapping partitions. Note that this fix has to be enabled on all nodes in the network in order to work properly. Since this quite substantially changes the behavior, this fix is currently disabled by default. Since you might get hard to detect issues without this fix you are, however, strongly advised to enable this fix in order to avoid issues such as the ones described above. As of OTP 25 this fix will become enabled by default.

Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611

Fix bug where logger would crash when logging a report including improper lists.

Own Id: OTP-17851

Make erlang:set_cookie work for dynamic node names.

Own Id: OTP-17902 Aux Id: GH-5402, PR-5670

Improvements and New Features

Add support for using socket:sockaddr_in() and socket:sockaddr_in6() when using gen_sctp, gen_tcp and gen_udp. This will make it possible to use Link Local IPv6 addresses.

Own Id: OTP-17455 Aux Id: GH-4852

A net_tickintensity kernel parameter has been introduced. It can be used to control the amount of ticks during a net_ticktime period.

A new net_kernel:start/2 function has also been introduced in order to make it easier to add new options. The use of net_kernel:start/1 has been deprecated.

Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740

Improve documentation for the dynamic node name feature.

Own Id: OTP-17918

Kernel 8.2

Fixed Bugs and Malfunctions

socket:which_sockets( pid() ) uses wrong keyword when looking up socket owner ('ctrl' instead of 'owner').

Own Id: OTP-17716

In epmd_ntop, the #if defined(EPMD6) conditional was inverted and it was only including the IPv6-specific code when EPMD6 was undefined. This was causing IPv6 addrs to be interpreted as IPv4 addrs and generating nonsense IPv4 addresses as output.

Several places were incorrectly using 'num_sockets' instead of 'i' to index into the iserv_addr array during error logging. This would result in a read into uninitialized data in the iserv_addr array.

Thanks to John Eckersberg for providing this fix.

Own Id: OTP-17730

Minor fix of the erl_uds_dist distribution module example.

Own Id: OTP-17765 Aux Id: PR-5289

A bug has been fixed for the legacy TCP socket adaption module gen_tcp_socket where it did bind to a socket address when given a file descriptor, but should not.

Own Id: OTP-17793 Aux Id: PR-5348, OTP-17451, PR-4787, GH-4680, PR-2989, OTP-17216

Improve the error printout when open_port/2 fails because of invalid arguments.

Own Id: OTP-17805 Aux Id: PR-5406

Calling socket:monitor/1 on an already closed socket should succeed and result in an immediate DOWN message. This has now been fixed.

Own Id: OTP-17806

Fix the configuration option logger_metadata to work.

Own Id: OTP-17807 Aux Id: PR-5418

Fix tls and non-tls distribution to use erl_epmd:address_please to figure out if IPv4 or IPv6 addresses should be used when connecting to the remote node.

Before this fix, a dns lookup of the remote node hostname determined which IP version was to be used which meant that the hostname had to resolve to a valid ip address.

Own Id: OTP-17809 Aux Id: PR-5337 GH-5334

Improvements and New Features

Add logger:reconfigure/0.

Own Id: OTP-17375 Aux Id: PR-4663 PR-5186

Add socket function ioctl/2,3,4 for socket device control.

Own Id: OTP-17528

Add simple support for socknames/1 for gen_tcp_socket and gen_udp_socket.

Own Id: OTP-17531

The types for callback result types in gen_statem has bee augmented with arity 2 types where it is possible for a callback module to specify the type of the callback data, so the callback module can get type validation of it.

Own Id: OTP-17738 Aux Id: PR-4926, OTP-17589

Kernel 8.1.3

Fixed Bugs and Malfunctions

The internal, undocumented, but used, module inet_dns has been fixed to handle mDNS high bit usage of the Class field.

Code that uses the previously obsolete, undocumented and unused record field #dns_rr.func will need to be updated since that field is now used as a boolean flag for the mDNS high Class bit. Code that uses the also undocumented record #dns_query will need to be recompiled since a boolean field #dns_query.unicast_response has been added for the mDNS high Class bit.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-17734 Aux Id: GH-5327, OTP-17659

The fix for Linux's behaviour when reconnecting an UDP socket in PR-5120 released in OTP-24.1.2 has been refined to only dissolve the socket's connection before a connect if the socket is already connected, that is: only for a reconnect.

This allows code to open a socket with an ephemeral port, get the port number and connect; without the port number changing (on Linux). This turned out to have at least one valid use case (besides test cases).

Should one reconnect the socket then the port number may change, on Linux; it is a known quirk, which can be worked around by binding to a specific port number when opening the socket. If you can do without an ephemeral port, that is...

Own Id: OTP-17736 Aux Id: GH-5279, PR-5120, OTP-17559

Kernel 8.1.2

Fixed Bugs and Malfunctions

The undocumented DNS encode/decode module inet_dns has been cleaned up to handle the difference between "symbolic" and "raw" records in a more consistent manner.

PR-5145/OTP-17584 introduced a change that contributed to an already existing confusion, which this correction should remedy.

Own Id: OTP-17659 Aux Id: ERIERL-702

Kernel 8.1.1

Fixed Bugs and Malfunctions

Add more info about the socket 'type' ('socket' or 'port') for the DOWN message when monitoring sockets.

Own Id: OTP-17640

Kernel 8.1

Fixed Bugs and Malfunctions

The extended error information has been corrected and improved for the following BIFs: binary_to_existing_atom/2, list_to_existing_atom/1, erlang:send_after/{3,4}, and erlang:start_timer/{3,4}.

Own Id: OTP-17449 Aux Id: GH-4900

Fixed rare bug that could cause net_kernel process to hang for ever. Have seen to happen with massive number of TLS connections while remote nodes are restarting. Bug exists since OTP-22.0.

Own Id: OTP-17476 Aux Id: GH-4931, PR-4934

Improve handling of closed sockets for inet:info/1.

Own Id: OTP-17492

This change fixes a performance problem introduced in pull-request #2675. Pull-request #2675 made so the system tried to start children of already started applications which is unnecessary. This change fixes this performance problem.

Own Id: OTP-17519

Fix code:get_doc/1 to not crash when module is located in an escript.

Own Id: OTP-17570 Aux Id: PR-5139 GH-4256 ERL-1261

Parsing of the result value in the native DNS resolver has been made more defensive against incorrect results.

Own Id: OTP-17578 Aux Id: ERIERL-683

A bug in the option handling for the legacy socket adaptor, that is; when using inet_backend = socket, has been fixed. Now socket options are set before the bind() call so options regarding, for example address reuse have the desired effect.

Own Id: OTP-17580 Aux Id: GH-5122

inet:ntoa/1 has been fixed to not accept invalid numerical addresses.

Own Id: OTP-17583 Aux Id: GH-5136

Parsing of DNS records has been improved for records of known types to not accept and present malformed ones in raw format.

Own Id: OTP-17584 Aux Id: PR-5145

The ip_mreq() type for the {ip,add_membership} and {ip,drop_membership} socket options has been corrected to have an interface field instead of, incorrectly, an address field.

Own Id: OTP-17590 Aux Id: PR-5170

Improvements and New Features

Add simple utility function to display existing sockets i the erlang shell (socket:i/0).

Own Id: OTP-17376 Aux Id: OTP-17157

gen_udp can now be configured to use the socket inet-backend (in the same way as gen_tcp).

Own Id: OTP-17410

Functions erlang:set_cookie(Cookie) and erlang:get_cookie(Node) have been added for completeness and to facilitate configuring distributed nodes with different cookies.

The documentation regarding distribution cookies has been improved to be less vague.

Own Id: OTP-17538 Aux Id: GH-5063, PR-5111

A workaround has been implemented for Linux's quirky behaviour to not adjust the source IP address when connecting a connected (reconnecing) UDP socket.

The workaround is to, on Linux, always dissolve any connection before connecting an UDP socket.

Own Id: OTP-17559 Aux Id: GH-5092, PR-5120

Documented our recommendation against opening NFS-mounted files, FIFOs, devices, and similar using file:open/2.

Own Id: OTP-17576 Aux Id: ERIERL-685

Kernel 8.0.2

Fixed Bugs and Malfunctions

For gen_tcp:connect/3,4 it is possible to specify a specific source port, which should be enough to bind the socket to an address with that port before connecting.

Unfortunately that feature was lost in OTP-17216 that made it mandatory to specify the source address to get an address binding, and ignored a specified source port if no source address was specified.

That bug has now been corrected.

Own Id: OTP-17536 Aux Id: OTP-17216, ERIERL-677

Kernel 8.0.1

Fixed Bugs and Malfunctions

Fix a race condition in Global.

Own Id: OTP-16033 Aux Id: ERIERL-329, ERL-1414, GH-4448, ERL-885, GH-3923

After a node restart with init:restart/0,1, the module socket was not usable because supporting tables had been cleared and not re-initialized. This has now been fixed.

Handling of the "." domain as a search domain was incorrect and caused a crash in the DNS resolver inet_res, which has now been fixed.

Own Id: OTP-17439 Aux Id: GH-4827, PR-4888, GH-4838

Handling of combinations of the fd option and binding to an address has been corrected, especially for the local address family.

Own Id: OTP-17451 Aux Id: OTP-17374

Bug fixes and code cleanup for the new socket implementation, such as:

Assertions on the result of demonitoring has been added in the NIF code, where appropriate.

Internal state handling for socket close in the NIF code has been reviewed.

Looping over close() for EINTR in the NIF code has been removed, since it is strongly discouraged on Linux and Posix is not clear about if it is allowed.

The inet_backend temporary socket option for legacy gen_tcp sockets has been documented.

The return value from net:getaddrinfo/2 has been corrected: the protocol field is now an atom/0, instead of, incorrectly, list(atom()). The documentation has also been corrected about this return type.

Deferred close of a socket:sendfile/* file was broken and has been corrected.

Some debug code, not enabled by default, in the socket NIF has been corrected to not accidentally core dump for debug printouts of more or less innocent events.

Own Id: OTP-17452

Kernel 8.0

Fixed Bugs and Malfunctions

A bug has been fixed for the internal inet_res resolver cache that handled a resolver configuration file status timer incorrectly and caused performance problems due to many unnecessary file system accesses.

Own Id: OTP-14700 Aux Id: PR-2848

Change the value of the tag head returned by disk_log:info/1 from {ok, Head} to just Head.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-16809 Aux Id: ERL-1313

Two options have been added to erl_call. The -fetch_stdout option fetches stdout data resulting from the code invoked by erl_call. The -fetch_stdout option disables printing of the result term. In order to implement the first of these two options a new function called ei_xrpc_from has been added to erl_interface. For details see the erl_call documentation and erl_interface documentation.

Own Id: OTP-17132

Missing runtime dependencies has been added to this application.

Own Id: OTP-17243 Aux Id: PR-4557

inet:get_rc/0 has been corrected to return host entries as separate entries instead of (incorrectly) in a list within the list. This bug was introduced by OTP-16487 in OTP-23.0-rc1.

Own Id: OTP-17262 Aux Id: GH-4588, PR-4604, OTP-16487

The type gen_tcp:option_name() had a duplicate pktoptions value.

Own Id: OTP-17277

Fixed removal of empty groups from internal state in pg.

Own Id: OTP-17286 Aux Id: PR-4619

erl -remsh now prints an error message when it fails to connect to the remote node.

Own Id: OTP-17287 Aux Id: PR-4581

Fix bugs related to corrupt shell history files.

Error messages printed by shell history are now logged as logger error reports instead of written to standard error.

Own Id: OTP-17288 Aux Id: PR-4581

A logger warning is now issues when too many arguments are given to -name or -sname. Example: erl -name a b.

Own Id: OTP-17315 Aux Id: GH-4626

The cache used by inet_res now, again, can handle multiple IP addresses per domain name, and thus fixes a bug introduced in PR-3041 (OTP-13126) and PR-2891 (OTP-14485).

Own Id: OTP-17344 Aux Id: PR-4633, GH-4631, OTP-14485, OTP-12136

Sockets created with socket:accept not counted (socket:info/0).

Own Id: OTP-17372

The {fd, Fd} option to gen_tcp:listen/2 did not work for inet_backend socket, which has been fixed.

Own Id: OTP-17374 Aux Id: PR-4787, GH-4680, PR-2989, OTP-17216

Improvements and New Features

The cache used by the DNS resolver inet_res has been improved to use ETS lookups instead of server calls. This is a considerable speed improvement for cache hits.

Own Id: OTP-13126 Aux Id: PR-3041

The cache ETS table type for the internal DNS resolver inet_res has changed type (internally) to get better speed and atomicity.

Own Id: OTP-14485 Aux Id: PR-2891

The experimental socket module can now use any protocol (by name) the OS supports. Suggested in PR-2641, implemented in PR-2670.

Own Id: OTP-14601 Aux Id: PR-2641, PR-2670, OTP-16749

The DNS resolver inet_res has been updated to support CAA (RFC 6844) and URI (RFC 7553) records.

Own Id: OTP-16517 Aux Id: PR-2827

A compatibility adaptor for gen_tcp to use the new socket API has been implemented (gen_tcp_socket). Used when setting the kernel application variable inet_backend = socket.

Own Id: OTP-16611 Aux Id: OTP-16749

Extended error information for failing BIF calls as proposed in EEP 54 has been implemented.

When a BIF call from the Erlang shell fails, more information about which argument or arguments that were in error will be printed. The same extended error information will by proc_lib, common_test, and qlc when BIF calls fail.

For applications that wish to provide the same extended error information, there are new functions erl_error:format_exception/3 and erl_error:format_exception/4.

There is a new error/3 BIF that allows applications or libraries to provide extended error information in the same way for their own exceptions.

Own Id: OTP-16686

The file server can now be bypassed in file:delete/1,2 with the raw option.

Own Id: OTP-16698 Aux Id: PR-2634

An example implementation of Erlang distribution over UDS using distribution processes has been introduced.

Thanks to Jérôme de Bretagne

Own Id: OTP-16703 Aux Id: PR-2620

The process alias feature as outlined by EEP 53 has been introduced. It is introduced in order to provide a lightweight mechanism that can prevent late replies after timeout or connection loss. For more information, see EEP 53 and the documentation of the new alias/1 BIF and the new options to the monitor/3 BIF.

The call operation in the framework used by gen_server, gen_statem, and gen_event has been updated to utilize alias in order to prevent late responses. The gen_statem behavior still use a proxy process in the distributed case, since it has always prevented late replies and aliases won't work against pre OTP 24 nodes. The proxy process can be removed in OTP 26.

The alias feature also made it possible to introduce new functions similar to the erpc:receive_response() function in the gen behaviors, so the new functions gen_server:receive_response(), gen_statem:receive_response(), gen_event:receive_response() have also been introduced.

Own Id: OTP-16718 Aux Id: PR-2735

The experimental new socket API has been further developed. Some backwards incompatible changes with respect to OTP 23 have been made.

The control message format has been changed so a decoded value is now in the 'value' field instead of in the 'data' field. The 'data' field now always contains binary data.

Some type names have been changed regarding message headers and control message headers.

socket:bind/2 now returns plain ok instead of {ok, Port} which was only relevant for the inet and inet6 address families and often not interesting. To find out which port was chosen use socket:sockname/1.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-16749 Aux Id: OTP-14601

New function os:env/0 returns all OS environment variables as a list of 2-tuples.

Own Id: OTP-16793 Aux Id: ERL-1332, PR-2740

Remove the support for distributed disk logs. The new function disk_log:all/0 is to be used instead of disk_log:accessible_logs/0. The function disk_log:close/1 is to be used instead of disk_log:lclose/1,2.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-16811

Expand the spec for erl_epmd:listen_port_please/2 to mirror erl_epmd:port_please/2.

Own Id: OTP-16947 Aux Id: PR-2781

A new erl parameter for specifying a file descriptor with configuration data has been added. This makes it possible to pass the parameter "-configfd FD" when executing the erl command. When this option is given, the system will try to read and parse configuration parameters from the file descriptor.

Own Id: OTP-16952

The experimental HiPE application has been removed, together with all related functionality in other applications.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-16963

The pg2 module has been removed.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-16968

Accept references up to a size of 160-bits from remote nodes. This is the first step in an upgrade path toward using references up to 160-bits in a future OTP release.

Own Id: OTP-17005 Aux Id: OTP-16718

Allow utf-8 binaries as parts of logger_formatter template.

Own Id: OTP-17015

Let disk_log:open/1 change the size if a wrap log is opened for the first time, that is, the disk log process does not exist, and the value of option size does not match the current size of the disk log.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-17062 Aux Id: ERL-1418, GH-4469, ERIERL-537

Allow the shell history of an erlang node to be fetched and stores using a custom callback module. See shell_history configuration parameter in the kernel documentation for more details.

Own Id: OTP-17103 Aux Id: PR-2949

The simple logger (used to log events that happen before kernel has been started) has been improved to print prettier error messages.

Own Id: OTP-17106 Aux Id: PR-2885

socket:sendfile/2,3,4,5 has been implemented, for platforms that support the underlying socket library call.

Own Id: OTP-17154 Aux Id: OTP-16749

Add socket monitor(s) for all types sockets.

Own Id: OTP-17155

Fix various issues with the gen_tcp_socket. Including documenting some incompatibilities.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-17156

inet:i/0 now also shows existing gen_tcp compatibility sockets (based on 'socket').

Own Id: OTP-17157

Added support in logger for setting primary metadata. The primary metadata is passed as a base metadata to all log events in the system. See Metadata in the Logger chapter of the Kernel User's Guide for more details.

Own Id: OTP-17181 Aux Id: PR-2457

Recognize new key 'optional_applications' in application resource files.

Own Id: OTP-17189 Aux Id: PR-2675

The Fun's passed to logger:log/2,3,4 can now return metadata that will only be fetched when needed. See logger:log/2,3,4 for more details.

Own Id: OTP-17198 Aux Id: PR-2721

erpc:multicall() has been rewritten to be able to utilize the newly introduced and improved selective receive optimization.

Own Id: OTP-17201 Aux Id: PR-4534

Add utility fiunction inet:info/1 to provide miscellaneous info about a socket.

Own Id: OTP-17203 Aux Id: OTP-17156

The behaviour for gen_tcp:connect/3,4 has been changed to not per default bind to an address, which allows the network stack to delay the address and port selection to when the remote address is known. This allows better port re-use, and thus enables far more outgoing connections, since the ephemeral port range no longer has to be a hard limit.

There is a theoretical possibility that this behaviour change can affect the set of possible error values, or have other small implications on some platforms.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-17216 Aux Id: PR-2989

An option {nxdomain_reply, boolean()} has been implemented in the DNS resolver inet_res. It is useful since an nxdomain error from a name server does contain the SOA record if the domain exists at all. This record is useful to determine a TTL for negative caching of the failed entry.

Own Id: OTP-17266 Aux Id: PR-4564

Optimized lookup of local processes part of groups in pg.

Own Id: OTP-17284 Aux Id: PR-4615

The return values from module socket functions send(), sendto(), sendmsg(), sendfile() and recv() has been changed to return a tuple tagged with select when a SelectInfo was returned, and not sometimes tagged with ok.

This is a backwards incompatible change that improves usability for code using asynchronous operations.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-17355 Aux Id: OTP-17154

Fixed warnings in code matching on underscore prefixed variables.

Own Id: OTP-17385 Aux Id: OTP-17123

Kernel 7.3.1.7

Improvements and New Features

A new function global:disconnect/0 has been introduced with which one can cleanly disconnect a node from all other nodes in a cluster of global nodes.

Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264

Kernel 7.3.1.6

Fixed Bugs and Malfunctions

A call to net_kernel:setopts(new, Opts) at the same time as a connection was being set up could cause a deadlock between the net_kernel process and the process setting up the connection.

Own Id: OTP-18198 Aux Id: GH-6129, PR-6216

Kernel 7.3.1.5

Fixed Bugs and Malfunctions

By default global does not take any actions to restore a fully connected network when connections are lost due to network issues. This is problematic for all applications expecting a fully connected network to be provided, such as for example mnesia, but also for global itself. A network of overlapping partitions might cause the internal state of global to become inconsistent. Such an inconsistency can remain even after such partitions have been brought together to form a fully connected network again. The effect on other applications that expects that a fully connected network is maintained may vary, but they might misbehave in very subtle hard to detect ways during such a partitioning.

In order to prevent such issues, we have introduced a prevent overlapping partitions fix which can be enabled using the prevent_overlapping_partitions kernel(6) parameter. When this fix has been enabled, global will actively disconnect from nodes that reports that they have lost connections to other nodes. This will cause fully connected partitions to form instead of leaving the network in a state with overlapping partitions. Note that this fix has to be enabled on all nodes in the network in order to work properly. Since this quite substantially changes the behavior, this fix is currently disabled by default. Since you might get hard to detect issues without this fix you are, however, strongly advised to enable this fix in order to avoid issues such as the ones described above. As of OTP 25 this fix will become enabled by default.

Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611

Fix failed accepted connection setup after previous established connection from same node closed down silently.

Own Id: OTP-17979 Aux Id: ERIERL-780

Improvements and New Features

A net_tickintensity kernel parameter has been introduced. It can be used to control the amount of ticks during a net_ticktime period.

A new net_kernel:start/2 function has also been introduced in order to make it easier to add new options. The use of net_kernel:start/1 has been deprecated.

Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740

Kernel 7.3.1.4

Fixed Bugs and Malfunctions

Parsing of the result value in the native DNS resolver has been made more defensive against incorrect results.

Own Id: OTP-17578 Aux Id: ERIERL-683

Kernel 7.3.1.3

Fixed Bugs and Malfunctions

Fix code:get_doc/1 to not crash when module is located in an escript.

Own Id: OTP-17570 Aux Id: PR-5139 GH-4256 ERL-1261

Kernel 7.3.1.2

Fixed Bugs and Malfunctions

Handling of the "." domain as a search domain was incorrect and caused a crash in the DNS resolver inet_res, which has now been fixed.

Own Id: OTP-17473 Aux Id: GH-4838, OTP-17439

Fixed rare bug that could cause net_kernel process to hang for ever. Have seen to happen with massive number of TLS connections while remote nodes are restarting. Bug exists since OTP-22.0.

Own Id: OTP-17476 Aux Id: GH-4931, PR-4934

Kernel 7.3.1.1

Fixed Bugs and Malfunctions

Fix a race condition in Global.

Own Id: OTP-16033 Aux Id: ERIERL-329, ERL-1414, GH-4448, ERL-885, GH-3923

Kernel 7.3.1

Fixed Bugs and Malfunctions

A bug in the Erlang DNS resolver has been fixed, where it could be made to bring down the kernel supervisor and thereby the whole node, when getting an incorrect (IN A reply to an IN CNAME query) reply from the DNS server and used the reply record's value without verifying its type.

Own Id: OTP-17361

Kernel 7.3

Fixed Bugs and Malfunctions

The range check for compression pointers in DNS encoding was faulty, which caused incorrect label compression encoding for very large DNS messages; larger than about 16 kBytes, such as AXFR responses. This more than 11 year old bug has now been corrected.

Own Id: OTP-13641 Aux Id: PR-2959

Fix of internal links in the erpc documentation.

Own Id: OTP-17202 Aux Id: PR-4516

Fix bug where complex seq_trace tokens (that is lists, tuples, maps etc) could becomes corrupted by the GC. The bug was introduced in OTP-21.

Own Id: OTP-17209 Aux Id: PR-3039

When running Xref in the modules mode, the Debugger application would show up as a dependency for the Kernel applications.

Own Id: OTP-17223 Aux Id: GH-4546, PR-4554

Improvements and New Features

erl_epmd (the epmd client) will now try to reconnect to the local EPMD if the connection is broken.

Own Id: OTP-17178 Aux Id: PR-3003

Kernel 7.2.1

Fixed Bugs and Malfunctions

When using the DNS resolver option servfail_retry_timeout it did not honour the overall call time-out in e.g inet_res:getbyname/3. This misbehaviour has now been fixed. Also, the servfail_retry_timeout behaviour has been improved to only be enforced for servers that gives a servfail answer.

Own Id: OTP-12960 Aux Id: ERIERL-598, PR-4509

Kernel 7.2

Fixed Bugs and Malfunctions

The apply call's in logger.hrl are now called with erlang prefix to avoid clashed with local apply/3 functions.

Own Id: OTP-16976 Aux Id: PR-2807

Fix memory leak in pg.

Own Id: OTP-17034 Aux Id: PR-2866

Fix crash in logger_proxy due to stray gen_server:call replies not being handled. The stray replies come when logger is under heavy load and the flow control mechanism is reaching its limit.

Own Id: OTP-17038

Fixed a bug in erl_epmd:names() that caused it to return the illegal return value noport instead of {error, Reason} where Reason is the actual error reason. This bug also propagated to net_adm:names().

This bug was introduced in kernel version 7.1 (OTP 23.1).

Own Id: OTP-17054 Aux Id: ERL-1424

Improvements and New Features

Add export of some resolver documented types.

Own Id: OTP-16954 Aux Id: ERIERL-544

Add configurable retry timeout for resolver lookups.

Own Id: OTP-16956 Aux Id: ERIERL-547

gen_server:multi_call() has been optimized in the special case of only calling the local node with timeout set to infinity.

Own Id: OTP-17058 Aux Id: PR-2887

Kernel 7.1

Fixed Bugs and Malfunctions

A fallback has been implemented for file:sendfile when using inet_backend socket

Own Id: OTP-15187 Aux Id: ERL-1293

Make default TCP distribution honour option backlog in inet_dist_listen_options.

Own Id: OTP-16694 Aux Id: PR-2625

Raw option handling for the experimental gen_tcp_socket backend was broken so that all raw options were ignored by for example gen_tcp:listen/2, a bug that now has been fixed. Reported by Jan Uhlig.

Own Id: OTP-16743 Aux Id: ERL-1287

Accept fails with inet-backend socket.

Own Id: OTP-16748 Aux Id: ERL-1284

Fixed various minor errors in the socket backend of gen_tcp.

Own Id: OTP-16754

Correct disk_log:truncate/1 to count the header. Also correct the documentation to state that disk_log:truncate/1 can be used with external disk logs.

Own Id: OTP-16768 Aux Id: ERL-1312

Fix erl_epmd:port_please/2,3 type specs to include all possible error values.

Own Id: OTP-16783

Fix erl -erl_epmd_port to work properly. Before this fix it did not work at all.

Own Id: OTP-16785

Fix typespec for internal function erlang:seq_trace_info/1 to allow term/0 as returned label. This in turn fixes so that calls to seq_trace:get_token/1 can be correctly analyzer by dialyzer.

Own Id: OTP-16823 Aux Id: PR-2722

Fix erroneous double registration of processes in pg when distribution is dynamically started.

Own Id: OTP-16832 Aux Id: PR-2738

Improvements and New Features

Make (use of) the socket registry optional (still enabled by default). Its now possible to build OTP with the socket registry turned off, turn it off by setting an environment variable and controlling in runtime (via function calls and arguments when creating sockets).

Own Id: OTP-16763

erl -remsh nodename no longer requires the hostname to be given when used together with dynamic nodenames.

Own Id: OTP-16784

Kernel 7.0

Fixed Bugs and Malfunctions

Fix race condition during shutdown when shell_history is enabled. The race condition would trigger crashes in disk_log.

Own Id: OTP-16008 Aux Id: PR-2302

Fix the Erlang distribution to handle the scenario when a node connects that can handle message fragmentation but can not handle the atom cache. This bug only affects users that have implemented a custom distribution carrier. It has been present since OTP-21.

The DFLAG_FRAGMENT distribution flag was added to the set of flags that can be rejected by a distribution implementation.

Own Id: OTP-16284

Fix bug where a binary was not allowed to be the format string in calls to logger:log.

Own Id: OTP-16395 Aux Id: PR-2444

Fix bug where logger would end up in an infinite loop when trying to log the crash of a handler or formatter.

Own Id: OTP-16489 Aux Id: ERL-1134

code:lib_dir/1 has been fixed to also return the lib dir for erts.

This is been marked as an incompatibility for any application that depended on {error,bad_name} to be returned for erts.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-16502

The application stop/1 callback was not called if the application master of the application terminated.

Own Id: OTP-16504 Aux Id: PR-2328

Fix bug in application:loaded_applications/0 that could cause it to fail with badarg if for example a concurrent upgrade/downgrade is running.

Own Id: OTP-16627 Aux Id: PR-2601

Improvements and New Features

A new module erpc has been introduced in the kernel application. The erpc module implements an enhanced subset of the operations provided by the rpc module. Enhanced in the sense that it makes it possible to distinguish between returned value, raised exceptions, and other errors. erpc also has better performance and scalability than the original rpc implementation. This by utilizing the newly introduced spawn_request() BIF. Also the rpc module benefits from these improvements by utilizing erpc when it is possible.

This change has been marked as a potential incompatibility since rpc:block_call() now only is guaranteed to block other block_call() operations. The documentation previously claimed that it would block all rpc operations. This has however never been the case. It previously did not block node-local block_call() operations.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-13450 Aux Id: OTP-15251

A client node can receive its node name dynamically from the node that it first connects to. This featured can by used by

starting with erl -sname undefined

erl_interface functions ei_connect_init and friends

erl_call -R

Own Id: OTP-13812

Improved the printout of single line logger events for most of the OTP behaviours in STDLIB and Kernel. This includes proc_lib, gen_server, gen_event, gen_statem, gen_fsm, supervisor, supervisor_bridge and application.

Improved the chars_limit and depth handling in proc_lib and when formatting of exceptions.

Own Id: OTP-15299

Remove usage and documentation of old requests of the I/O-protocol.

Own Id: OTP-15695

Directories can now be opened by file:open/2 when passing the directory option.

Own Id: OTP-15835 Aux Id: PR-2212

The check of whether to log or not based on the log level in logger has been optimized by using persistent_term to store the log level.

Own Id: OTP-15948 Aux Id: PR-2356

file:read_file_info/2 can now be used on opened files and directories.

Own Id: OTP-15956 Aux Id: PR-2231

The -config option to erl now can take multiple config files without repeating the -config option. Example:

erl -config sys local

Own Id: OTP-16148 Aux Id: PR-2373

Improved node connection setup handshake protocol. Made possible to agree on protocol version without dependence on epmd or other prior knowledge of peer node version. Also added exchange of node incarnation ("creation") values and expanded the distribution capability flag field from 32 to 64 bits.

Own Id: OTP-16229

The possibility to run Erlang distribution without relying on EPMD has been extended. To achieve this a couple of new options to the inet distribution has been added.

-dist_listen false - Setup the distribution channel, but do not listen for incoming connection. This is useful when you want to use the current node to interact with another node on the same machine without it joining the entire cluster.

-erl_epmd_port Port - Configure a default port that the built-in EPMD client should return. This allows the local node to know the port to connect to for any other node in the cluster.

The erl_epmd callback API has also been extended to allow returning -1 as the creation which means that a random creation will be created by the node.

In addition a new callback function called listen_port_please has been added that allows the callback to return which listen port the distribution should use. This can be used instead of inet_dist_listen_min/max if the listen port is to be fetched from an external service.

Own Id: OTP-16250

A first EXPERIMENTAL module that is a socket backend to gen_tcp and inet has been implemented. Others will follow. Feedback will be appreciated.

Own Id: OTP-16260 Aux Id: OTP-15403

The new experimental socket module has been moved to the Kernel application.

Own Id: OTP-16312

Replace usage of deprecated function in the group module.

Own Id: OTP-16345

Minor updates due to the new spawn improvements made.

Own Id: OTP-16368 Aux Id: OTP-15251

Update of sequential tracing to also support other information transfers than message passing.

Own Id: OTP-16370 Aux Id: OTP-15251, OTP-15232

code:module_status/1 now accepts a list of modules. code:module_status/0, which returns the statuses for all loaded modules, has been added.

Own Id: OTP-16402

filelib:wildcard/1,2 is now twice as fast when a double star (**) is part of the pattern.

Own Id: OTP-16419

A new implementation of distributed named process groups has been introduced. It is available in the pg module.

Note that this pg module only has the name in common with the experimental pg module that was present in stdlib up until OTP 17.

Thanks to Maxim Fedorov for the implementation.

Own Id: OTP-16453 Aux Id: PR-2524

The pg2 module has been deprecated. It has also been scheduled for removal in OTP 24.

You are advised to replace the usage of pg2 with the newly introduced pg module. pg has a similar API, but with a more scalable implementation.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-16455

Refactored the internal handling of deprecated and removed functions.

Own Id: OTP-16469

The internal hosts file resolver cache inet_hosts has been rewritten to behave better when the hosts file changes. For example the cache is updated per entry instead of cleared and reloaded so lookups do not temporarily fail during reloading, and; when multiple processes simultaneously request reload these are now folded into one instead of all done in sequence. Reported and first solution suggestion by Maxim Fedorov.

Own Id: OTP-16487 Aux Id: PR-2516

Add code:all_available/0 that can be used to get all available modules.

Own Id: OTP-16494

As of OTP 23, the distributed disk_log feature has been deprecated. It has also been scheduled for removal in OTP 24.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-16495

Add the function code:fetch_docs/1 for fetching embedded documentation for aa Erlang module.

Own Id: OTP-16499

Improve configure for the net nif, which should increase portability.

Own Id: OTP-16530 Aux Id: OTP-16464

socket: Socket counters and socket global counters are now represented as maps (instead of property lists).

Own Id: OTP-16535

The experimental socket module has gotten restrictions removed so now the 'seqpacket' socket type should work for any communication domain (protocol family) where the OS supports it, typically the Unix Domain.

Own Id: OTP-16550 Aux Id: ERIERL-476

Allow using custom IO devices in logger_std_h.

Own Id: OTP-16563 Aux Id: PR-2523

Added file:del_dir_r/1 which deletes a directory together with all of its contents, similar to rm -rf on Unix systems.

Own Id: OTP-16570 Aux Id: PR-2565

socket: By default the socket options rcvtimeo and sndtimeo are now disabled. To enable these, OTP now has to be built with the configure option --enable-esock-rcvsndtimeo

Own Id: OTP-16620

The experimental gen_tcp compatibility code utilizing the socket module could loose buffered data when receiving a specified number of bytes. This bug has been fixed. Reported by Maksim Lapshin on bugs.erlang.org ERL-1234

Own Id: OTP-16632 Aux Id: ERL-1234

Kernel 6.5.2.5

Fixed Bugs and Malfunctions

By default global does not take any actions to restore a fully connected network when connections are lost due to network issues. This is problematic for all applications expecting a fully connected network to be provided, such as for example mnesia, but also for global itself. A network of overlapping partitions might cause the internal state of global to become inconsistent. Such an inconsistency can remain even after such partitions have been brought together to form a fully connected network again. The effect on other applications that expects that a fully connected network is maintained may vary, but they might misbehave in very subtle hard to detect ways during such a partitioning.

In order to prevent such issues, we have introduced a prevent overlapping partitions fix which can be enabled using the prevent_overlapping_partitions kernel(6) parameter. When this fix has been enabled, global will actively disconnect from nodes that reports that they have lost connections to other nodes. This will cause fully connected partitions to form instead of leaving the network in a state with overlapping partitions. Note that this fix has to be enabled on all nodes in the network in order to work properly. Since this quite substantially changes the behavior, this fix is currently disabled by default. Since you might get hard to detect issues without this fix you are, however, strongly advised to enable this fix in order to avoid issues such as the ones described above. As of OTP 25 this fix will become enabled by default.

Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611

Improvements and New Features

A net_tickintensity kernel parameter has been introduced. It can be used to control the amount of ticks during a net_ticktime period.

A new net_kernel:start/2 function has also been introduced in order to make it easier to add new options. The use of net_kernel:start/1 has been deprecated.

Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740

Kernel 6.5.2.4

Fixed Bugs and Malfunctions

Fixed rare bug that could cause net_kernel process to hang for ever. Have seen to happen with massive number of TLS connections while remote nodes are restarting. Bug exists since OTP-22.0.

Own Id: OTP-17476 Aux Id: GH-4931, PR-4934

Kernel 6.5.2.3

Fixed Bugs and Malfunctions

Fix a race condition in Global.

Own Id: OTP-16033 Aux Id: ERIERL-329, ERL-1414, GH-4448, ERL-885, GH-3923

Kernel 6.5.2.2

Fixed Bugs and Malfunctions

When running Xref in the modules mode, the Debugger application would show up as a dependency for the Kernel applications.

Own Id: OTP-17223 Aux Id: GH-4546, PR-4554

Kernel 6.5.2.1

Fixed Bugs and Malfunctions

Fix bug in application:loaded_applications/0 that could cause it to fail with badarg if for example a concurrent upgrade/downgrade is running.

Own Id: OTP-16627 Aux Id: PR-2601

Kernel 6.5.2

Fixed Bugs and Malfunctions

The DNS resolver `inet_res` has been fixed to return the last intermediate error when subsequent requests times out.

Own Id: OTP-16414 Aux Id: ERIERL-452

The prim_net nif (net/kernel) made use of an undefined atom, notsup. This has now been corrected.

Own Id: OTP-16440

Fix a crash when attempting to log faults when loading files during early boot.

Own Id: OTP-16491

Fix crash in logger when logging to a remote node during boot.

Own Id: OTP-16493 Aux Id: ERIERL-459

Improvements and New Features

Improved net_kernel debug functionality.

Own Id: OTP-16458 Aux Id: PR-2525

Kernel 6.5.1

Fixed Bugs and Malfunctions

The 'socket state' info provided by the inet info function has been improved

Own Id: OTP-16043 Aux Id: ERL-1036

Fix bug where logger would crash when starting when a very large log file needed to be rotated and compressed.

Own Id: OTP-16145 Aux Id: ERL-1034

Fixed a bug causing actual nodedown reason reported by net_kernel:monitor_nodes(true, [nodedown_reason]) to be lost and replaced by the reason killed.

Own Id: OTP-16216

The documentation for rpc:call/4,5/ has been updated to describe what happens when the called function throws or return an 'EXIT' tuple.

Own Id: OTP-16279 Aux Id: ERL-1066

Kernel 6.5

Fixed Bugs and Malfunctions

The type specification for gen_sctp:connect/4,5 has been corrected.

Own Id: OTP-15344 Aux Id: ERL-947

Extra -mode flags given to erl are ignored with a warning.

Own Id: OTP-15852

Fix type spec for seq_trace:set_token/2.

Own Id: OTP-15858 Aux Id: ERL-700

logger:compare_levels/2 would fail with a badarg exception if given the values all or none as any of the parameters. This is now corrected.

Own Id: OTP-15942 Aux Id: PR-2301

Fix bug where the log file in logger_std_h would not be closed when the inode of the file changed. This would in turn cause a file descriptor leak when tools like logrotate are used.

Own Id: OTP-15997 Aux Id: PR-2331

Fix a race condition in the debugging function net_kernel:nodes_info/0.

Own Id: OTP-16022

Fix race condition when closing a file opened in compressed or delayed_write mode.

Own Id: OTP-16023

Improvements and New Features

The possibility to send ancillary data, in particular the TOS field, has been added to gen_udp:send/4,5.

Own Id: OTP-15747 Aux Id: ERIERL-294

If the log file was given with relative path, the standard logger handler (logger_std_h) would store the file name with relative path. If the current directory of the node was later changed, a new file would be created relative the new current directory, potentially failing with an enoent if the new directory did not exist. This is now corrected and logger_std_h always stores the log file name as an absolute path, calculated from the current directory at the time of the handler startup.

Own Id: OTP-15850

Support local sockets with inet:i/0.

Own Id: OTP-15935 Aux Id: PR-2299

Kernel 6.4.1

Fixed Bugs and Malfunctions

user/user_drv could respond to io requests before they had been processed, which could cause data to be dropped if the emulator was halted soon after a call to io:format/2, such as in an escript.

Own Id: OTP-15805

Kernel 6.4

Fixed Bugs and Malfunctions

Fix so that when multiple -sname or -name are given to erl the first one is chosen. Before this fix distribution was not started at all when multiple name options were given.

Own Id: OTP-15786 Aux Id: ERL-918

Fix inet_res configuration pointing to non-existing files to work again. This was broken in KERNEL-6.3 (OTP-21.3).

Own Id: OTP-15806

Improvements and New Features

A simple socket API is provided through the socket module. This is a low level API that does not replace gen_[tcp|udp|sctp]. It is intended to eventually replace the inet driver, but not the high level gen-modules (gen_tcp, gen_udp and gen_sctp). It also provides a basic API that facilitates the implementation of other protocols, that is TCP, UDP and SCTP.

Known issues are; No support for the Windows OS (currently).

Own Id: OTP-14831

Improved the documentation for the linger option.

Own Id: OTP-15491 Aux Id: PR-2019

Global no longer tries more than once when connecting to other nodes.

Own Id: OTP-15607 Aux Id: ERIERL-280

The dist messages EXIT, EXIT2 and MONITOR_DOWN have been updated with new versions that send the reason term as part of the payload of the message instead of as part of the control message.

The old versions are still present and can be used when communicating with nodes that don't support the new versions.

Own Id: OTP-15611

Kernel configuration parameter start_distribution = boolean() is added. If set to false, the system is started with all distribution functionality disabled. Defaults to true.

Own Id: OTP-15668 Aux Id: PR-2088

In OTP-21.3, a warning was introduced for duplicated applications/keys in configuration. This warning would be displayed both when the configuration was given as a file on system start, and during runtime via application:set_env/1,2.

The warning is now changed to a badarg exception in application:set_env/1,2. If the faulty configuration is given in a configuration file on system start, the startup will fail.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-15692 Aux Id: PR-2170

Kernel 6.3.1.3

Fixed Bugs and Malfunctions

Fix bug where the log file in logger_std_h would not be closed when the inode of the file changed. This would in turn cause a file descriptor leak when tools like logrotate are used.

Own Id: OTP-15997 Aux Id: PR-2331

Kernel 6.3.1.2

Improvements and New Features

The possibility to send ancillary data, in particular the TOS field, has been added to gen_udp:send/4,5.

Own Id: OTP-15747 Aux Id: ERIERL-294

Kernel 6.3.1.1

Fixed Bugs and Malfunctions

Fix type spec for seq_trace:set_token/2.

Own Id: OTP-15858 Aux Id: ERL-700

Kernel 6.3.1

Fixed Bugs and Malfunctions

Fixed a performance regression when reading files opened with the compressed flag.

Own Id: OTP-15706 Aux Id: ERIERL-336

Kernel 6.3

Fixed Bugs and Malfunctions

If for example the /etc/hosts did not come into existence until after the kernel application had started, its content was never read. This bug has now been corrected.

Own Id: OTP-14702 Aux Id: PR-2066

Fix bug where doing seq_trace:reset_trace() while another process was doing a garbage collection could cause the run-time system to segfault.

Own Id: OTP-15490

Fix erl_epmd:port_please spec to include atom/0 and string/0.

Own Id: OTP-15557 Aux Id: PR-2117

The Logger handler logger_std_h now keeps track of the inode of its log file in order to re-open the file if the inode changes. This may happen, for instance, if the log file is opened and saved by an editor.

Own Id: OTP-15578 Aux Id: ERL-850

When user specific file modes are given to the logger handler logger_std_h, they were earlier accepted without any control. This is now changes, so Logger will adjust the file modes as follows:

- If raw is not found in the list, it is added.
- If none of write, append or exclusive are found in the list, append is added.
- If none of delayed_write or {delayed_write,Size,Delay} are found in the list, delayed_write is added.

Own Id: OTP-15602

Improvements and New Features

The standard logger handler, logger_std_h, now has a new internal feature for log rotation. The rotation scheme is as follows:

The log file to which the handler currently writes always has the same name, i.e. the name which is configured for the handler. The archived files have the same name, but with extension ".N", where N is an integer. The newest archive has extension ".0", and the oldest archive has the highest number.

The size at which the log file is rotated, and the number of archive files that are kept, is specified with the handler specific configuration parameters max_no_bytes and max_no_files respectively.

Archives can be compressed, in which case they get a ".gz" file extension after the integer. Compression is specified with the handler specific configuration parameter compress_on_rotate.

Own Id: OTP-15479

The new functions logger:i/0 and logger:i/1 are added. These provide the same information as logger:get_config/0 and other logger:get_*_config functions, but the information is more logically sorted and more readable.

Own Id: OTP-15600

Logger is now protected against overload due to massive amounts of log events from the emulator or from remote nodes.

Own Id: OTP-15601

Logger now uses os:system_time/1 instead of erlang:system_time/1 to generate log event timestamps.

Own Id: OTP-15625

Add functions application:set_env/1,2 and application:set_env/2. These take a list of application configuration parameters, and the behaviour is equivalent to calling application:set_env/4 individually for each application/key combination, except it is more efficient.

set_env/1,2 warns about duplicated applications or keys. The warning is also emitted during boot, if applications or keys are duplicated within one configuration file, e.g. sys.config.

Own Id: OTP-15642 Aux Id: PR-2164

Handler specific configuration parameters for the standard handler logger_std_h are changed to be more intuitive and more similar to the disk_log handler.

Earlier there was only one parameter, type, which could have the values standard_io, standard_error, {file,FileName} or {file,FileName,Modes}.

This is now changed, so the following parameters are allowed:

type = standard_io | standard_error | file
file = file:filename()
modes = [file:mode()]

All parameters are optional. type defaults to standard_io, unless a file name is given, in which case it defaults to file. If type is set to file, the file name defaults to the same as the handler id.

The potential incompatibility is that logger:get_config/0 and logger:get_handler_config/1 now returns the new parameters, even if the configuration was set with the old variant, e.g. #{type=>{file,FileName}}.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-15662

The new configuration parameter file_check is added to the Logger handler logger_std_h. This parameter specifies how long (in milliseconds) the handler may wait before checking if the log file still exists and the inode is the same as when it was opened.

The default value is 0, which means that this check is done prior to each write operation. Setting a higher number may improve performance, but adds the risk of losing log events.

Own Id: OTP-15663

Kernel 6.2.1

Fixed Bugs and Malfunctions

Setting the recbuf size of an inet socket the buffer is also automatically increased. Fix a bug where the auto adjustment of inet buffer size would be triggered even if an explicit inet buffer size had already been set.

Own Id: OTP-15651 Aux Id: ERIERL-304

Kernel 6.2

Fixed Bugs and Malfunctions

A new function, logger:update_handler_config/3 is added, and the handler callback changing_config now has a new argument, SetOrUpdate, which indicates if the configuration change comes from set_handler_config/2,3 or update_handler_config/2,3.

This allows the handler to consistently merge the new configuration with the old (if the change comes from update_handler_config/2,3) or with the default (if the change comes from set_handler_config/2,3).

The built-in handlers logger_std_h and logger_disk_log_h are updated accordingly. A bug which could cause inconsistency between the handlers' internal state and the stored configuration is also corrected.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-15364

Fix fallback when custom erl_epmd client does not implement address_please.

Own Id: OTP-15388 Aux Id: PR-1983

The logger ets table did not have the read_concurrency option. This is now added.

Own Id: OTP-15453 Aux Id: ERL-782

During system start, logger has a simple handler which prints to stdout. After the kernel supervision is started, this handler is removed and replaced by the default handler. Due to a bug, logger earlier issued a debug printout saying it received an unexpected message, which was the EXIT message from the simple handler's process. This is now corrected. The simple handler's process now unlinks from the logger process before terminating.

Own Id: OTP-15466 Aux Id: ERL-788

The logger handler logger_std_h would not re-create it's log file if it was removed. Due to this it could not be used with tools like 'logrotate'. This is now corrected.

Own Id: OTP-15469

Improvements and New Features

A function inet:getifaddrs/1 that takes a list with a namespace option has been added, for platforms that support that feature, for example Linux (only?).

Own Id: OTP-15121 Aux Id: ERIERL-189, PR-1974

Added the nopush option for TCP sockets, which corresponds to TCP_NOPUSH on *BSD and TCP_CORK on Linux.

This is also used internally in file:sendfile to reduce latency on subsequent send operations.

Own Id: OTP-15357 Aux Id: ERL-698

Optimize handling of send_delay for tcp sockes to better work with the new pollthread implementation introduced in OTP-21.

Own Id: OTP-15471 Aux Id: ERIERL-229

Kernel 6.1.1

Fixed Bugs and Malfunctions

Fix bug causing net_kernel process crash on connection attempt from node with name identical to local node.

Own Id: OTP-15438 Aux Id: ERL-781

Kernel 6.1

Fixed Bugs and Malfunctions

The values all and none are documented as valid value for the Kernel configuration parameter logger_level, but would cause a crash during node start. This is now corrected.

Own Id: OTP-15143

Fix some potential buggy behavior in how ticks are sent on inter node distribution connections. Tick is now sent to c-node even if there are unsent buffered data, as c-nodes need ticks in order to send reply ticks. The amount of sent data was also calculated wrongly when ticks were suppressed due to unsent buffered data.

Own Id: OTP-15162 Aux Id: ERIERL-191

Non semantic change in dist_util.erl to silence dialyzer warning.

Own Id: OTP-15170

Fixed net_kernel:connect_node(node()) to return true (and do nothing) as it always has before OTP-21.0. Also documented this successful "self connect" as the expected behavior.

Own Id: OTP-15182 Aux Id: ERL-643

The single_line option on logger_formatter would in some cases add an unwanted comma after the association arrows in a map. This is now corrected.

Own Id: OTP-15228

Improved robustness of distribution connection setup. In OTP-21.0 a truly asynchronous connection setup was introduced. This is further improvement on that work to make the emulator more robust and also be able to recover in cases when involved Erlang processes misbehave.

Own Id: OTP-15297 Aux Id: OTP-15279, OTP-15280

Improvements and New Features

A new macro, ?LOG(Level,...), is added. This is equivalent to the existing ?LOG_<LEVEL>(...) macros.

A new variant of Logger report callback is added, which takes an extra argument containing options for size limiting and line breaks. Module proc_lib in STDLIB uses this for crash reports.

Logger configuration is now checked a bit more for errors.

Own Id: OTP-15132

The socket options recvtos, recvttl, recvtclass and pktoptions have been implemented in the socket modules. See the documentation for the gen_tcp, gen_udp and inet modules. Note that support for these in the runtime system is platform dependent. Especially for pktoptions which is very Linux specific and obsoleted by the RFCs that defined it.

Own Id: OTP-15145 Aux Id: ERIERL-187

Add logger:set_application_level/2 for setting the logger level of all modules in one application.

Own Id: OTP-15146

Kernel 6.0.1

Fixed Bugs and Malfunctions

Fixed bug in net_kernel that could cause an emulator crash if certain connection attempts failed. Bug exists since kernel-6.0 (OTP-21.0).

Own Id: OTP-15280 Aux Id: ERIERL-226, OTP-15279

Kernel 6.0

Fixed Bugs and Malfunctions

Clarify the documentation of rpc:multicall/5.

Own Id: OTP-10551

The DNS resolver when getting econnrefused from a server retained an invalid socket so look up towards the next server(s) also failed.

Own Id: OTP-13133 Aux Id: PR-1557

No resolver backend returns V4Mapped IPv6 addresses any more. This was inconsistent before, some did, some did not. To facilitate working with such addresses a new function inet:ipv4_mapped_ipv6_address/1 has been added.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-13761 Aux Id: ERL-503

The type specifications for file:posix/0 and inet:posix/0 have been updated according to which errors file and socket operations should be able to return.

Own Id: OTP-14019 Aux Id: ERL-550

Fix name resolving in IPv6 only environments when doing the initial distributed connection.

Own Id: OTP-14501

File operations used to accept filenames containing null characters (integer value zero). This caused the name to be truncated and in some cases arguments to primitive operations to be mixed up. Filenames containing null characters inside the filename are now rejected and will cause primitive file operations to fail.

Also environment variable operations used to accept names and values of environment variables containing null characters (integer value zero). This caused operations to silently produce erroneous results. Environment variable names and values containing null characters inside the name or value are now rejected and will cause environment variable operations to fail.

Primitive environment variable operations also used to accept the $= character in environment variable names causing various problems. $= characters in environment variable names are now also rejected.

Also os:cmd/1 now reject null characters inside its command.

erlang:open_port/2 will also reject null characters inside the port name from now on.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-14543 Aux Id: ERL-370

os:putenv and os:getenv no longer access the process environment directly and instead work on a thread-safe emulation. The only observable difference is that it's not kept in sync with libc getenv(3) / putenv(3), so those who relied on that behavior in drivers or NIFs will need to add manual synchronization.

On Windows this means that you can no longer resolve DLL dependencies by modifying the PATH just before loading the driver/NIF. To make this less of a problem, the emulator now adds the target DLL's folder to the DLL search path.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-14666

Fixed connection tick toward primitive hidden nodes (erl_interface) that could cause faulty tick timeout in rare cases when payload data is sent to hidden node but not received.

Own Id: OTP-14681

Make group react immediately on an EXIT-signal from shell in e.g ssh.

Own Id: OTP-14991 Aux Id: PR1705

Calls to gen_tcp:send/2 on closed sockets now returns {error, closed} instead of {error,enotconn}.

Own Id: OTP-15001

The included_applications key are no longer duplicated as application environment variable. Earlier, the included applications could be read both with application:get[_all]_env(...) and application:get[_all]_key(...) functions. Now, it can only be read with application:get[_all]_key(...).

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-15071

Owner and group changes through file:write_file_info, file:change_owner, and file:change_group will no longer report success on permission errors.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-15118

Improvements and New Features

A new logging API is added to Erlang/OTP, see the logger manual page, and section Logging in the Kernel User's Guide.

Calls to error_logger are automatically redirected to the new API, and legacy error logger event handlers can still be used. It is, however, recommended to use the Logger API directly when writing new code.

Notice the following potential incompatibilities:

Kernel configuration parameters error_logger still works, but is overruled if the default handler's output destination is configured with Kernel configuration parameter logger.

In general, parameters for configuring error logger are overwritten by new parameters for configuring Logger.

The concept of SASL error logging is deprecated, meaning that by default the SASL application does not affect which log events are logged.

By default, supervisor reports and crash reports are logged by the default Logger handler started by Kernel, and end up at the same destination (terminal or file) as other standard log event from Erlang/OTP.

Progress reports are not logged by default, but can be enabled by setting the primary log level to info, for example with the Kernel configuration parameter logger_level.

To obtain backwards compatibility with the SASL error logging functionality from earlier releases, set Kernel configuration parameter logger_sasl_compatible to true. This prevents the default Logger handler from logging any supervisor-, crash-, or progress reports. Instead, SASL adds a separate Logger handler during application start, which takes care of these log events. The SASL configuration parameters sasl_error_logger and sasl_errlog_type specify the destination (terminal or file) and severity level to log for these events.

Since Logger is new in Erlang/OTP 21.0, we do reserve the right to introduce changes to the Logger API and functionality in patches following this release. These changes might or might not be backwards compatible with the initial version.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-13295

The function inet:i/0 has been documented.

Own Id: OTP-13713 Aux Id: PR-1645

Typespecs for netns and bind_to_device options have been added to gen_tcp, gen_udp and gen_sctp functions.

Own Id: OTP-14359 Aux Id: PR-1816

New functionality for implementation of alternative carriers for the Erlang distribution has been introduced. This mainly consists of support for usage of distribution controller processes (previously only ports could be used as distribution controllers). For more information see ERTS User's Guide ➜ How to implement an Alternative Carrier for the Erlang Distribution ➜ Distribution Module.

Own Id: OTP-14459

seq_trace labels may now be any erlang term.

Own Id: OTP-14899

The SSL distribution protocol -proto inet_tls has stopped setting the SSL option server_name_indication. New verify funs for client and server in inet_tls_dist has been added, not documented yet, that checks node name if present in peer certificate. Usage is still also yet to be documented.

Own Id: OTP-14969 Aux Id: OTP-14465, ERL-598

Changed timeout of gen_server calls to auth server from default 5 seconds to infinity.

Own Id: OTP-15009 Aux Id: ERL-601

The callback module passed as -epmd_module to erl has been expanded to be able to do name and port resolving.

Documentation has also been added in the erl_epmd reference manual and ERTS User's Guide How to Implement an Alternative Node Discovery for Erlang Distribution.

Own Id: OTP-15086 Aux Id: PR-1694

Included config file specified with relative path in sys.config are now first searched for relative to the directory of sys.config itself. If not found, it is also searched for relative to the current working directory. The latter is for backwards compatibility.

Own Id: OTP-15137 Aux Id: PR-1838

Kernel 5.4.3.2

Fixed Bugs and Malfunctions

Non semantic change in dist_util.erl to silence dialyzer warning.

Own Id: OTP-15170

Kernel 5.4.3.1

Fixed Bugs and Malfunctions

Fix some potential buggy behavior in how ticks are sent on inter node distribution connections. Tick is now sent to c-node even if there are unsent buffered data, as c-nodes need ticks in order to send reply ticks. The amount of sent data was calculated wrongly when ticks where suppressed due to unsent buffered data.

Own Id: OTP-15162 Aux Id: ERIERL-191

Kernel 5.4.3

Fixed Bugs and Malfunctions

Correct a few contracts.

Own Id: OTP-14889

Reject loading modules with names containing directory separators ('/' or '\' on Windows).

Own Id: OTP-14933 Aux Id: ERL-564, PR-1716

Fix bug in handling of os:cmd/2 option max_size on windows.

Own Id: OTP-14940

Kernel 5.4.2

Fixed Bugs and Malfunctions

Add os:cmd/2 that takes an options map as the second argument.

Add max_size as an option to os:cmd/2 that control the maximum size of the result that os:cmd/2 will return.

Own Id: OTP-14823

Kernel 5.4.1

Fixed Bugs and Malfunctions

Refactored an internal API.

Own Id: OTP-14784

Kernel 5.4

Fixed Bugs and Malfunctions

Processes which did output after switching jobs (Ctrl+G) could be left forever stuck in the io request.

Own Id: OTP-14571 Aux Id: ERL-472

Improvements and New Features

Lock counting can now be fully toggled at runtime in the lock counting emulator (-emu_type lcnt). Everything is enabled by default to match the old behavior, but specific categories can be toggled at will with minimal runtime overhead when disabled. Refer to the documentation on lcnt:rt_mask/1 for details.

Own Id: OTP-13170

lcnt:collect and lcnt:clear will no longer block all other threads in the runtime system.

Own Id: OTP-14412

General Unicode improvements.

Own Id: OTP-14462

Kernel 5.3.1

Fixed Bugs and Malfunctions

The documentation for the 'quiet' option in disk_log:open/1 had an incorrect default value.

Own Id: OTP-14498

Kernel 5.3

Fixed Bugs and Malfunctions

Function inet:ntoa/1 has been fixed to return lowercase letters according to RFC 5935 that has been approved after this function was written. Previously uppercase letters were returned so this may be a backwards incompatible change depending on how the returned address string is used.

Function inet:parse_address/1 has been fixed to accept %-suffixes on scoped addresses. The addresses does not work yet, but gives no parse errors.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-13006 Aux Id: ERIERL-20, ERL-429

Fix bug where gethostname would incorrectly fail with enametoolong on Linux.

Own Id: OTP-14310

Fix bug causing code:is_module_native to falsely return true when local call trace is enabled for the module.

Own Id: OTP-14390

Add early reject of invalid node names from distributed nodes.

Own Id: OTP-14426

Improvements and New Features

Since Unicode is now allowed in atoms an extra check is needed for node names, which are restricted to Latin-1.

Own Id: OTP-13805

Replaced usage of deprecated symbolic time unit representations.

Own Id: OTP-13831 Aux Id: OTP-13735

file:write_file(Name, Data, [raw]) would turn Data into a single binary before writing. This meant it could not take advantage of the writev() system call if it was given a list of binaries and told to write with raw mode.

Own Id: OTP-13909

The performance of the disk_log has been somewhat improved in some corner cases (big items), and the documentation has been clarified.

Own Id: OTP-14057 Aux Id: PR-1245

Functions for detecting changed code has been added. code:modified_modules/0 returns all currently loaded modules that have changed on disk. code:module_status/1 returns the status for a module. In the shell and in c module, mm/0 is short for code:modified_modules/0, and lm/0 reloads all currently loaded modules that have changed on disk.

Own Id: OTP-14059

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.

Own Id: OTP-14186

Sockets can now be bound to device (SO_BINDTODEVICE) on platforms where it is supported.

This has been implemented e.g to support VRF-Lite under Linux; see VRF , and GitHub pull request #1326.

Own Id: OTP-14357 Aux Id: PR-1326

Added option to store shell_history on disk so that the history can be reused between sessions.

Own Id: OTP-14409 Aux Id: PR-1420

The size of crash reports created by gen_server, gen_statem and proc_lib is limited with aid of the Kernel application variable error_logger_format_depth. The purpose is to limit the size of the messages sent to the error_logger process when processes with huge message queues or states crash.

The crash report generated by proc_lib includes the new tag message_queue_len. The neighbour report also includes the new tag current_stacktrace. Finally, the neighbour report no longer includes the tags messages and dictionary.

The new function error_logger:get_format_depth/0 can be used to retrieve the value of the Kernel application variable error_logger_format_depth.

Own Id: OTP-14417

One of the ETS tables used by the global module is created with {read_concurrency, true} in order to reduce contention.

Own Id: OTP-14419

Warnings have been added to the relevant documentation about not using un-secure distributed nodes in exposed environments.

Own Id: OTP-14425

Kernel 5.2

Fixed Bugs and Malfunctions

Fix a race during cleanup of os:cmd that would cause os:cmd to hang indefinitely.

Own Id: OTP-14232 Aux Id: seq13275

Improvements and New Features

The functions in the 'file' module that take a list of paths (e.g. file:path_consult/2) will now continue to search in the path if the path contains something that is not a directory.

Own Id: OTP-14191

Two OTP processes that are known to receive many messages are 'rex' (used by 'rpc') and 'error_logger'. Those processes will now store unprocessed messages outside the process heap, which will potentially decrease the cost of garbage collections.

Own Id: OTP-14192

Kernel 5.1.1

Fixed Bugs and Malfunctions

code:add_pathsa/1 and command line option -pa both revert the given list of directories when adding it at the beginning of the code path. This is now documented.

Own Id: OTP-13920 Aux Id: ERL-267

Add lost runtime dependency to erts-8.1. This should have been done in kernel-5.1 (OTP-19.1) as it cannot run without at least erts-8.1 (OTP-19.1).

Own Id: OTP-14003

Type and doc for gen_{tcp,udp,sctp}:controlling_process/2 has been improved.

Own Id: OTP-14022 Aux Id: PR-1208

Kernel 5.1

Fixed Bugs and Malfunctions

Fix a memory leak when calling seq_trace:get_system_tracer().

Own Id: OTP-13742

Fix for the problem that when adding the ebin directory of an application to the code path, the code:priv_dir/1 function returns an incorrect path to the priv directory of the same application.

Own Id: OTP-13758 Aux Id: ERL-195

Fix code_server crash when adding code paths of two levels.

Own Id: OTP-13765 Aux Id: ERL-194

Respect -proto_dist switch while connection to EPMD

Own Id: OTP-13770 Aux Id: PR-1129

Fixed a bug where init:stop could deadlock if a process with infinite shutdown timeout (e.g. a supervisor) attempted to load code while terminating.

Own Id: OTP-13802

Close stdin of commands run in os:cmd. This is a backwards compatibility fix that restores the behaviour of pre 19.0 os:cmd.

Own Id: OTP-13867 Aux Id: seq13178

Improvements and New Features

Add net_kernel:setopts/2 and net_kernel:getopts/2 to control options for distribution sockets in runtime.

Own Id: OTP-13564

Rudimentary support for DSCP has been implemented in the guise of a tclass socket option for IPv6 sockets.

Own Id: OTP-13582

Kernel 5.0.2

Fixed Bugs and Malfunctions

When calling os:cmd from a process that has set trap_exit to true an 'EXIT' message would be left in the message queue. This bug was introduced in kernel vsn 5.0.1.

Own Id: OTP-13813

Kernel 5.0.1

Fixed Bugs and Malfunctions

Fix a os:cmd bug where creating a background job using & would cause os:cmd to hang until the background job terminated or closed its stdout and stderr file descriptors. This bug has existed from kernel 5.0.

Own Id: OTP-13741

Kernel 5.0

Fixed Bugs and Malfunctions

The handling of on_load functions has been improved. The major improvement is that if a code upgrade fails because the on_load function fails, the previous version of the module will now be retained.

Own Id: OTP-12593

rpc:call() and rpc:block_call() would sometimes cause an exception (which was not mentioned in the documentation). This has been corrected so that {badrpc,Reason} will be returned instead.

Own Id: OTP-13409

On Windows, for modules that were loaded early (such as the lists module), code:which/1 would return the path with mixed slashes and backslashes, for example: "C:\\Program Files\\erl8.0/lib/stdlib-2.7/ebin/lists.beam". This has been corrected.

Own Id: OTP-13410

Make file:datasync use fsync instead of fdatasync on Mac OSX.

Own Id: OTP-13411

The default chunk size for the fallback sendfile implementation, used on platforms that do not have a native sendfile, has been decreased in order to reduce connectivity issues.

Own Id: OTP-13444

Large file writes (2Gb or more) could fail on some Unix platforms (for example, OS X and FreeBSD).

Own Id: OTP-13461

A bug has been fixed where the DNS resolver inet_res did not refresh its view of the contents of for example resolv.conf immediately after start and hence then failed name resolution. Reported and fix suggested by Michal Ptaszek in GitHUB pull req #949.

Own Id: OTP-13470 Aux Id: Pull #969

Fix process leak from global_group.

Own Id: OTP-13516 Aux Id: PR-1008

The function inet:gethostbyname/1 now honors the resolver option inet6 instead of always looking up IPv4 addresses.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-13622 Aux Id: PR-1065

The Status argument to init:stop/1 is now sanity checked to make sure erlang:halt does not fail.

Own Id: OTP-13631 Aux Id: PR-911

Improvements and New Features

Add {line_delim, byte()} option to inet:setopts/2 and decode_packet/3

Own Id: OTP-12837

Added os:perf_counter/1.

The perf_counter is a very very cheap and high resolution timer that can be used to timestamp system events. It does not have monoticity guarantees, but should on most OS's expose a monotonous time.

Own Id: OTP-12908

The os:cmd call has been optimized on unix platforms to be scale better with the number of schedulers.

Own Id: OTP-13089

New functions that can load multiple modules at once have been added to the 'code' module. The functions are code:atomic_load/1, code:prepare_loading/1, code:finish_loading/1, and code:ensure_modules_loaded/1.

Own Id: OTP-13111

The code path cache feature turned out not to be very useful in practice and has been removed. If an attempt is made to enable the code path cache, there will be a warning report informing the user that the feature has been removed.

Own Id: OTP-13191

When an attempt is made to start a distributed Erlang node with the same name as an existing node, the error message will be much shorter and easier to read than before. Example:

Protocol 'inet_tcp': the name somename@somehost seems to be in use by another Erlang node

Own Id: OTP-13294

The output of the default error logger is somewhat prettier and easier to read. The default error logger is used during start-up of the OTP system. If the start-up fails, the output will be easier to read.

Own Id: OTP-13325

The functions rpc:safe_multi_server_call/2,3 that were deprecated in R12B have been removed.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-13449

Update the error reasons in dist_util, and show them in the logs if net_kernel:verbose(1) has been called.

Own Id: OTP-13458

Experimental support for Unix Domain Sockets has been implemented. Read the sources if you want to try it out. Example: gen_udp:open(0, [{ifaddr,{local,"/tmp/socket"}}]). Documentation will be written after user feedback on the experimental API.

Own Id: OTP-13572 Aux Id: PR-612

Allow heart to be configured to not kill the previous emulator before calling the HEART_COMMAND. This is done by setting the environment variable HEART_NO_KILL to TRUE.

Own Id: OTP-13650

Kernel 4.2

Fixed Bugs and Malfunctions

code:load_abs([10100]) would bring down the entire runtime system and create a crash dump. Corrected to generate an error exception in the calling process.

Also corrected specs for code loading functions and added more information in the documentation about the error reasons returned by code-loading functions.

Own Id: OTP-9375

gen_tcp:accept/2 was not time warp safe. This since it used the same time as returned by erlang:now/0 when calculating timeout. This has now been fixed.

Own Id: OTP-13254 Aux Id: OTP-11997, OTP-13222

Correct the contract for inet:getifaddrs/1.

Own Id: OTP-13335 Aux Id: ERL-95

Improvements and New Features

Time warp safety improvements.

Introduced the options monotonic_timestamp, and strict_monotonic_timestamp to the trace, sequential trace, and system profile functionality. This since the already existing timestamp option is not time warp safe.

Introduced the option safe_fixed_monotonic_time to ets:info/2 and dets:info/2. This since the already existing safe_fixed option is not time warp safe.

Own Id: OTP-13222 Aux Id: OTP-11997

Add validation callback for heart

The erlang heart process may now have a validation callback installed. The validation callback will be executed, if present, before any heartbeat to heart port program. If the validation fails, or stalls, no heartbeat will be sent and the node will go down.

With the option 'check_schedulers' heart executes a responsiveness check of the schedulers before a heartbeat is sent to the port program. If the responsiveness check fails, the heartbeat will not be performed (as intended).

Own Id: OTP-13250

Clarify documentation of net_kernel:allow/1

Own Id: OTP-13299

EPMD supports both IPv4 and IPv6

Also affects oldest supported windows version.

Own Id: OTP-13364

Kernel 4.1.1

Fixed Bugs and Malfunctions

Host name lookups though inet_res, the Erlang DNS resolver, are now done case insensitively according to RFC 4343. Patch by Holger Weiß.

Own Id: OTP-12836

IPv6 distribution handler has been updated to share code with IPv4 so that all features are supported in IPv6 as well. A bug when using an IPv4 address as hostname has been fixed.

Own Id: OTP-13040

Caching of host names in the internal DNS resolver inet_res has been made character case insensitive for host names according to RFC 4343.

Own Id: OTP-13083

Cooked file mode buffering has been fixed so file:position/2 now works according to Posix on Posix systems i.e. when file:position/2 returns an error the file pointer is unaffected.

The Windows system documentation, however, is unclear on this point so the documentation of file:position/2 still does not promise anything.

Cooked file mode file:pread/2,3 and file:pwrite/2,3 have been corrected to honor character encoding like the combination of file:position/2 and file:read/2 or file:write/2 already does. This is probably not very useful since the character representation on the caller's side is latin1, period.

Own Id: OTP-13155 Aux Id: PR#646

Improvements and New Features

Add {line_delim, byte()} option to inet:setopts/2 and decode_packet/3

Own Id: OTP-12837

Kernel 4.1

Improvements and New Features

A mechanism for limiting the amount of text that the built-in error logger events will produce has been introduced. It is useful for limiting both the size of log files and the CPU time used to produce them.

This mechanism is experimental in the sense that it may be changed if it turns out that it does not solve the problem it is supposed to solve. In that case, there may be backward incompatible improvements to this mechanism.

See the documentation for the config parameter error_logger_format_depth in the Kernel application for information about how to turn on this feature.

Own Id: OTP-12864

Kernel 4.0

Fixed Bugs and Malfunctions

Fix error handling in file:read_line/1 for Unicode contents.

Own Id: OTP-12144

Introduce os:getenv/2 which is similar to os:getenv/1 but returns the passed default value if the required environment variable is undefined.

Own Id: OTP-12342

It is now possible to paste text in JCL mode (using Ctrl-Y) that has been copied in the previous shell session. Also a bug that caused the JCL mode to crash when pasting text has been fixed.

Own Id: OTP-12673

Ensure that each segment of an IPv6 address when parsed from a string has a maximum of 4 hex digits

Own Id: OTP-12773

Improvements and New Features

New BIF: erlang:get_keys/0, lists all keys associated with the process dictionary. Note: erlang:get_keys/0 is auto-imported.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-12151 Aux Id: seq12521

The internal group to user_drv protocol has been changed to be synchronous in order to guarantee that output sent to a process implementing the user_drv protocol is printed before replying. This protocol is used by the standard_output device and the ssh application when acting as a client.

This change changes the previous unlimited buffer when printing to standard_io and other devices that end up in user_drv to 1KB.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-12240

The inflateInit/2 and deflateInit/6 functions now accepts a WindowBits argument equal to 8 and -8.

Own Id: OTP-12564

Map error logger warnings to warning messages by default.

Own Id: OTP-12755

Map beam error logger warnings to warning messages by default. Previously these messages were mapped to the error channel by default.

Own Id: OTP-12781

gen_tcp:shutdown/2 is now asynchronous

This solves the following problems with the old implementation:

It doesn't block when the TCP peer is idle or slow. This is the expected behaviour when shutdown() is called: the caller needs to be able to continue reading from the socket, not be prevented from doing so.

It doesn't truncate the output. The current version of gen_tcp:shutdown/2 will truncate any outbound data in the driver queue after about 10 seconds if the TCP peer is idle of slow. Worse yet, it doesn't even inform anyone that the data has been truncated: 'ok' is returned to the caller; and a FIN rather than an RST is sent to the TCP peer.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-12797

There are many cases where user code needs to be able to distinguish between a socket that was closed normally and one that was aborted. Setting the option {show_econnreset, true} enables the user to receive ECONNRESET errors on both active and passive sockets.

Own Id: OTP-12843

Kernel 3.2.0.1

Fixed Bugs and Malfunctions

The 'raw' socket option could not be used multiple times in one call to any e.g gen_tcp function because only one of the occurrences were used. This bug has been fixed, and also a small bug concerning propagating error codes from within inet:setopts/2.

Own Id: OTP-11482 Aux Id: seq12872

Kernel 3.2

Fixed Bugs and Malfunctions

A bug causing an infinite loop in hostname resolving has been corrected. To trigger this bug you would have to enter an bogus search method from a configuration file e.g .inetrc.

Bug pinpointed by Emil Holmström

Own Id: OTP-12133

The standard_error process now handles the getopts I/O protocol request correctly and stores its encoding in the same way as standard_io.

Also, io:put_chars(standard_error, [oops]) could previously crash the standard_error process. This is now corrected.

Own Id: OTP-12424

Improvements and New Features

Configuration parameters for the Kernel application that allows setting socket options for the distribution sockets have been added. See the application Kernel documentation; parameters 'inet_dist_listen_options' and 'inet_dist_connect_options'.

Own Id: OTP-12476 Aux Id: OTP-12476

Kernel 3.1

Fixed Bugs and Malfunctions

Make sure to install .hrl files when needed

Own Id: OTP-12197

Removed the undocumented application environment variable 'raw_files' from the kernel application. This variable was checked (by call to application:get_env/2) each time a raw file was to be opened in the file module.

Own Id: OTP-12276

A bug has been fixed when using the netns option to gen_udp, which accidentally only worked if it was the last option.

Own Id: OTP-12314

Improvements and New Features

Updated documentation for inet buffer size options.

Own Id: OTP-12296

Introduce new option 'raw' in file_info and link_info functions. This option allows the caller not to go through the file server for information about files guaranteed to be local.

Own Id: OTP-12325

Kernel 3.0.3

Fixed Bugs and Malfunctions

Accept inet:ip_address() in net_adm:names/1

Own Id: OTP-12154

Kernel 3.0.2

Fixed Bugs and Malfunctions

OTP-11850 fixed filelib:wildcard/1 to work with broken symlinks. This correction, however, introduced problems since symlinks were no longer followed for functions like filelib:ensure_dir/1, filelib:is_dir/1, filelib:file_size/1, etc. This is now corrected.

Own Id: OTP-12054 Aux Id: seq12660

Kernel 3.0.1

Fixed Bugs and Malfunctions

If the Config given to application_controller:change_application_data included other config files, it was only expanded for already existing (loaded) applications. If an upgrade added a new application which had config data in an included config file, the new application did not get correct config data.

This is now changed so config data will be expanded for all applications.

Own Id: OTP-11864

It was allowed to re-load pre-loaded modules such as erlang, but that could cause strange and unwanted things to happen, such as call apply/3 to loop. Pre-loaded modules are now sticky by default. (Thanks to Loïc Hoguin for reporting this bug.)

code:add_path("/ending/in/slash/") removes the trailing slash, adding /ending/in/slash to the code path. However, code:del_path("/ending/in/slash/") would fail to remove the path since it did not remove the trailing slash. This has been fixed.

Own Id: OTP-11913

Fix erts_debug:size/1 to handle Map sizes

Own Id: OTP-11923

The documentation for file:file_info/1 has been removed. The function itself was removed a long time ago.

Own Id: OTP-11982

Kernel 3.0

Fixed Bugs and Malfunctions

Fixed a deadlock possibility in terminate application

Own Id: OTP-11171

Fixed bug where sendfile would return the wrong error code for a remotely closed socket if the socket was in passive mode. (Thanks to Vincent Siliakus for reporting the bug.)

Own Id: OTP-11614

The new option persistent is added to application:set_env/4 and application:unset_env/3. An environment key set with the persistent option will not be overridden by the ones configured in the application resource file on load. This means persistent values will stick after the application is loaded and also on application reload. (Thanks to José Valim)

Own Id: OTP-11708

The spec for file:set_cwd/1 is modified to also accept binaries as arguments. This has always been allowed in the code, but it was not reflected in the spec since binaries are mostly used for raw file names. Raw file names are names that are not encoded according to file:native_name_encoding(), and these are not allowed in file:set_cwd/1. The spec is now, however, more allowing in order to avoid unnecessary dialyzer warnings. Raw file names will still fail in runtime with reason 'no_translation'. (Thanks to José Valim)

Own Id: OTP-11787

Improvements and New Features

heart:set_cmd/1 is updated to allow unicode code points > 255 in the given heart command

Own Id: OTP-10843

Dialyzer's unmatched_return warnings have been corrected.

Own Id: OTP-10908

Make erlang:open_port/2 spawn and spawn_executable handle unicode.

Own Id: OTP-11105

Erlang/OTP has been ported to the realtime operating system OSE. The port supports both smp and non-smp emulator. For details around the port and how to started see the User's Guide in the ose application.

Note that not all parts of Erlang/OTP has been ported.

Notable things that work are: non-smp and smp emulators, OSE signal interaction, crypto, asn1, run_erl/to_erl, tcp, epmd, distribution and most if not all non-os specific functionality of Erlang.

Notable things that does not work are: udp/sctp, os_mon, erl_interface, binding of schedulers.

Own Id: OTP-11334

Add the {active,N} socket option for TCP, UDP, and SCTP, where N is an integer in the range -32768..32767, to allow a caller to specify the number of data messages to be delivered to the controlling process. Once the socket's delivered message count either reaches 0 or is explicitly set to 0 with inet:setopts/2 or by including {active,0} as an option when the socket is created, the socket transitions to passive ({active, false}) mode and the socket's controlling process receives a message to inform it of the transition. TCP sockets receive {tcp_passive,Socket}, UDP sockets receive {udp_passive,Socket} and SCTP sockets receive {sctp_passive,Socket}.

The socket's delivered message counter defaults to 0, but it can be set using {active,N} via any gen_tcp, gen_udp, or gen_sctp function that takes socket options as arguments, or via inet:setopts/2. New N values are added to the socket's current counter value, and negative numbers can be used to reduce the counter value. Specifying a number that would cause the socket's counter value to go above 32767 causes an einval error. If a negative number is specified such that the counter value would become negative, the socket's counter value is set to 0 and the socket transitions to passive mode. If the counter value is already 0 and inet:setopts(Socket, [{active,0}]) is specified, the counter value remains at 0 but the appropriate passive mode transition message is generated for the socket.

Thanks to Steve Vinoski

Own Id: OTP-11368

A call to either the garbage_collect/1 BIF or the check_process_code/2 BIF may trigger garbage collection of another processes than the process calling the BIF. The previous implementations performed these kinds of garbage collections without considering the internal state of the process being garbage collected. In order to be able to more easily and more efficiently implement yielding native code, these types of garbage collections have been rewritten. A garbage collection like this is now triggered by an asynchronous request signal, the actual garbage collection is performed by the process being garbage collected itself, and finalized by a reply signal to the process issuing the request. Using this approach processes can disable garbage collection and yield without having to set up the heap in a state that can be garbage collected.

The garbage_collect/2, and check_process_code/3 BIFs have been introduced. Both taking an option list as last argument. Using these, one can issue asynchronous requests.

code:purge/1 and code:soft_purge/1 have been rewritten to utilize asynchronous check_process_code requests in order to parallelize work.

Characteristics impact: A call to the garbage_collect/1 BIF or the check_process_code/2 BIF will normally take longer time to complete while the system as a whole won't be as much negatively effected by the operation as before. A call to code:purge/1 and code:soft_purge/1 may complete faster or slower depending on the state of the system while the system as a whole won't be as much negatively effected by the operation as before.

Own Id: OTP-11388 Aux Id: OTP-11535, OTP-11648

Add sync option to file:open/2.

The sync option adds the POSIX O_SYNC flag to the open system call on platforms that support the flag or its equivalent, e.g., FILE_FLAG_WRITE_THROUGH on Windows. For platforms that don't support it, file:open/2 returns {error, enotsup} if the sync option is passed in. Thank to Steve Vinoski and Joseph Blomstedt

Own Id: OTP-11498

The contract of inet:ntoa/1 has been corrected.

Thanks to Max Treskin.

Own Id: OTP-11730

Kernel 2.16.4.1

Known Bugs and Problems

When using gen_tcp:connect and the fd option with port and/or ip, the port and ip options were ignored. This has been fixed so that if port and/or ip is specified together with fd a bind is requested for that fd. If port and/or ip is not specified bind will not be called.

Own Id: OTP-12061

Kernel 2.16.4

Fixed Bugs and Malfunctions

Fix the typespec for the inet:ifget/2 and inet:ifget/3 return value. Thanks to Ali Sabil.

Own Id: OTP-11377

Fix various typos in erts, kernel and ssh. Thanks to Martin Hässler.

Own Id: OTP-11414

Fix rpc multicall sample code. Thanks to Edwin Fine.

Own Id: OTP-11471

Under rare circumstances a process calling inet:close/1, gen_tcp:close/1, gen_udp:close/1, or gen_sctp:close/1 could hang in the call indefinitely.

Own Id: OTP-11491

Improvements and New Features

Add more SCTP errors as described in RFC 4960. Thanks to Artem Teslenko.

Own Id: OTP-11379

Add new BIF os:unsetenv/1 which deletes an environment variable. Thanks to Martin Hässler.

Own Id: OTP-11446

Kernel 2.16.3

Fixed Bugs and Malfunctions

Fix indentation of User switch command help in Erlang shell. Thanks to Sylvain Benner.

Own Id: OTP-11209

Improvements and New Features

The previous undocumented function ntoa/1 has been added to inet docs and exported in the inet module.

Own Id: OTP-10676 Aux Id: OTP-10314

Fix typo in abcast() function comment. Thanks to Johannes Weissl.

Own Id: OTP-11219

Add application:ensure_all_started/1-2. Thanks to Fred Hebert.

Own Id: OTP-11250

Make edlin understand a few important control keys. Thanks to Stefan Zegenhagen.

Own Id: OTP-11251

Cleanup of hipe_unified_loader, eliminating uses of is_subtype/2 in specs, change module-local void functions to return 'ok' instead of [] and made sure there are no dialyzer warnings with --Wunmatched_returns. Thanks to Kostis Sagonas.

Own Id: OTP-11301

Kernel 2.16.2

Fixed Bugs and Malfunctions

A bug in prim_inet has been corrected. If the port owner was killed at a bad time while closing the socket port the port could become orphaned hence causing port and socket leaking. Reported by Fred Herbert, Dmitry Belyaev and others.

Own Id: OTP-10497 Aux Id: OTP-10562

A few bugs regarding case sensitivity for hostname resolution while using e.g the internal lookup types 'file' and 'dns' has been corrected. When looking up hostnames ASCII letters a-z are to be regarded as the same as A-Z according to RFC 4343 "Domain Name System (DNS) Case Insensitivity Clarification", and this was not always the case.

Own Id: OTP-10689 Aux Id: seq12227

Improvements and New Features

Add application:ensure_started/1,2. It is equivavlent to application:start/1,2 except it returns ok for already started applications.

Own Id: OTP-10910

Optimize communication with file io server. Thanks to Anthony Ramine.

Own Id: OTP-11040

Erlang source files with non-ASCII characters are now encoded in UTF-8 (instead of latin1).

Own Id: OTP-11041 Aux Id: OTP-10907

Optimization of simultaneous inet_db operations on the same socket by using a lock free implementation.

Impact on the characteristics of the system: Improved performance.

Own Id: OTP-11074

The high_msgq_watermark and low_msgq_watermark inet socket options introduced in OTP-R16A could only be set on TCP sockets. These options are now generic and can be set on all types of sockets.

Own Id: OTP-11075 Aux Id: OTP-10336

Fix deep list argument error under Windows in os:cmd/1. Thanks to Aleksandr Vinokurov .

Own Id: OTP-11104

Kernel 2.16.1

Fixed Bugs and Malfunctions

A bug that could cause a crash with wrong reason has been corrected in the application_controller module.

Own Id: OTP-10754

Fix code:is_module_native/1 that sometimes in R16A returned false for hipe compiled modules containing BIFs such as lists.

Own Id: OTP-10870

Respect {exit_on_close,false} option on tcp socket in non-passive mode when receiving fails (due to an ill-formed packet for example) by only doing a half close and still allow sending on the socket. (Thanks to Anthony Molinaro and Steve Vinoski for reporting the problem)

Own Id: OTP-10879

Improvements and New Features

Slightly nicer error message when node start fails due to duplicate name. Thanks to Magnus Henoch.

Own Id: OTP-10797

Miscellaneous updates due to Unicode support.

Own Id: OTP-10820

Add a new function code:get_mode() can be used to detect how the code servers behaves. Thanks to Vlad Dumitrescu

Own Id: OTP-10823

Fix type of error Reason on gen_tcp:send/2. Thanks to Sean Cribbs.

Own Id: OTP-10839

file:list_dir_all/1 and file:read_link_all/1 that can handle raw file names have been added. See the User Guide for STDLIB for information about raw file names.

Own Id: OTP-10852

Kernel 2.16

Fixed Bugs and Malfunctions

It is no longer possible to have {Mod,Vsn} in the 'modules' list in a .app file.

This was earlier possible, although never documented in the .app file reference manual. It was however visible in the documentation of application:load/[1,2], where the same term as in a .app file can be used as the first argument.

The possibility has been removed since the Vsn part was never used.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-10417

The contract of erl_ddll:format_error/1 has been corrected. (Thanks to Joseph Wayne Norton.)

Own Id: OTP-10473

Change printout of application crash message on startup to formatted strings (Thanks to Serge Aleynikov)

Own Id: OTP-10620

The type ascii_string() in the base64 module has been corrected. The type file:file_info() has been cleaned up. The type file:fd() has been made opaque in the documentation.

Own Id: OTP-10624 Aux Id: kunagi-352 [263]

Improvements and New Features

Inet exported functionality

inet:parse_ipv4_address/1, inet:parse_ipv4strict_address/1, inet:parse_ipv6_address/1, inet:parse_ipv6strict_address/1, inet:parse_address/1 and inet:parse_strict_address is now exported from the inet module.

Own Id: OTP-8067 Aux Id: kunagi-274 [185]

A boolean socket option 'ipv6_v6only' for IPv6 sockets has been added. The default value of the option is OS dependent, so applications aiming to be portable should consider using {ipv6_v6only,true} when creating an inet6 listening/destination socket, and if necessary also create an inet socket on the same port for IPv4 traffic. See the documentation.

Own Id: OTP-8928 Aux Id: kunagi-193 [104]

Support for Unicode has been implemented.

Own Id: OTP-10302

The documentation for global:register_name/3 has been updated to mention that the use of {Module,Function} as the method argument (resolve function) is deprecated.

Own Id: OTP-10419

Fixed bug where sendfile on oracle solaris would return an error when a partial send was done.

Own Id: OTP-10549

The error_handler module will now call '$handle_undefined_function'/2 if an attempt is made to call a non-existing function in a module that exists. See the documentation for error_handler module for details.

Own Id: OTP-10617 Aux Id: kunagi-340 [251]

Where necessary a comment stating encoding has been added to Erlang files. The comment is meant to be removed in Erlang/OTP R17B when UTF-8 becomes the default encoding.

Own Id: OTP-10630

Do not return wrong terms unnecessarily. (Thanks to Kostis Sagonas.)

Own Id: OTP-10662

Some examples overflowing the width of PDF pages have been corrected.

Own Id: OTP-10665

Add file:allocate/3 operation

This operation allows pre-allocation of space for files. It succeeds only on systems that support such operation. (Thanks to Filipe David Manana)

Own Id: OTP-10680

Add application:get_key/3. The new function provides a default value for a configuration parameter. Thanks to Serge Aleynikov.

Own Id: OTP-10694

Add search to Erlang shell's history. Thanks to Fred Herbert.

Own Id: OTP-10739

Kernel 2.15.3

Fixed Bugs and Malfunctions

Ensure 'erl_crash.dump' when asked for it. This will change erl_crash.dump behaviour.

* Not setting ERL_CRASH_DUMP_SECONDS will now terminate beam immediately on a crash without writing a crash dump file.

* Setting ERL_CRASH_DUMP_SECONDS to 0 will also terminate beam immediately on a crash without writing a crash dump file, i.e. same as not setting ERL_CRASH_DUMP_SECONDS environment variable.

* Setting ERL_CRASH_DUMP_SECONDS to a negative value will let the beam wait indefinitely on the crash dump file being written.

* Setting ERL_CRASH_DUMP_SECONDS to a positive value will let the beam wait that many seconds on the crash dump file being written.

A positive value will set an alarm/timeout for restart both in beam and in heart if heart is running.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-10422 Aux Id: kunagi-250 [161]

Kernel 2.15.2

Fixed Bugs and Malfunctions

Fixed issue where using controlling_process/2 with self() as the second argument caused the port to leak if self() crashes. (Thanks to Ricardo Catalinas Jiménez)

Own Id: OTP-10094

When sending large files using the file:sendfile fallback file:sendfile would crash. This is now fixed.

Own Id: OTP-10098

Fix rpc:call/5 for local calls with a finite Timeout (Thanks to Tomer Chachamu)

Own Id: OTP-10149

fix escript/primary archive reloading

If the mtime of an escript/primary archive file changes after being added to the code path, correctly reload the archive and update the cache. (Thanks to Tuncer Ayaz)

Own Id: OTP-10151

Support added for home directories named with non-ASCII characters (codepoints above 127) on a system running in Unicode file mode (e.g. on MacOSX or Linux with startup arguments +fnu or +fna with the right LOCALE). Also environment variables with Unicode content are supported in applicable environments.

Own Id: OTP-10160

Allow mixed IPv4 and IPv6 addresses to sctp_bindx

Also allow mixed address families to bind, since the first address on a multihomed sctp socket must be bound with bind, while the rest are to be bound using sctp_bindx. At least Linux supports adding address of mixing families. Make inet_set_faddress function available also when HAVE_SCTP is not defined, since we use it to find an address for bind to be able to mix ipv4 and ipv6 addresses. Thanks to Tomas Abrahamsson

Own Id: OTP-10217

Improvements and New Features

Document inet options: high_watermark, priority, linger and a some other options that previously was undocumented.

Own Id: OTP-10053

Remove bit8 option support from inet

Own Id: OTP-10056

The type of the disk log header has been corrected. (Thanks to Niclas Eklund.)

Own Id: OTP-10131

Kernel 2.15.1

Fixed Bugs and Malfunctions

Driver output has been corrected so output of large binaries (> 4 GiB) now does not silently fail or crash the emulator, but either outputs the binary or fails the call. This means that writing a binary > 4 Gib to file now works but on e.g 64-bit Windows (that has scatter/gather I/O buffer segment lengths of 32 bits) fails. The behaviour may change in the future to always write the binary, in parts if necessary.

Own Id: OTP-9820 Aux Id: OTP-9795

erts: minor fix for unnecessary condition erts: change SENDFILE_CHUNK_SIZE from signed to unsigned (Thanks to jovi zhang)

Own Id: OTP-9872

Two contracts in gen_sctp have been corrected.

Own Id: OTP-9874

If a process calls a module with an running on_load handler, the process is supposed to be suspended. But if the module with the on_load handler was loading used code:load_binary/3, the call would instead fail with an undef exception.

Own Id: OTP-9875

File name and error reason is now returned if creation of a cookie fails. (Thanks to Magnus Henoch)

Own Id: OTP-9954

Fix port leak in zlib when passing invalid data to compress,uncompress,zip,unzip,gzip,gunzip.

Own Id: OTP-9981

Various typographical errors corrected in documentation for the global, error_logger, etop, lists, ets and supervisor modules and in the c_portdriver and kernel_app documentation. (Thanks to Ricardo Catalinas Jiménez)

Own Id: OTP-9987

Fix returned error from gen_tcp:accept/1,2 when running out of ports.

The {error, enfile} return value is badly misleading and confusing for this case, since the Posix ENFILE errno value has a well-defined meaning that has nothing to do with Erlang ports. The fix changes the return value to {error, system_limit}, which is consistent with e.g. various file(3) functions. inet:format_error/1 has also been updated to support system_limit in the same manner as file:format_error/1. (Thanks to Per Hedeland)

Own Id: OTP-9990

erts_debug:size/1 has been corrected to take sharing in the environment of funs into account. For funs it used to always give the same result as erts_debug:flat_size/1.

Own Id: OTP-9991

In some cases when the process doing file:sendfile crashes while sending the file the efile_drv code would not clean up after itself correctly. This has now been fixed.

Own Id: OTP-9993

On BSD based platforms file:sendfile would sometime go into an infinite loop when sending big files. This has now been fixed.

Own Id: OTP-9994

While disk_log eagerly collects logged terms for better performance, collecting too much data may choke the system and cause huge binaries to be written.

The problem was addressed in OTP-9764, but the situation was not improved in all cases.

(Thanks to Richard Carlsson.)

Own Id: OTP-9999 Aux Id: OTP-9764

The documentation of .app files incorrectly said that the default value for the mod parameter is undefined. This is now corrected to [].

Own Id: OTP-10002

Kernel 2.15

Fixed Bugs and Malfunctions

Calls to global:whereis_name/1 have been substituted for calls to global:safe_whereis_name/1 since the latter is not safe at all.

The reason for not doing this earlier is that setting a global lock masked out a bug concerning the restart of supervised children. The bug has now been fixed by a modification of global:whereis_name/1. (Thanks to Ulf Wiger for code contribution.)

A minor race conditions in gen_fsm:start* has been fixed: if one of these functions returned {error, Reason} or ignore, the name could still be registered (either locally or in global. (This is the same modification as was done for gen_server in OTP-7669.)

The undocumented function global:safe_whereis_name/1 has been removed.

Own Id: OTP-9212 Aux Id: seq7117, OTP-4174

Honor option packet_size for http packet parsing by both TCP socket and erlang:decode_packet. This gives the ability to accept HTTP headers larger than the default setting, but also avoid DoS attacks by accepting lines only up to whatever length you wish to allow. For consistency, packet type line also honor option packet_size. (Thanks to Steve Vinoski)

Own Id: OTP-9389

disk_log:reopen/2,3 and disk_log:breopen/3 could return the error reason from file:rename/2 rather than the reason {file_error, Filename, Reason}. This bug has been fixed.

The message {disk_log, Node, {error, disk_log_stopped}} which according the documentation is sent upon failure to truncate or reopen a disk log was sometimes turned into a reply. This bug has been fixed.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-9508

Environment variable 'shutdown_timeout' is added to kernel application. Earlier, application_controller would hang forever if an application top supervisor did not terminate upon a shutdown request. If this new environment variable is set to a positive integer T, then application controller will now give up after T milliseconds and instead brutally kill the application. For backwards compatibility, the default value for shutdown_timeout is 'infinity'.

Own Id: OTP-9540

Add '-callback' attributes in stdlib's behaviours

Replace the behaviour_info(callbacks) export in stdlib's behaviours with -callback' attributes for all the callbacks. Update the documentation with information on the callback attribute Automatically generate 'behaviour_info' function from '-callback' attributes

'behaviour_info(callbacks)' is a special function that is defined in a module which describes a behaviour and returns a list of its callbacks.

This function is now automatically generated using the '-callback' specs. An error is returned by lint if user defines both '-callback' attributes and the behaviour_info/1 function. If no type info is needed for a callback use a generic spec for it. Add '-callback' attribute to language syntax

Behaviours may define specs for their callbacks using the familiar spec syntax, replacing the '-spec' keyword with '-callback'. Simple lint checks are performed to ensure that no callbacks are defined twice and all types referred are declared.

These attributes can be then used by tools to provide documentation to the behaviour or find discrepancies in the callback definitions in the callback module.

Add callback specs into 'application' module in kernel Add callback specs to tftp module following internet documentation Add callback specs to inets_service module following possibly deprecated comments

Own Id: OTP-9621

make tab completion work in remote shells (Thanks to Mats Cronqvist)

Own Id: OTP-9673

Add missing parenthesis in heart doc.

Add missing spaces in the Reference Manual distributed section.

In the HTML version of the doc those spaces are necessary to separate those words.

Own Id: OTP-9693

Fixes net_kernel:get_net_ticktime() doc

Adds missing description when `ignored' is returned. (Thanks to Ricardo Catalinas Jiménez )

Own Id: OTP-9713

While disk_log eagerly collects logged terms for better performance, collecting too much data may choke the system and cause huge binaries to be written. In order to remedy the situation a (small) limit on the amount of data that is collected before writing to disk has been introduced.

Own Id: OTP-9764

Correct callback spec in application module

Refine warning about callback specs with extra ranges

Cleanup autoimport compiler directives

Fix Dialyzer's warnings in typer

Fix Dialyzer's warning for its own code

Fix bug in Dialyzer's behaviours analysis

Fix crash in Dialyzer

Variable substitution was not generalizing any unknown variables.

Own Id: OTP-9776

Fix a crash when file:change_time/2,3 are called with invalid dates

Calling file:change_time/2,3 with an invalid date tuple (e.g file:change_time("file.txt", {undefined, undefined})) will cause file_server_2 to crash. error_logger will shutdown and the whole VM will stop. Change behavior to validate given dates on system boundaries. (i.e before issuing a server call).(Thanks to Ahmed Omar)

Own Id: OTP-9785

Improvements and New Features

An option list argument can now be passed to file:read_file_info/2, file:read_link_info/2 and file:write_file_info/3 and set time type information in the call. Valid options are {time, local}, {time, universal} and {time, posix}. In the case of posix time no conversions are made which makes the operation a bit faster.

Own Id: OTP-7687

file:list_dir/1,2 will now fill an buffer entire with filenames from the efile driver before sending it to an erlang process. This will speed up this file operation in most cases.

Own Id: OTP-9023

gen_sctp:open/0-2 may now return {error,eprotonosupport} if SCTP is not supported

gen_sctp:peeloff/1 has been implemented and creates a one-to-one socket which also are supported now

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-9239

Sendfile has been added to the file module's API. sendfile/2 is used to read data from a file and send it to a tcp socket using a zero copying mechanism if available on that OS.

Thanks to Tuncer Ayaz and Steve Vinovski for original implementation

Own Id: OTP-9240

Tuple funs (a two-element tuple with a module name and a function) are now officially deprecated and will be removed in R16. Use 'fun M:F/A' instead. To make you aware that your system uses tuple funs, the very first time a tuple fun is applied, a warning will be sent to the error logger.

Own Id: OTP-9649

Kernel 2.14.5

Fixed Bugs and Malfunctions

Fix type of Packet arg of gen_tcp:send/2 and gen_udp:send/4

The type is marked as a binary() or a string() but in practice it can be an iodata(). The test suite was updated to confirm the gen_tcp/2 and gen_udp:send/4 functions accept iodata() (iolists) packets. (Thanks to Filipe David Manana)

Own Id: OTP-9514

XML files have been corrected.

Own Id: OTP-9550 Aux Id: OTP-9541

Improvements and New Features

The types and specifications of the inet modules have been improved.

Own Id: OTP-9260

Types and specifications have been added.

Own Id: OTP-9356

Contracts in STDLIB and Kernel have been improved and type errors have been corrected.

Own Id: OTP-9485

Update documentation and specifications of some of the zlib functions.

Own Id: OTP-9506

Kernel 2.14.4

Fixed Bugs and Malfunctions

The send_timeout option in gen_tcp did not work properly in active mode or with {active,once} options. This is now corrected.

Own Id: OTP-9145

Fixed various typos across the documentation (Thanks to Tuncer Ayaz)

Own Id: OTP-9154

Fix typo in doc of rpc:pmap/3 (Thanks to Ricardo Catalinas Jiménez)

Own Id: OTP-9168

A bug in inet_res, the specialized DNS resolver, has been corrected. A late answer with unfortunate timing could cause a runtime exception. Some code cleanup and improvements also tagged along. Thanks to Evegeniy Khramtsov for a pinpointing bug report and bug fix testing.

Own Id: OTP-9221 Aux Id: OTP-8712

Improvements and New Features

Types and specifications have been added.

Own Id: OTP-9268

Erlang types and specifications are used for documentation.

Own Id: OTP-9272

Two opaque types that could cause warnings when running Dialyzer have been modified.

Own Id: OTP-9337

Kernel 2.14.3

Fixed Bugs and Malfunctions

os:find_executable/{1,2} will no longer return the path of a directory that happens to be in the PATH.

Own Id: OTP-8983 Aux Id: seq11749

Fix -spec for file:write_file/3

Change type for second parameter from binary() to iodata(), since the function explicitly takes steps to accept lists as well as binaries. (thanks to Magnus Henoch).

Own Id: OTP-9067

Sanitize the specs of the code module

After the addition of unicode_binary() to the file:filename() type, dialyzer started complaining about erroneous or incomplete specs in some functions of the 'code' module. The culprit was hard-coded information in erl_bif_types for functions of this module, which were not updated. Since these functions have proper specs these days and code duplication (pun intended) is never a good idea, their type information was removed from erl_bif_types.

While doing this, some erroneous comments were fixed in the code module and also made sure that the code now runs without dialyzer warnings even when the -Wunmatched_returns option is used.

Some cleanups were applied to erl_bif_types too.

Own Id: OTP-9100

- Add spec for function that does not return - Strengthen spec - Introduce types to avoid duplication in specs - Add specs for functions that do not return - Add specs for behaviour callbacks - Simplify two specs

Own Id: OTP-9127

Kernel 2.14.2

Improvements and New Features

The Erlang VM now supports Unicode filenames. The feature is turned on by default on systems where Unicode filenames are mandatory (Windows and MacOSX), but can be enabled on other systems with the '+fnu' emulator option. Enabling the Unicode filename feature on systems where it is not default is however considered experimental and not to be used for production. Together with the Unicode file name support, the concept of "raw filenames" is introduced, which means filenames provided without implicit unicode encoding translation. Raw filenames are provided as binaries, not lists. For further information, see stdlib users guide and the chapter about using Unicode in Erlang. Also see the file module manual page.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-8887

There is now a new function inet:getifaddrs/0 modeled after C library function getifaddrs() on BSD and LInux that reports existing interfaces and their addresses on the host. This replaces the undocumented and unsupported inet:getiflist/0 and inet:ifget/2.

Own Id: OTP-8926

Kernel 2.14.1.1

Fixed Bugs and Malfunctions

In embedded mode, on_load handlers that called code:priv_dir/1 or other functions in code would hang the system. Since the crypto application now contains an on_loader handler that calls code:priv_dir/1, including the crypto application in the boot file would prevent the system from starting.

Also extended the -init_debug option to print information about on_load handlers being run to facilitate debugging.

Own Id: OTP-8902 Aux Id: seq11703

Kernel 2.14.1

Fixed Bugs and Malfunctions

Fixed: inet:setopts(S, [{linger,{true,2}}]) returned {error,einval} for SCTP sockets. The inet_drv had a bug when checking the option size.

Own Id: OTP-8726 Aux Id: seq11617

gen_udp:connect/3 was broken for SCTP enabled builds. It did not detect remote end errors as it should.

Own Id: OTP-8729

reference() has been substituted for ref() in the documentation.

Own Id: OTP-8733

A bug introduced in kernel-2.13.5.3 has been fixed. If running net_kernel:set_net_ticktime/1 twice within the TransitionPerod the second call caused the net_kernel process to crash with a badmatch.

Own Id: OTP-8787 Aux Id: seq11657, OTP-8643

inet:getsockopt for SCTP sctp_default_send_param had a bug to not initialize required feilds causing random answers. It is now corrected.

Own Id: OTP-8795 Aux Id: seq11655

For a socket in the HTTP packet mode, the return value from gen_tcp:recv/2,3 if there is an error in the header will be {ok,{http_error,String}} instead of {error,{http_error,String}} to be consistent with ssl:recv/2,3.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-8831

Improvements and New Features

Even when configuring erlang with --enable-native-libs, the native code for modules loaded very early (such as lists) would not get loaded. This has been corrected. (Thanks to Paul Guyot.)

Own Id: OTP-8750

The undocumented function inet:ifget/2 has been improved to return interface hardware address (MAC) on platforms supporting getaddrinfo() (such as BSD unixes). Note it still does not work on all platforms for example not Windows nor Solaris, so the function is still undocumented.

Buffer overflow and field init bugs for inet:ifget/2 and inet:getservbyname/2 has also been fixed.

Thanks to Michael Santos.

Own Id: OTP-8816

As a usability improvement the 'inet6' option to functions gen_tcp:listen/2, gen_tcp:connect/3-4, gen_udp:open/2 and gen_sctp:open/1-2 is now implicit if the address argument or the 'ip' option contain an IPv6 address (8-tuple).

Own Id: OTP-8822

Kernel 2.14

Fixed Bugs and Malfunctions

os:find_executable can now be fed with the complete name of the executable on Windows and still find it. I.e os:find_executable("werl.exe") will work as os:find_executable("werl").

Own Id: OTP-3626

The shell's line editing has been improved to more resemble the behaviour of readline and other shells. (Thanks to Dave Peticolas)

Own Id: OTP-8635

Under certain circumstances the net kernel could hang. (Thanks to Scott Lystig Fritchie.)

Own Id: OTP-8643 Aux Id: seq11584

The kernel DNS resolver was leaking one or two ports if the DNS reply could not be parsed or if the resolver(s) caused noconnection type errors. Bug now fixed. A DNS specification borderline truncated reply triggering the port leakage bug has also been fixed.

Own Id: OTP-8652

Improvements and New Features

As of this version, the global name server no longer supports nodes running Erlang/OTP R11B.

Own Id: OTP-8527

The file module's functions write,read and read_line now handles named io_servers like 'standard_io' and 'standard_error' correctly.

Own Id: OTP-8611

The functions file:advise/4 and file:datasync/1 have been added. (Thanks to Filipe David Manana.)

Own Id: OTP-8637

When exchanging groups between nodes pg2 did not remove duplicated members. This bug was introduced in R13B03 (kernel-2.13.4).

Own Id: OTP-8653

There is a new option 'exclusive' to file:open/2 that uses the OS O_EXCL flag where supported to open the file in exclusive mode.

Own Id: OTP-8670

Kernel 2.13.5.3

Fixed Bugs and Malfunctions

A bug introduced in Kernel 2.13.5.2 has been fixed.

Own Id: OTP-8686 Aux Id: OTP-8643

Kernel 2.13.5.2

Fixed Bugs and Malfunctions

Under certain circumstances the net kernel could hang. (Thanks to Scott Lystig Fritchie.)

Own Id: OTP-8643 Aux Id: seq11584

Kernel 2.13.5.1

Fixed Bugs and Malfunctions

A race condition in os:cmd/1 could cause the caller to get stuck in os:cmd/1 forever.

Own Id: OTP-8502

Kernel 2.13.5

Fixed Bugs and Malfunctions

A race bug affecting pg2:get_local_members/1 has been fixed. The bug was introduced in R13B03.

Own Id: OTP-8358

The loading of native code was not properly atomic in the SMP emulator, which could cause crashes. Also a per-MFA information table for the native code has now been protected with a lock since it turns that it could be accessed concurrently in the SMP emulator. (Thanks to Mikael Pettersson.)

Own Id: OTP-8397

user.erl (used in oldshell) is updated to handle unicode in prompt strings (io:get_line/{1,2}). io_lib is also updated to format prompts with the 't' modifier (i.e. ~ts instead of ~s).

Own Id: OTP-8418 Aux Id: OTP-8393

The resolver routines failed to look up the own node name as hostname, if the OS native resolver was erroneously configured, bug reported by Yogish Baliga, now fixed.

The resolver routines now tries to parse the hostname as an IP string as most OS resolvers do, unless the native resolver is used.

The DNS resolver inet_res and file resolver inet_hosts now do not read OS configuration files until they are needed. Since the native resolver is default, in most cases they are never needed.

The DNS resolver's automatic updating of OS configuration file data (/etc/resolv.conf) now uses the 'domain' keyword as default search domain if there is no 'search' keyword.

Own Id: OTP-8426 Aux Id: OTP-8381

Improvements and New Features

The expected return value for an on_load function has been changed. (See the section about code loading in the Reference manual.)

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-8339

Explicit top directories in archive files are now optional.

For example, if an archive (app-vsn.ez) just contains an app-vsn/ebin/mod.beam file, the file info for the app-vsn and app-vsn/ebin directories are faked using the file info from the archive file as origin. The virtual directories can also be listed. For short, the top directories are virtual if they does not exist.

Own Id: OTP-8387

code:clash/0 now looks inside archives (.ez files). (Thanks to Tuncer Ayaz.)

Own Id: OTP-8413

There are new gen_sctp:connect_init/* functions that initiate an SCTP connection without blocking for the result. The result is delivered asynchronously as an sctp_assoc_change event. (Thanks to Simon Cornish.)

Own Id: OTP-8414

Kernel 2.13.4

Fixed Bugs and Malfunctions

A link in m:pg2 has been fixed. (Thanks to Christophe Romain.)

Own Id: OTP-8198

A ticker process could potentially be blocked indefinitely trying to send a tick to a node not responding. If this happened, the connection would not be brought down as it should.

Own Id: OTP-8218

A bug in pg2 when members who died did not leave process groups has been fixed. (Thanks to Matthew Dempsky.)

Own Id: OTP-8259

Improvements and New Features

The documentation is now built with open source tools (xsltproc and fop) that exists on most platforms. One visible change is that the frames are removed.

Own Id: OTP-8201

The top directory in archive files does not need to have a -vsn suffix anymore. For example if the archive file has the name like mnesia-4.4.7.ez the top directory in the archive can either be named mnesia or mnesia-4.4.7. If the archive file has a name like mnesia.ez the top directory in the archive must be named mnesia as earlier.

Own Id: OTP-8266

The -on_load() directive can be used to run a function when a module is loaded. It is documented in the section about code loading in the Reference Manual.

Own Id: OTP-8295

Kernel 2.13.3

Improvements and New Features

The DNS resolver client inet_res has been rewritten, documented and released. See inet_res(3) and Erts User's Guide: Inet configuration.

It can formally not be incompatible with respect to earlier versions since there was no earlier official version. However it was used before and some details have changed.

Configuration now initializes from /etc/resolv.conf and /etc/hosts on all unix platforms regardless of which distribution mode the node is started in. The directory (/etc) these files are supposed to reside in can be changed via an environment variable. These configuration file locations can also be changed in the inet configuration. The files are monitored for change and re-read, which makes a few resolver configuration variables out of application control. The /etc/hosts entries have now their own cache table that is shadowed (with lookup method 'file' is used) by the application configured host entries. This problem (that inet_res configuration only worked for distribution mode long names) was among other reported by Matthew O'Gorman many moons ago.

The lookup methods are still 'native' only per default. Resolver configuration is done on all Unix platforms just to get a usable configuration for direct calls to inet_res.

The functions inet_res:nslookup/3..5 and inet_res:nnslookup/4..4 are no longer recommended to use, instead use inet_res:lookup/3..5 and inet_res:resolve/3..5 which provide clearer argument types and the possibility to override options in the call.

Users of previous unsupported versions of inet_res have included internal header files to get to the internal record definitions in order to examine DNS replies. This is still unsupported and there are access functions in inet_dns to use instead. These are documented in inet_res(3).

Bug fix: a compression reference loop would make DNS message decoding loop forever. Problem reported by Florian Weimer.

Bug fix and patch suggestion by Sergei Golovan: configuring IPv6 nameservers did not work. His patch (as he warned) created many UDP sockets; one per nameserver. This has been fixed in the released version.

Improvement: inet_res is now EDNS0 capable. The current implementation is simple and does not probe and cache EDNS info for nameservers, which a fully capable implementation probably should do. EDNS has to be enabled via resolver configuration, and if a nameserver replies that it does not support EDNS, inet_res falls back to a regular DNS query.

Improvement: now inet_res automatically falls back to TCP if it gets a truncated answer from a nameserver.

Warning: some of the ancient and exotic record types handled by inet_res and inet_dns are not supported by current versions of BIND, so they could not be tested after the rewrite, with reasonable effort, e.g MD, MF, NULL, and SPF. The risk for bugs in these particular records is still low since their code is mostly shared with other tested record types.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-7955 Aux Id: OTP-7107 OTP-6852

A TCP socket with option {packet,4} could crash the emulator if it received a packet header with a very large size value (>2Gb). The same bug caused erlang:decode_packet/3 to return faulty values. (Thanks to Georgos Seganos.)

Own Id: OTP-8102

The file module has now a read_line/1 function similar to the io:get_line/2, but with byte oriented semantics. The function file:read_line/1 works for raw files as well, but for good performance it is recommended to use it together with the 'read_ahead' option for raw file access.

Own Id: OTP-8108

Kernel 2.13.2

Fixed Bugs and Malfunctions

A bug when doing io:get_line (among other calls) from a file opened with encoding other than latin1, causing false unicode errors to occur, is now corrected.

Own Id: OTP-7974

Improvements and New Features

Added functionality to get higher resolution timestamp from system. The erlang:now function returns a timestamp that's not always consistent with the actual operating system time (due to resilience against large time changes in the operating system). The function os:timestamp/0 is added to get a similar timestamp as the one being returned by erlang:now, but untouched by Erlangs time correcting and smoothing algorithms. The timestamp returned by os:timestamp is always consistent with the operating systems view of time, like the calendar functions for getting wall clock time, but with higher resolution. Example of usage can be found in the os manual page.

Own Id: OTP-7971

Kernel 2.13.1

Fixed Bugs and Malfunctions

Many concurrent calls to os:cmd/1 will only block one scheduler thread at a time, making an smp emulator more responsive if the OS is slow forking processes.

Own Id: OTP-7890 Aux Id: seq11219

Fixed hanging early RPC that did IO operation during node start.

Own Id: OTP-7903 Aux Id: seq11224

The error behavior of gen_tcp and gen_udp has been corrected. gen_tcp:connect/3,4 and gen_udp:send/4 now returns {error,eafnosupport} for conflicting destination address versus socket address family. Other corner cases for IP address string host names combined with not using the native (OS) resolver (which is not default) has also been changed to return {error,nxdomain} instead of {error,einval}. Those changes just may surprise old existing code. gen_tcp:listen/2 and gen_udp:open/2 now fails for conflicting local address versus socket address family instead of trying to use an erroneous address. Problem reported by Per Hedeland.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-7929

Improvements and New Features

Several glitches and performance issues in the Unicode and I/O-system implementation of R13A have been corrected.

Own Id: OTP-7896 Aux Id: OTP-7648 OTP-7887

The unsupported DNS resolver client inet_res has now been improved to handle NAPTR queries.

Own Id: OTP-7925 Aux Id: seq11231

Kernel 2.13

Fixed Bugs and Malfunctions

The old Erlang DNS resolver inet_res has been corrected to handle TXT records with more than one character string. Patch courtesy of Geoff Cant.

Own Id: OTP-7588

When chunk reading a disk log opened in read_only mode, bad terms could crash the disk log process.

Own Id: OTP-7641 Aux Id: seq11090

gen_tcp:send() did sometimes (only observed on Solaris) return {error,enotconn} instead of the expected {error,closed} as the peer socket had been explicitly closed.

Own Id: OTP-7647

The gen_sctp option sctp_peer_addr_params, #sctp_paddrparams{address={IP,Port} was erroneously decoded in the inet driver. This bug has now been corrected.

Own Id: OTP-7755

Improvements and New Features

Erlang programs can now access STDERR on platforms where such a file descriptor is available by using the io_server 'standard_error', i.e. io:format(standard_error,"~s~n",[ErrorMessage]),

Own Id: OTP-6688

The format of the string returned by erlang:system_info(system_version) (as well as the first message when Erlang is started) has changed. The string now contains the both the OTP version number as well as the erts version number.

Own Id: OTP-7649

As of this version, the global name server no longer supports nodes running Erlang/OTP R10B.

Own Id: OTP-7661

A {nodedown, Node} message passed by the net_kernel:monitor_nodes/X functionality is now guaranteed to be sent after Node has been removed from the result returned by erlang:nodes/Y.

Own Id: OTP-7725

The deprecated functions erlang:fault/1, erlang:fault/2, and file:rawopen/2 have been removed.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-7812

Nodes belonging to different independent clusters can now co-exist on the same host with the help of a new environment variable setting ERL_EPMD_PORT.

Own Id: OTP-7826

The copyright notices have been updated.

Own Id: OTP-7851

Kernel 2.12.5.1

Fixed Bugs and Malfunctions

When chunk reading a disk log opened in read_only mode, bad terms could crash the disk log process.

Own Id: OTP-7641 Aux Id: seq11090

Calling gen_tcp:send() from several processes on socket with option send_timeout could lead to much longer timeout than specified. The solution is a new socket option {send_timeout_close,true} that will do automatic close on timeout. Subsequent calls to send will then immediately fail due to the closed connection.

Own Id: OTP-7731 Aux Id: seq11161

Kernel 2.12.5

Fixed Bugs and Malfunctions

The documentation of rpc:pmap/3 has been corrected. (Thanks to Kirill Zaborski.)

Own Id: OTP-7537

The listen socket used for the distributed Erlang protocol now uses the socket option 'reuseaddr', which is useful when you force the listen port number using kernel options 'inet_dist_listen_min' and 'inet_dist_listen_max' and restarts a node with open connections.

Own Id: OTP-7563

Fixed memory leak of unclosed TCP-ports. A gen_tcp:send() followed by a failing gen_tcp:recv() could in some cases cause the port to linger after being closed.

Own Id: OTP-7615

Improvements and New Features

Processes spawned using proc_lib (including gen_server and other library modules that use proc_lib) no longer keep the entire argument list for the initial call, but only the arity.

Also, if proc_lib:spawn/1 is used to spawn a fun, the actual fun is not kept, but only module, function name, and arity of the function that implements the fun.

The reason for the change is that keeping the initial fun (or a fun in an argument list), would prevent upgrading the code for the module. A secondary reason is that keeping the fun and function arguments could waste a significant amount of memory.

The drawback with the change is that the crash reports will provide less precise information about the initial call (only Module:Function/Arity instead of Module:Function(Arguments)). The function proc_lib:initial_call/1 still returns a list, but each argument has been replaced with a dummy atom.

Own Id: OTP-7531 Aux Id: seq11036

io:get_line/1 when reading from standard input is now substantially faster. There are also some minor performance improvements in io:get_line/1 when reading from any file opened in binary mode. (Thanks to Fredrik Svahn.)

Own Id: OTP-7542

There is now experimental support for loading of code from archive files. See the documentation of code, init, erl_prim_loaderand escript for more info.

The error handling of escripts has been improved.

An escript may now set explicit arguments to the emulator, such as -smp enabled.

An escript may now contain a precompiled beam file.

An escript may now contain an archive file containing one or more applications (experimental).

The internal module code_aux has been removed.

Own Id: OTP-7548 Aux Id: otp-6622

code:is_sticky/1 is now documented. (Thanks to Vlad Dumitrescu.)

Own Id: OTP-7561

In the job control mode, the "s" and "r" commands now take an optional argument to specify which shell to start. (Thanks to Robert Virding.)

Own Id: OTP-7617

net_adm:world/0,1 could crash if called in an emulator that has not been started with either the -sname or -name option; now it will return an empty list. (Thanks to Edwin Fine.)

Own Id: OTP-7618

Kernel 2.12.4

Fixed Bugs and Malfunctions

Large files are now handled on Windows, where the filesystem supports it.

Own Id: OTP-7410

Improvements and New Features

New BIF erlang:decode_packet/3 that extracts a protocol packet from a binary. Similar to the socket option {packet, Type}. Also documented the socket packet type http and made it official. NOTE: The tuple format for http packets sent from an active socket has been changed in an incompatible way.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-7404

Setting the {active,once} for a socket (using inets:setopts/2) is now specially optimized (because the {active,once} option is typically used much more frequently than other options).

Own Id: OTP-7520

Kernel 2.12.3

Fixed Bugs and Malfunctions

SCTP_ADDR_CONFIRMED events are now handled by gen_sctp.

Own Id: OTP-7276

When leaving a process group with pg2:leave/2 the process was falsely assumed to be a member of the group. This bug has been fixed.

Own Id: OTP-7277

In the Erlang shell, using up and down arrow keys, the wrong previous command could sometimes be retrieved.

Own Id: OTP-7278

The documentation for erlang:trace/3 has been corrected.

Own Id: OTP-7279 Aux Id: seq10927

In the SMP emulator, there was small risk that code:purge(Mod) would kill a process that was running code in Mod and unload the module Mod before the process had terminated. code:purge(Mod) now waits for confirmation (using erlang:monitor/2) that the process has been killed before proceeding.

Own Id: OTP-7282

zlib:inflate failed when the size of the inflated data was an exact multiple of the internal buffer size (4000 bytes by default).

Own Id: OTP-7359

Improvements and New Features

Additional library directories can now be specified in the environment variable ERL_LIBS. See the manual page for the code module. (Thanks to Serge Aleynikov.)

Own Id: OTP-6940

crypto and zlib drivers improved to allow concurrent smp access.

Own Id: OTP-7262

There is a new function init:stop/1 which can be used to shutdown the system cleanly AND generate a non-zero exit status or crash dump. (Thanks to Magnus Froberg.)

Own Id: OTP-7308

The hide option for open_port/2 is now documented. (Thanks to Richard Carlsson.)

Own Id: OTP-7358

Kernel 2.12.2.1

Improvements and New Features

os:cmd/1 on unix platforms now use /bin/sh as shell instead of looking for sh in the PATH environment.

Own Id: OTP-7283

Kernel 2.12.2

Fixed Bugs and Malfunctions

A bug caused by a race condition involving disk_log and pg2 has been fixed.

Own Id: OTP-7209 Aux Id: seq10890

The beta testing module gen_sctp now supports active mode as stated in the documentation. Active mode is still rather untested, and there are some issues about what should be the right semantics for gen_sctp:connect/5. In particular: should it be blocking or non-blocking or choosable. There is a high probability it will change semantics in a (near) future patch.

Try it, give comments and send in bug reports!

Own Id: OTP-7225

Improvements and New Features

erlang:system_info/1 now accepts the logical_processors, and debug_compiled arguments. For more info see the, erlang documentation.

The scale factor returned by test_server:timetrap_scale_factor/0 is now also effected if the emulator uses a larger amount of scheduler threads than the amount of logical processors on the system.

Own Id: OTP-7175

Updated the documentation for erlang:function_exported/3 and io:format/2 functions to no longer state that those functions are kept mainly for backwards compatibility.

Own Id: OTP-7186

A process executing the processes/0 BIF can now be preempted by other processes during its execution. This in order to disturb the rest of the system as little as possible. The returned result is, of course, still a consistent snapshot of existing processes at a time during the call to processes/0.

The documentation of the processes/0 BIF and the is_process_alive/1 BIF have been updated in order to clarify the difference between an existing process and a process that is alive.

Own Id: OTP-7213

tuple_size/1 and byte_size/1 have been substituted for size/1 in the documentation.

Own Id: OTP-7244

Kernel 2.12.1.2

Improvements and New Features

The {allocator_sizes, Alloc} and alloc_util_allocators arguments are now accepted by erlang:system_info/1. For more information see the erlang documentation.

Own Id: OTP-7167

Kernel 2.12.1.1

Fixed Bugs and Malfunctions

Fixed a problem in group that could cause the ssh server to lose answers or hang.

Own Id: OTP-7185 Aux Id: seq10871

Kernel 2.12.1

Fixed Bugs and Malfunctions

file:read/2 and file:consult_stream/1,3 did not use an empty prompt on I/O devices. This bug has now been corrected.

Own Id: OTP-7013

The sctp driver has been updated to work against newer lksctp packages e.g 1.0.7 that uses the API spelling change adaption -> adaptation. Older lksctp (1.0.6) still work. The erlang API in gen_sctp.erl and inet_sctp.hrl now spells 'adaptation' regardless of the underlying C API.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-7120

Improvements and New Features

The documentation has been updated so as to reflect the last updates of the Erlang shell as well as the minor modifications of the control sequence p of the io_lib module.

Superfluous empty lines have been removed from code examples and from Erlang shell examples.

Own Id: OTP-6944 Aux Id: OTP-6554, OTP-6911

tuple_size/1 and byte_size/1 have been substituted for size/1.

Own Id: OTP-7009

Kernel 2.12

Fixed Bugs and Malfunctions

A bug for raw files when reading 0 bytes returning 'eof' instead of empty data has been corrected.

Own Id: OTP-6291 Aux Id: OTP-6967

A bug in gen_udp:fdopen reported by David Baird and also found by Dialyzer has been fixed.

Own Id: OTP-6836 Aux Id: OTP-6594

Calling error_logger:tty(true) multiple times does not give multiple error log printouts.

Own Id: OTP-6884 Aux Id: seq10767

The global name server now ignores nodeup messages when the command line flag -connect_all false has been used. (Thanks to Trevor Woollacott.)

Own Id: OTP-6931

file:write_file/3, file:write/2 and file:read/2 could crash (contrary to documentation) for odd enough file system problems, e.g write to full file system. This bug has now been corrected.

In this process the file module has been rewritten to produce better error codes. Posix error codes now originate from the OS file system calls or are generated only for very similar causes (for example 'enomem' is generated if a memory allocation fails, and 'einval' is generated if the file handle in Erlang is a file handle but currently invalid).

More Erlang-ish error codes are now generated. For example {error,badarg} is now returned from file:close/1 if the argument is not of a file handle type. See file(3).

The possibility to write a single byte using file:write/2 instead of a list or binary of one byte, contradictory to the documentation, has been removed.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-6967 Aux Id: OTP-6597 OTP-6291

Monitor messages produced by the system monitor functionality, and garbage collect trace messages could contain erroneous heap and/or stack sizes when the actual heaps and/or stacks were huge.

As of erts version 5.6 the large_heap option to erlang:system_monitor/[1,2] has been modified. The monitor message is sent if the sum of the sizes of all memory blocks allocated for all heap generations is equal to or larger than the specified size. Previously the monitor message was sent if the memory block allocated for the youngest generation was equal to or larger than the specified size.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-6974 Aux Id: seq10796

inet:getopts/2 returned random values on Windows Vista.

Own Id: OTP-7003

Improvements and New Features

Minor documentation corrections for file:pread/2 and file:pread/3.

Own Id: OTP-6853

The deprecated functions file:file_info/1, init:get_flag/1, init:get_flags/0, and init:get_args/0 have been removed.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-6886

Contract directives for modules in Kernel and STDLIB.

Own Id: OTP-6895

The functions io:columns/0, io:columns/1, io:rows/0 and io:rows/1 are added to allow the user to get information about the terminal geometry. The shell takes some advantage of this when formatting output. For regular files and other io-devices where height and width are not applicable, the functions return {error,enotsup}.

Potential incompatibility: If one has written a custom io-handler, the handler has to either return an error or take care of io-requests regarding terminal height and width. Usually that is no problem as io-handlers, as a rule of thumb, should give an error reply when receiving unknown io-requests, instead of crashing.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-6933

The undocumented and unsupported functions inet:ip_to_bytes/1, inet:ip4_to_bytes/1, inet:ip6_to_bytes/1, and inet:bytes_to_ip6/16 have been removed.

Own Id: OTP-6938

Added new checksum combine functions to zlib. And fixed a bug in zlib:deflate. Thanks Matthew Dempsky.

Own Id: OTP-6970

The spawn_monitor/1 and spawn_monitor/3 BIFs are now auto-imported (i.e. they no longer need an erlang: prefix).

Own Id: OTP-6975

All functions in the code module now fail with an exception if they are called with obviously bad arguments, such as a tuple when an atom was expected. Some functions now also fail for undocumented argument types (for instance, ensure_loaded/1 now only accepts an atom as documented; it used to accept a string too).

Dialyzer will generally emit warnings for any calls that use undocumented argument types. Even if the call happens to still work in R12B, you should correct your code. A future release will adhere to the documentation.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-6983

Kernel 2.11.5.2

Fixed Bugs and Malfunctions

The kernel parameter dist_auto_connect once could fail to block a node if massive parallel sends were issued during a transient failure of network communication

Own Id: OTP-6893 Aux Id: seq10753

Kernel 2.11.5.1

Fixed Bugs and Malfunctions

The internal (rarely used) DNS resolver has been modified to not use the domain search list when asked to resolve an absolute name; a name with a terminating dot. There was also a bug causing it to create malformed DNS queries for absolute names that has been corrected, correction suggested by Scott Lystig Fritchie. The code has also been corrected to look up cached RRs in the same search order as non-cached, now allows having the root domain among the search domains, and can now actually do a zone transfer request.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-6806 Aux Id: seq10714 EABln35459

zlib:close/1 would leave an EXIT message in the message queue if the calling process had the trap_exit flag enabled.

Own Id: OTP-6811

Improvements and New Features

The documentation of process_flag(priority, Level) has been updated, see the erlang documentation.

Own Id: OTP-6745 Aux Id: OTP-6715

Kernel 2.11.5

Fixed Bugs and Malfunctions

The shell has been updated to fix the following flaws: Shell process exit left you with an unresponsive initial shell if not using oldshell. Starting a restricted shell with a nonexisting callback module resulted in a shell where no commands could be used, not even init:stop/0. Fun's could not be used as parameters to local shell functions (in shell_default or user_default) when restricted_shell was active.

Own Id: OTP-6537

The undocumented feature gen_tcp:fdopen/2 was broken in R11B-4. It is now fixed again.

Own Id: OTP-6615

Corrected cancellation of timers in three places in the inet_res module. (Problem found by Dialyzer.)

Own Id: OTP-6676

Improvements and New Features

Corrected protocol layer flue for socket options SO_LINGER, SO_SNDBUF and SO_RCVBUF, for SCTP.

Own Id: OTP-6625 Aux Id: OTP-6336

The behaviour of the inet option {active,once} on peer close is improved and documented.

Own Id: OTP-6681

The inet option send_timeout for connection oriented sockets is added to allow for timeouts in communicating send requests to the underlying TCP stack.

Own Id: OTP-6684 Aux Id: seq10637 OTP-6681

Minor Makefile changes.

Own Id: OTP-6689 Aux Id: OTP-6742

The documentation of process_flag(priority, Level) has been updated, see the erlang documentation.

Own Id: OTP-6715

Kernel 2.11.4.2

Improvements and New Features

process_flag/2 accepts the new flag sensitive.

Own Id: OTP-6592 Aux Id: seq10555

Kernel 2.11.4.1

Fixed Bugs and Malfunctions

A bug in gen_udp:open that broke the 'fd' option has been fixed.

Own Id: OTP-6594 Aux Id: seq10619

Kernel 2.11.4

Fixed Bugs and Malfunctions

Added a warning to the documentation for the error_logger functions error_msg/1,2, warning_msg/1,2 and info_msg/1,2 that calling these function with bad arguments can crash the standard event handler.

Own Id: OTP-4575 Aux Id: seq7693

A bug in inet_db concerning getting the resolver option retry has been corrected.

Own Id: OTP-6380 Aux Id: seq10534

Names registered by calling global:register_name() or global:re_register_name() were not always unregistered when the registering or registered process died. This bug has been fixed.

Own Id: OTP-6428

When setting the kernel configuration parameter error_logger to false, the documentation stated that "No error logger handler is installed". This is true, but error logging is not turned off, as the initial, primitive error logger event handler is kept, printing raw event messages to tty.

Changing this behavior can be viewed as a backward incompatible change. Instead a new value silent for the configuration parameter has been added, which ensures that error logging is completely turned off.

Own Id: OTP-6445

Clarified the documentation for code:lib_dir/1 and code:priv_dir/1. The functions traverse the names of the code path, they do not search the actual directories.

Own Id: OTP-6466

io:setopts returned {error,badarg}, when called with only an expand_fun argument. (Thanks to igwan.)

Own Id: OTP-6508

Improvements and New Features

An interface towards the SCTP Socket API Extensions has been implemented.It is an Open Source patch courtesy of Serge Aleynikov and Leonid Timochouk. The Erlang code parts has been adapted by the OTP team, changing the Erlang API somewhat.

The Erlang interface consists of the module gen_sctp and an include file -include_lib("kernel/include/inet_sctp.hrl"). for option record definitions. The gen_sctp module is documented.

The delivered Open Source patch, before the OTP team rewrites, was written according to http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13 and was claimed to work fine, tested on Linux Fedora Core 5.0 (kernel 2.6.15-2054 or later) and on Solaris 10 and 11. The OTP team rewrites used the same standard document but might have accidentally broken some functionality. If so, it will soon be patched to working state. The tricky parts in C and the general design has essentially not changed. During the rewrites the code was hand tested on SuSE Linux Enterprise Server 10, and briefly on Solaris 10. Feedbach on code and docs is very much appreciated.

The SCTP interface is in beta state. It has only been hand tested and has no automatic test suites in OTP meaning everything is most certainly not tested. Socket active mode is broken. IPv6 is not tested. The documentation has been reworked due to the API changes, but has not been proofread after this.

Thank you from the OTP team to Serge Aleynikov and Leonid Timochouk for a valuable contribution. We hope we have not messed it up too much.

Own Id: OTP-6336

A {minor_version,Version} option is now recognized by term_to_binary/2. {minor_version,1} will cause floats to be encoded in an exact and more space-efficient way compared to the previous encoding.

Own Id: OTP-6434

Monitoring of nodes has been improved. Now the following properties apply to net_kernel:monitor_nodes/[1,2]:

nodeup messages will be delivered before delivery of any message from the remote node passed through the newly established connection.

nodedown messages will not be delivered until all messages from the remote node that have been passed through the connection have been delivered.

Subscriptions can also be made before the net_kernel server has been started.

Own Id: OTP-6481

Setting and getting socket options in a "raw" fashion is now allowed. Using this feature will inevitably produce non portable code, but will allow setting ang getting arbitrary uncommon options on TCP stacks that do have them.

Own Id: OTP-6519

Dialyzer warnings have been eliminated.

Own Id: OTP-6523

The documentation for file:delete/1 and file:set_cwd/1 has been updated to clarify what happens if the input arguments are of an incorrect type.

Own Id: OTP-6535

Kernel 2.11.3.1

Fixed Bugs and Malfunctions

An erroneous packet size could be used for the first messages passed through a newly established connection between two Erlang nodes. This could cause messages to be discarded, or termination of the connection.

Own Id: OTP-6473

Kernel 2.11.3

Fixed Bugs and Malfunctions

On Unix, the unix:cmd/1 function could leave an 'EXIT' message in the message queue for the calling process That problem was more likely to happen in an SMP emulator.

Own Id: OTP-6368

Improvements and New Features

More interfaces are added in erl_ddll, to support different usage scenarios.

Own Id: OTP-6307 Aux Id: OTP-6234

Locks set by calling global:set_lock() were not always deleted when the locking process died. This bug has been fixed.

Own Id: OTP-6341 Aux Id: seq10445

Kernel 2.11.2

Fixed Bugs and Malfunctions

Behavior in case of disappeared nodes when using he dist_auto_connect once got changed in R11B-1. The timeouts regarding normal distributed operations is now reverted to the old (pre R11B-1).

Own Id: OTP-6258 Aux Id: OTP-6200, seq10449

Start-up problems for the internal process used by the inet:gethostbyname() functions were eliminated. If the internal process (inet_gethost_native) had not previously been started, and if several processes at the same time called one of the inet:gethostbyname() functions, the calls could fail.

Own Id: OTP-6286

Improvements and New Features

Code cleanup: the old internal obsolete file_server has been removed. It was only used when communicating with R7 and older nodes.

Own Id: OTP-6245

Trying to open a non-existent or badly formed disk log no longer results in a crash report. In particular, ets:file2tab/1 reports no error when the argument is not a well-formed disk log file. (The return value has not been changed, it is still an error tuple.)

Own Id: OTP-6278 Aux Id: seq10421

There are new BIFs erlang:spawn_monitor/1,3, and the new option monitor for spawn_opt/2,3,4,5.

The observer_backend module has been updated to handle the new BIFs.

Own Id: OTP-6281

To help Dialyzer find more bugs, many functions in the Kernel and STDLIB applications now only accept arguments of the type that is documented.

For instance, the functions lists:prefix/2 and lists:suffix/2 are documented to only accept lists as their arguments, but they actually accepted anything and returned false. That has been changed so that the functions cause an exception if one or both arguments are not lists.

Also, the string:strip/3 function is documented to take a character argument that is a character to strip from one or both ends of the string. Given a list instead of a character, it used to do nothing, but will now cause an exception.

Dialyzer will find most cases where those functions are passed arguments of the wrong type.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-6295

Kernel 2.11.1.1

Improvements and New Features

There is now an option read_packets for UDP sockets that sets the maximum number of UDP packets that will be read for each invocation of the socket driver.

Own Id: OTP-6249 Aux Id: seq10452

Kernel 2.11.1

Fixed Bugs and Malfunctions

In R11B-0, the erl_ddll server process is always started. Despite that, the configuration parameter start_ddll for the Kernel application was still obeyed, which would cause the erl_ddll server to be started TWICE (and the system shutting down as a result). In this release, start_ddll is no longer used and its documentation has been removed.

Own Id: OTP-6163

The kernel option {dist_auto_connect,once} could block out nodes that had never been connected, causing persistent partitioning of networks. Furthermore, partial restarts of networks could cause inconsistent global name databases. Both problems are now solved.

Own Id: OTP-6200 Aux Id: seq10377

Improvements and New Features

Late arriving tcp_closed and udp_closed messages are now removed from the message queue of a process calling gen_tcp:close/1, gen_udp:close/1, and inet:close/1.

Own Id: OTP-6197

Kernel 2.11

Fixed Bugs and Malfunctions

When repairing a disk log with a corrupt index file (caused by for instance a hard disk failure) the old contents of the index file is kept unmodified. This will make repeated attempts to open the disk log fail every time.

Own Id: OTP-5558 Aux Id: seq9823

Previously unlink/1 and erlang:demonitor/2 behaved completely asynchronous. This had one undesirable effect, though. You could never know when you were guaranteed not to be affected by a link that you had unlinked or a monitor that you had demonitored.

The new behavior of unlink/1 and erlang:demonitor/2 can be viewed as two operations performed atomically. Asynchronously send an unlink signal or a demonitor signal, and ignore any future results of the link or monitor.

NOTE: This change can cause some obscure code to fail which previously did not. For example, the following code might hang:

            Mon = erlang:monitor(process, Pid),
            %% ...
            exit(Pid, bang),
            erlang:demonitor(Mon),
            receive
                {'DOWN', Mon, process, Pid, _} -> ok
            %% We were previously guaranteed to get a down message
            %% (since we exited the process ourself), so we could
            %% in this case leave out:
            %% after 0 -> ok
            end,

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-5772

The behavior when an application fails to start and possibly causes the runtime system to halt has been cleaned up, including fixing some minor bugs.

application_controller should now always terminate with a non-nested string, meaning the slogan in an erl_crash.dump should always be easy to read.

init now makes sure that the slogan passed to erlang:halt/1 does not exceed the maximum allowed length.

Redundant calls to list_to_atom/1 has been removed from the primitive error_logger event handler. (Thanks Serge Aleynikov for pointing this out).

The changes only affects the contents of the error messages and crashdump file slogan.

Own Id: OTP-5964

The erl_ddll server is now started when OTP is started and placed under the Kernel supervisor. This fixes several minor issues. It used to be started on demand.

The documentation for the start and stop functions in the erl_ddll module has been removed, as those functions are not meant to be used by other applications.

Furthermore, the erl_ddll:stop/1 function no longer terminates the erl_ddll server, as that would terminate the entire runtime system.

Own Id: OTP-6033

Improvements and New Features

Removed some unused functions from application_master.

Own Id: OTP-3889

Global no longer allows the registration of a process under more than one name. If the old (buggy) behavior is desired the Kernel application variable global_multi_name_action can be given the value allow.

Own Id: OTP-5640 Aux Id: OTP-5603

The (slightly misleading) warnings that was shown when the erlang.erl file was compiled has been eliminated.

Own Id: OTP-5947

The auth module API is deprecated.

Own Id: OTP-6037

Added erlang:demonitor/2, making it possible to at the same time flush a received 'DOWN' message, if there is one. See erlang.

Own Id: OTP-6100 Aux Id: OTP-5772

Kernel 2.10.13

Fixed Bugs and Malfunctions

Large files (more than 2 GBytes) are now handled on Solaris 8.

Own Id: OTP-5849 Aux Id: seq10157

During startup, a garbage {'DOWN', ...} message was left by inet_gethost_native, that caused problems for the starting code server.

Own Id: OTP-5978 Aux Id: OTP-5974

Improvements and New Features

global now makes several attempts to connect nodes when maintaining the fully connected network. More than one attempt is sometimes needed under very heavy load.

Own Id: OTP-5889

erl_epmd now explicitly sets the timeout to infinity when calling gen_server:call. The old timeout of 15 seconds could time out under very heavy load.

Own Id: OTP-5959

Corrected the start of code server to use reference-tagged tuples to ensure that an unexpected message sent to the parent process does not cause a halt of the system. Also removed the useless start/* functions in both code.erl and code_server.erl and no longer exports the init function from code_server.erl.

Own Id: OTP-5974 Aux Id: seq10243, OTP-5978

Kernel 2.10.12

Fixed Bugs and Malfunctions

A bug in global has been fixed: the locker process added nonode@nohost to the list of nodes to lock. This could happen before any nodes got known to the global name server. Depending on net configuration the symptom was a delay.

Own Id: OTP-5792 Aux Id: OTP-5563

If an .app file is missing, the error reason returned by application:load/1 has been corrected to {"no such file or directory", "FILE.app"}, instead of the less informative {"unknown POSIX error","FILE.app"}.

Own Id: OTP-5809

Bug fixes: disk_log:accessible_logs/0 no longer reports all pg2 process groups as distributed disk logs; disk_log:pid2name/1 did not recognize processes of distributed disk logs.

Own Id: OTP-5810

The functions file:consult/1, file:path_consult/2, file:eval/1,2, file:path_eval/2,3, file:script/1,2, file:path_script/2,3 now return correct line numbers in error tuples.

Own Id: OTP-5814

If there were user-defined variables in the boot script, and their values were not provided using the -boot_var option, the emulator would refuse to start with a confusing error message. Corrected to show a clear, understandable message.

The prim_file module was modified to not depend on the lists module, to make it possible to start the emulator using a user-defined loader. (Thanks to Martin Bjorklund.)

Own Id: OTP-5828 Aux Id: seq10151

Minor corrections in the description of open modes. (Thanks to Richard Carlsson.)

Own Id: OTP-5856

Improvements and New Features

application_controller now terminates with the actual error reason, instead of shutdown. This means that the crash dump now should be somewhat more informative, in the case where the runtime system is terminated due to an error in an application.

Example: If the (permanent) application app1 fails to start, the slogan now will be: "Kernel pid terminated (application_controller) ({application_start_failure,app1,{shutdown, {app1,start,[normal,[]]}}})"

rather than the previous "Kernel pid terminated (application_controller) (shutdown)".

Own Id: OTP-5811

Kernel 2.10.11.1

Fixed Bugs and Malfunctions

Timers could sometimes timeout too early. This bug has now been fixed.

Automatic cancellation of timers created by erlang:send_after(Time, pid(), Msg), and erlang:start_timer(Time, pid(), Msg) has been introduced. Timers created with the receiver specified by a pid, will automatically be cancelled when the receiver exits. For more information see the erlang man page.

In order to be able to maintain a larger amount of timers without increasing the maintenance cost, the internal timer wheel and bif timer table have been enlarged.

Also a number of minor bif timer optimizations have been implemented.

Own Id: OTP-5795 Aux Id: OTP-5090, seq8913, seq10139, OTP-5782

Improvements and New Features

Documentation improvements:

- documentation for erlang:link/1 corrected

- command line flag -code_path_cache added

- erl command line flags clarifications

- net_kernel clarifications

Own Id: OTP-5847

Kernel 2.10.11

Fixed Bugs and Malfunctions

Several bug fixes and improvements in the global name registration facility (see global):

the name resolving procedure did not always unlink no longer registered processes;

the global name could sometimes hang when a nodedown was immediately followed by a nodeup;

global names were not always unregistered when a node went down;

it is now possible to set and delete locks at the same time as the global name server is resolving names--the handling of global locks has been separated from registration of global names;

As of this version, global no longer supports nodes running Erlang/OTP R7B or earlier.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-5563

The functions global:set_lock/3 and global:trans/4 now accept the value 0 (zero) of the Retries argument.

Own Id: OTP-5737

The inet:getaddr(Addr, Family) no longer validates the Addr argument if it is a 4 or 8 tuple containing the IP address, except for the size of the tuple and that it contains integers in the correct range.

The reason for the change is that validation could cause the following sequence of calls to fail:

{ok,Addr} = inet:getaddr(localhost, inet6), gen_tcp:connect(Addr, 7, [inet6])

Own Id: OTP-5743

Improvements and New Features

The previously undocumented and UNSUPPORTED zlib module has been updated in an incompatible way and many bugs have been corrected. It is now also documented.

* POTENTIAL INCOMPATIBILITY *

Own Id: OTP-5715

Added application interface functions which_applications/1, set_env/4 and unset_env/3, which take an additional Timeout argument. To be used in situations where the standard gen_server timeout (5000ms) is not adequate.

Own Id: OTP-5724 Aux Id: seq10083

Improved documentation regarding synchronized start of applications with included applications (using start phases and application_starter).

Own Id: OTP-5754

New socket options priority and tos for platforms that support them (currently only Linux).

Own Id: OTP-5756

The global name server has been optimized when it comes to maintaining a fully connected network.

Own Id: OTP-5770

Kernel 2.10.10.1

Fixed Bugs and Malfunctions

The native resolver has gotten an control API for extended debugging and soft restart. It is: inet_gethost_native:control(Control)
Control = {debug_level,Level} | soft_restart
Level = integer() in the range 0-4.

Own Id: OTP-5751 Aux Id: EABln25013

Kernel 2.10.10

Fixed Bugs and Malfunctions

If several processes (at the same node) simultaneously tried to start the same distributed application, this could lead to application:start returning an erroneous value, or even hang.

Own Id: OTP-5606 Aux Id: seq9838

Improvements and New Features

The manual pages for most of the Kernel and some of the STDLIB modules have been updated, in particular regarding type definitions.

The documentation of the return value for erts:info/1 has been corrected.

The documentation for erlang:statistics/1 now lists all possible arguments.

Own Id: OTP-5360

When the native resolver fails a gethostbyaddr lookup, nxdomain should be returned. There should be no attempt to fallback on a routine that succeeds if only the syntax of the IP address is valid. This has been fixed.

Own Id: OTP-5598 Aux Id: OTP-5576

Replaced some tuple funs with the new fun M:F/A construct.

The high-order functions in the lists module no longer accept bad funs under any circumstances. 'lists:map(bad_fun, [])' used to return '[]' but now causes an exception.

Unused, broken compatibility code in the ets module was removed. (Thanks to Dialyzer.)

Eliminated 5 discrepancies found by Dialyzer in the Appmon application.

Own Id: OTP-5633

The possibility to have comments following the list of tuples in a config file (file specified with the -config flag) has been added.

Own Id: OTP-5661 Aux Id: seq10003

Kernel 2.10.9

Fixed Bugs and Malfunctions

'erl -config sys.config' would fail to start if the sys.config file did not contain any whitespace at all after the dot. (Thanks to Anders Nygren.)

Own Id: OTP-5543

A bug regarding tcp sockets which results in hanging gen_tcp:send/2 has been corrected. To encounter this bug you needed one process that read from a socket, one that wrote more date than the reader read out so the sender got suspended, and then the reader closed the socket. (Reported and diagnosed by Alexey Shchepin.)

Corrected a bug in the (undocumented and unsupported) option {packet,http} for gen_tcp. (Thanks to Claes Wikstrom and Luke Gorrie.)

Updated the documentation regarding the second argument to gen_tcp:recv/2, the Length to receive.

Own Id: OTP-5582 Aux Id: seq9839

Improvements and New Features

At startup, the Erlang resolver hosts table was used to look up the name of the local (and possibly stand alone) host. This was incorrect. The configured resolver method is now used for this purpose.

Own Id: OTP-5393

The erlang:port_info/1 BIF is now documented. Minor corrections of the documentation for erlang:port_info/2.

Added a note to the documentation of the math module that all functions are not available on all platforms.

Added more information about the +c option in the erl man page in the ERTS documentation.

Own Id: OTP-5555

The new fun M:F/A construct creates a fun that refers to the latest version of M:F/A. This syntax is meant to replace tuple funs {M,F} which have many problems.

The new type test is_function(Fun,A) (which may be used in guards) test whether Fun is a fun that can be applied with A arguments. (Currently, Fun can also be a tuple fun.)

Own Id: OTP-5584

According to the documentation global implements the equivalent of register/2, which returns badarg if a process is already registered. As it turns out there is no check in global if a process is registered under more than one name. If some process is accidentally or by design given several names, it is possible that the name registry becomes inconsistent due to the way the resolve function is called when name clashes are discovered (see register_name/3 in global).

In OTP R11B global will not allow the registration of a process under more than one name. To help finding code where no will be returned, a Kernel application variable, global_multi_name_action, is hereby introduced. Depending on its value (info, warning, or error), messages are sent to the error logger when global discovers that some process is given more than one name. The variable only affects the node where it is defined.

Own Id: OTP-5603

Kernel 2.10.8

Improvements and New Features

In case of a DNS lookup loop, inet_db:getbyname ends up building an infinite list. This has been fixed.

Own Id: OTP-5449

When doing an inet6 name lookup on an IPv4 address it was possible to get an address on IPv4 format back. This has been corrected. Some other minor inconsistencies regarding IPv6 name lookup have also been corrected.

Own Id: OTP-5576

Kernel 2.10.7

Fixed Bugs and Malfunctions

Under certain circumstances the net_kernel could emit spurious nodedown messages. This bug has been fixed.

Own Id: OTP-5396

Removed description of the keep_zombies configuration parameter in the kernel man page.

Own Id: OTP-5497

Improvements and New Features

Eliminated Dialyzer warnings (caused by dead code) in the init and prim_file modules.

Own Id: OTP-5496

inet_config now also checks the environment variable ERL_INETRC for a possible user configuration file. See the ERTS User's Guide for details.

Own Id: OTP-5512

Kernel 2.10.6

Improvements and New Features

The c option for the +B flag has been introduced which makes it possible to use Ctrl-C (Ctrl-Break on Windows) to interrupt the shell process rather than to invoke the emulator break handler. All new +B options are also supported on Windows (werl) as of now. Furthermore, Ctrl-C on Windows has now been reserved for copying text (what Ctrl-Ins was used for previously). Ctrl-Break should be used for break handling. Lastly, the documentation of the system flags has been updated.

Own Id: OTP-5388

The possibility to start the Erlang shell in parallel with the rest of the system was reintroduced for backwards compatibility in STDLIB 1.13.1. The flag to be used for this is now called async_shell_start and has been documented. New shells started from the JCL menu are not synchronized with init anymore. This makes it possible to start a new shell (e.g. for debugging purposes) even if the initial shell has not come up.

Own Id: OTP-5406 Aux Id: OTP-5218

Kernel 2.10.5

Fixed Bugs and Malfunctions

Documentation for erlang:binary_to_float/1 deleted. The BIF itself was removed several releases ago.

Updated documentation for apply/2 and apply/3.

Own Id: OTP-5391

Improvements and New Features

net_kernel:monitor_nodes/2 which takes a flag and an option list has been added. By use of net_kernel:monitor_nodes/2 one can subscribe for nodeup/nodedown messages with extra information. It is now possible to monitor hidden nodes, and get nodedown reason. See the net_kernel documentation for more information.

Own Id: OTP-5374

Kernel 2.10.4

Fixed Bugs and Malfunctions

The application master for an application now terminates the application faster, which reduces the risk for timeouts in other parts of the system.

Own Id: OTP-5363 Aux Id: EABln19084

A BIF erlang:raise/3 has been added. See the manual for details. It is intended for internal system programming only, advanced error handling.

Own Id: OTP-5376 Aux Id: OTP-5257

Kernel 2.10.3

Improvements and New Features

With the -eval flag (erl -eval Expr), an arbitrary expression can be evaluated during system initialization. This is documented in init.

Own Id: OTP-5260

The unsupported and undocumented modules socks5, socks5_auth, socks5_tcp, and socks5_udp have been removed.

Own Id: OTP-5266

Kernel 2.10.1

Fixed Bugs and Malfunctions

The Pman 'trace shell' functionality was broken and has now been fixed. Furthermore, Pman could not correctly find the pid of the active shell if more than one shell process was running on the node. This has also been corrected.

Own Id: OTP-5191

The documentation for the auth:open/1 function which no longer exists has been removed. (Thanks to Miguel Barreiro.)

Own Id: OTP-5208

Corrected the crc32/3 function in the undocumented and unsupported zlib module.

Own Id: OTP-5227

Improvements and New Features

You can now start Erlang with the -rsh flag which gives you a remote initial shell instead of a local one. Example:

            erl -sname this_node -rsh other_node@other_host

Own Id: OTP-5210

If /etc/hosts specified two hosts with the same IP address (on separate lines), only the last host would be registered by inet_db during inet configuration. This has been corrected now so that both aliases are registered with the same IP address.

Own Id: OTP-5212 Aux Id: seq7128

The documentation for BIFs that take I/O lists have been clarified. Those are list_to_binary/1, port_command/2, port_control/3.

Documentation for all is_* BIFs (such as is_atom/1) has been added.

Removed the documentation for erlang:float_to_binary/2 which was removed from the run-time system several releases ago.

Own Id: OTP-5222

Introduction

Scope

The Kernel application has all the code necessary to run the Erlang runtime system: file servers, code servers, and so on.

The Kernel application is the first application started. It is mandatory in the sense that the minimal system based on Erlang/OTP consists of Kernel and STDLIB. Kernel contains the following functional areas:

Start, stop, supervision, configuration, and distribution of applications

Code loading

Logging

Global name service

Supervision of Erlang/OTP

Communication with sockets

Operating system interface

Prerequisites

It is assumed that the reader is familiar with the Erlang programming language.

Socket Usage

Introduction

The socket interface (module) is basically a "thin" layer on top of the OS socket interface. It is assumed that, unless you have special needs, gen_[tcp|udp|sctp] should be sufficient (when they become available).

Note that just because we have a documented and described option, it does not mean that the OS supports it. So its recommended that the user reads the platform specific documentation for the option used.

Asynchronous calls

Some functions allow for an asynchronous call (accept/2, connect/3, recv/3,4, recvfrom/3,4, recvmsg/2,3,5, send/3,4, sendmsg/3,4 and sendto/4,5). This is achieved by setting the Timeout argument to nowait. For instance, if calling the recv/3 function with Timeout set to nowait (i.e. recv(Sock, 0, nowait)) when there is actually nothing to read, it will return with:

On Unix - {select,SelectInfo}

SelectInfo contains the SelectHandle.

On Windows - {completion,CompletionInfo}

CompletionInfo contains the CompletionHandle.

When data eventually arrives a 'select' or 'completion' message will be sent to the caller:

On Unix - {'$socket', socket(), select, SelectHandle}

The caller can then make another call to the recv function and now expect data.

Note that all other users are locked out until the 'current user' has called the function (recv in this case). So either immediately call the function or cancel.

On Windows - {'$socket', socket(), completion, {CompletionHandle, CompletionStatus}}

The CompletionStatus contains the result of the operation (read).

The user must also be prepared to receive an abort message:

{'$socket', socket(), abort, Info}

If the operation is aborted for whatever reason (e.g. if the socket is closed "by someone else"). The Info part contains the abort reason (in this case that the socket has been closed Info = {SelectHandle, closed}).

The general form of the 'socket' message is:

{'$socket', Sock :: socket(), Tag :: atom(), Info :: term()}

Where the format of Info is a function of Tag:

Tag | Info value type
select | select_handle()
completion | {completion_handle(), CompletionStatus}
abort | {select_handle(), Reason :: term()}

Table: socket message info value type

The select_handle() is the same as was returned in the SelectInfo.

The completion_handle() is the same as was returned in the CompletionInfo.

Socket Registry

The socket registry is how we keep track of sockets. There are two functions that can be used for interaction: socket:number_of/0 and socket:which_sockets/1.

In systems which create and delete many sockets dynamically, it (the socket registry) could become a bottleneck. For such systems, there are a couple of ways to control the use of the socket registry.

Firstly, its possible to effect the global default value when building OTP from source with the two configure options:

--enable-esock-socket-registry (default) | --disable-esock-socket-registry

Second, its possible to effect the global default value by setting the environment variable ESOCK_USE_SOCKET_REGISTRY (boolean) before starting the erlang.

Third, its possible to alter the global default value in runtime by calling the function use_registry/1.

And finally, its possible to override the global default when creating a socket (with open/2 and open/4) by providing the attribute use_registry (boolean) in the their Opts argument (which effects that specific socket).

Examples

Completion asynchronous sendv

This is a simple example function that illustrates how to use socket:sendv/3 with asynchronous (nowait) on completion systems (Windows).
Observe that this is not an illustration how to write a asynchronous sendv function. Its just an example of what kind of messages and results that can be expected. The example below basically (re-) implements: socket:sendv(Sock, IOV, infinity).

completion_sendv(Sock, IOV) ->
    case socket:sendv(Sock, IOV, nowait) of
        ok -> % Complete success - We are done
            ok;
        {completion, {CompletionInfo, RestIOV0}} ->
            %% Some of IOV was sent, but the rest, RestIOV0, was scheduled
            case completion_sendv_await_result(Sock,
                                               CompletionInfo, RestIOV0) of
                ok -> % We done
                    ok;
                {ok, RestIOV} ->
                    completion_sendv(Sock, RestIOV);
                {error, Reason} ->
                    {error, {Reason, RestIOV0}}
            end;
        {completion, CompletionInfo} ->
            %% Nothing was sent, IOV was scheduled
            case completion_sendv_await_result(Sock,
                                               CompletionInfo, IOV) of
                ok -> % We done
                    ok;
                {ok, RestIOV} ->
                    completion_sendv(Sock, RestIOV);
                {error, _} = ERROR ->
                    ERROR
            end;
        {error, {_Reason, _RestIOV}} = ERROR ->
            %% Some part of the I/O vector was sent before an error occured
            ERROR;
        {error, _} = ERROR ->
            %% Note that
            ERROR
    end.

completion_sendv_await_result(Sock,
                              {completion_info, _, Handle},
                              IOV) ->
  receive
      {'$socket', Sock, abort, {Handle, Reason}} ->
          ?P("unexpected abort: "
             "~n   Reason: ~p", [Reason]),
          {error, {abort, Reason}};

      {'$socket', Sock, completion, {Handle, {ok, Written}}} ->
          %% Partial send; calculate rest I/O vector
          case socket:rest_iov(Written, IOV) of
              [] -> % We are done
                  ok;
              RestIOV ->
                  {ok, RestIOV}
          end;

      {'$socket', Sock, completion, {Handle, CompletionStatus}} ->
          CompletionStatus

  end.

Completion asynchronous recv

This is a simple example function that illustrates how to use socket:recv/3 with asynchronous (nowait) on completion systems (Windows). Observe that this is not an illustration how to write a asynchronous read function. Its just an example of what kind of messages and results that can be expected. The example below basically (re-) implements: socket:recv(Sock, Sz).

completion_recv(Sock, Sz) when (Sz > 0) ->
    completion_recv(Sock, Sz, []).

completion_recv(_Sock, 0, [Bin] = _Acc) ->
    {ok, Bin};
completion_recv(_Sock, 0, Acc) ->
    {ok, erlang:iolist_to_binary(lists:reverse(Acc))};
completion_recv(Sock, Sz, Acc) ->
    case socket:recv(Sock, Sz, nowait) of
        {ok, Bin} when (byte_size(Bin) =:= Sz) ->
            completion_recv(Sock, 0, [Bin|Acc]);
        {ok, Bin} ->
            completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);

	{completion, CompletionInfo} ->
            case completion_recv_await_result(Sock, CompletionInfo) of
                {ok, Bin} ->
                    completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);
                {error, {_Reason, _Data}} = ERROR ->
                    ERROR;
                {error, _Reason} = ERROR ->
                    ERROR
	    end;

	{error, {_Reason, _Data}} = ERROR ->
	    ERROR;
	{error, _Reason} = ERROR ->
	    ERROR

    end.

completion_recv_await_result(Sock,
                             {completion_info, _, Handle}) ->
    receive
	{'$socket', Sock, abort, {Handle, Reason}} ->
	    {error, {abort, Reason}};

	{'$socket', Sock, completion, {Handle, {ok, _Bin} = OK}} ->
            %% We "should" be done
	    OK;
	{'$socket', Sock, completion, {Handle, {more, Bin}}} ->
            %% There is more to read
	    {ok, Bin};

	{'$socket', Sock, completion, {Handle, CompletionStatus}} ->
	    CompletionStatus

    end.

Echo server (and client)

This example is intended to show how to create a simple (echo) server (and client).

-module(example).

-export([client/2, client/3]).
-export([server/0, server/1, server/2]).

%% ======================================================================

%% === Client ===

client(#{family := Family} = ServerSockAddr, Msg)
  when is_list(Msg) orelse is_binary(Msg) ->
    {ok, Sock} = socket:open(Family, stream, default),
    ok         = maybe_bind(Sock, Family),
    ok         = socket:connect(Sock, ServerSockAddr),
    client_exchange(Sock, Msg);

client(ServerPort, Msg)
  when is_integer(ServerPort) andalso (ServerPort > 0) ->
    Family   = inet, % Default
    Addr     = get_local_addr(Family), % Pick an address
    SockAddr = #{family => Family,
		 addr   => Addr,
		 port   => ServerPort},
    client(SockAddr, Msg).

client(ServerPort, ServerAddr, Msg)
  when is_integer(ServerPort) andalso (ServerPort > 0) andalso
       is_tuple(ServerAddr) ->
    Family   = which_family(ServerAddr),
    SockAddr = #{family => Family,
		 addr   => ServerAddr,
		 port   => ServerPort},
    client(SockAddr, Msg).

%% Send the message to the (echo) server and wait for the echo to come back.
client_exchange(Sock, Msg) when is_list(Msg) ->
    client_exchange(Sock, list_to_binary(Msg));
client_exchange(Sock, Msg) when is_binary(Msg) ->
    ok = socket:send(Sock, Msg, infinity),
    {ok, Msg} = socket:recv(Sock, byte_size(Msg), infinity),
    ok.

%% ======================================================================

%% === Server ===

server() ->
    %% Make system choose port (and address)
    server(0).

%% This function return the port and address that it actually uses,
%% in case server/0 or server/1 (with a port number) was used to start it.

server(#{family := Family, addr := Addr, port := _} = SockAddr) ->
    {ok, Sock} = socket:open(Family, stream, tcp),
    ok         = socket:bind(Sock, SockAddr),
    ok         = socket:listen(Sock),
    {ok, #{port := Port}} = socket:sockname(Sock),
    Acceptor = start_acceptor(Sock),
    {ok, {Port, Addr, Acceptor}};

server(Port) when is_integer(Port) ->
    Family   = inet, % Default
    Addr     = get_local_addr(Family), % Pick an address
    SockAddr = #{family => Family,
		 addr   => Addr,
		 port   => Port},
    server(SockAddr).

server(Port, Addr)
  when is_integer(Port) andalso (Port >= 0) andalso
       is_tuple(Addr) ->
    Family   = which_family(Addr),
    SockAddr = #{family => Family,
		 addr   => Addr,
		 port   => Port},
    server(SockAddr).

%% --- Echo Server - Acceptor ---

start_acceptor(LSock) ->
    Self = self(),
    {Pid, MRef} = spawn_monitor(fun() -> acceptor_init(Self, LSock) end),
    receive
	{'DOWN', MRef, process, Pid, Info} ->
	    erlang:error({failed_starting_acceptor, Info});
	{Pid, started} ->
	    %% Transfer ownership
	    socket:setopt(LSock, otp, owner, Pid),
	    Pid ! {self(), continue},
	    erlang:demonitor(MRef),
	    Pid
    end.

acceptor_init(Parent, LSock) ->
    Parent ! {self(), started},
    receive
	{Parent, continue} ->
	    ok
    end,
    acceptor_loop(LSock).

acceptor_loop(LSock) ->
    case socket:accept(LSock, infinity) of
	{ok, ASock} ->
	    start_handler(ASock),
	    acceptor_loop(LSock);
	{error, Reason} ->
	    erlang:error({accept_failed, Reason})
    end.

%% --- Echo Server - Handler ---

start_handler(Sock) ->
    Self = self(),
    {Pid, MRef} = spawn_monitor(fun() -> handler_init(Self, Sock) end),
    receive
	{'DOWN', MRef, process, Pid, Info} ->
	    erlang:error({failed_starting_handler, Info});
	{Pid, started} ->
	    %% Transfer ownership
	    socket:setopt(Sock, otp, owner, Pid),
	    Pid ! {self(), continue},
	    erlang:demonitor(MRef),
	    Pid
    end.

handler_init(Parent, Sock) ->
    Parent ! {self(), started},
    receive
	{Parent, continue} ->
	    ok
    end,
    handler_loop(Sock, undefined).

%% No "ongoing" reads
%% The use of 'nowait' here is clearly *overkill* for this use case,
%% but is intended as an example of how to use it.
handler_loop(Sock, undefined) ->
    case socket:recv(Sock, 0, nowait) of
	{ok, Data} ->
	    echo(Sock, Data),
	    handler_loop(Sock, undefined);

	{select, SelectInfo} ->
	    handler_loop(Sock, SelectInfo);

	{completion, CompletionInfo} ->
	    handler_loop(Sock, CompletionInfo);

	{error, Reason} ->
	    erlang:error({recv_failed, Reason})
    end;

%% This is the standard (asyncronous) behaviour.
handler_loop(Sock, {select_info, recv, SelectHandle}) ->
    receive
	{'$socket', Sock, select, SelectHandle} ->
	    case socket:recv(Sock, 0, nowait) of
		{ok, Data} ->
		    echo(Sock, Data),
		    handler_loop(Sock, undefined);

		{select, NewSelectInfo} ->
		    handler_loop(Sock, NewSelectInfo);

		{error, Reason} ->
		    erlang:error({recv_failed, Reason})
	    end
    end;

%% This is the (asyncronous) behaviour on platforms that support 'completion',
%% currently only Windows.
handler_loop(Sock, {completion_info, recv, CompletionHandle}) ->
    receive
	{'$socket', Sock, completion, {CompletionHandle, CompletionStatus}} ->
	    case CompletionStatus of
		{ok, Data} ->
		    echo(Sock, Data),
		    handler_loop(Sock, undefined);
		{error, Reason} ->
		    erlang:error({recv_failed, Reason})
	    end
    end.

echo(Sock, Data) when is_binary(Data) ->
    ok = socket:send(Sock, Data, infinity),
    io:format("** ECHO **"
	      "~n~s~n", [binary_to_list(Data)]).

%% ======================================================================

%% === Utility functions ===

maybe_bind(Sock, Family) ->
    maybe_bind(Sock, Family, os:type()).

maybe_bind(Sock, Family, {win32, _}) ->
    Addr     = get_local_addr(Family),
    SockAddr = #{family => Family,
                 addr   => Addr,
                 port   => 0},
    socket:bind(Sock, SockAddr);
maybe_bind(_Sock, _Family, _OS) ->
    ok.

%% The idea with this is extract a "usable" local address
%% that can be used even from *another* host. And doing
%% so using the net module.

get_local_addr(Family) ->
    Filter =
	fun(#{addr  := #{family := Fam},
	      flags := Flags}) ->
		(Fam =:= Family) andalso (not lists:member(loopback, Flags));
	   (_) ->
		false
	end,
    {ok, [SockAddr|_]} = net:getifaddrs(Filter),
    #{addr := #{addr := Addr}} = SockAddr,
    Addr.

which_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 4) ->
    inet;
which_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 8) ->
    inet6.

Socket SCTP example snippets

Here are couple of code snippets that attempts to explain some common use cases for socket SCTP. Note that this is in no way complete! Especially since the different implementations behaves slighly differently (different set of messages).

Basic init

This is an operation that must be performed before any active operations can be performed: Subscribe to SCTP events

.
.
.
%% data_io needs to be 'true' if data is to be exchanged
Events = #{data_io          => true,
           association      => true,
           address          => true,
           send_failure     => true,
           peer_error       => true,
           shutdown         => true,
           partial_delivery => true,
           adaptation_layer => false,
           authentication   => false,
           sender_dry       => false}),
socket:setopt(Sock, {sctp, events}, Events),
.
.
.

Accept

There are basically two variants of this. The first is when the server attempts to handle all incoming connections itself (data_io = true). The second is when the server only handles the "accept" operation and then spawns a handler process (that does a peeloff) to handle the "work" (data_io = false).

.
.
.
case socket:recvmsg(Sock) of
    {ok, #{notification := #{type := assoc_change,
                             state := comm_up,
                             assoc_id := AID}}} ->
         %% Start the handler, that performs a peeloff
         start_handler(Sock, AID);
.
.
.

Connect

This is a two step process. First perform connect and then await confirmation.

.
.
.
ServerSA = ...
%% Issue a connect...
ok = socket:connect(Sock, ServerSA),
%% Wait for confirmation...
AssocID = case socket:recvmsg(Sock) of
              {ok, #{flags        := _,
                     addr         := _,
                     notification := #{type     := assoc_change,
                                       state    := comm_up,
                                       assoc_id := AID}}} ->
	          AID;
	      {error, Reason} ->
	          exit(Reason)
	  end,
%% Ready for business...
.
.
.

Graceful shutdown

Perform a graceful shutdown by sending an message with the eof flag (in the SRI). On the "other end" a set of shutdown notification(s) will be received.

.
.
.
EofSRI = #{assoc_id => AssocID,
           stream   => StreamID,
           flags    => [eof]},
EofMsg = #{iov  => [],
           ctrl => [#{level => sctp,
                      type  => sndrcv,
                      value => EofSRI}]},
ok = socket:sendmsg(Sock, EofMsg),
.
.
.

Sending data

When sending, a (sparse) SRI (send receive info) structure is needed. This identifies the Assoc and Stream.

.
.
.
SRI     = #{assoc_id => AssocID,
            stream   => StreamID},
CtrlSRI = #{level => sctp,
            type  => sndrcv,
            value => SRI},
Msg     = #{iov => ... % List of binary()
            ctrl => [CtrlSRI]},
ok = socket:sendmsg(Sock, Msg),
.
.
.

Socket Options

Options for level otp:

Option Name | Value Type | Set | Get | Other Requirements and comments
assoc_id | integer() | no | yes | type = seqpacket, protocol = sctp, is an association
debug | boolean() | yes | yes | none
iow | boolean() | yes | yes | none
controlling_process | pid() | yes | yes | none
rcvbuf | default | pos_integer() | {pos_integer(), pos_ineteger()} | yes | yes | The tuple format is not allowed on Windows. 'default' only valid for set. The tuple form is only valid for type 'stream' and protocol 'tcp'.
rcvctrlbuf | default | pos_integer() | yes | yes | default only valid for set
sndctrlbuf | default | pos_integer() | yes | yes | default only valid for set
fd | integer() | no | yes | none
use_registry | boolean() | no | yes | the value is set when the socket is created, by a call to open/2 or open/4.

Table: option levels

Options for level socket:

Option Name | Value Type | Set | Get | Other Requirements and comments
acceptconn | boolean() | no | yes | none
bindtodevice | string() | yes | yes | Before Linux 3.8, this socket option could be set, but not get. Only works for some socket types (e.g. inet). If empty value is set, the binding is removed.
broadcast | boolean() | yes | yes | type = dgram
bsp_state | map() | no | yes | Windows only
debug | integer() | yes | yes | may require admin capability
domain | domain() | no | yes | Not on FreeBSD (for instance)
dontroute | boolean() | yes | yes | none
exclusiveaddruse | boolean() | yes | yes | Windows only
keepalive | boolean() | yes | yes | none
linger | abort | linger() | yes | yes | none
maxdg | integer() | no | yes | Windows only
max_msg_size | integer() | no | yes | Windows only
oobinline | boolean() | yes | yes | none
peek_off | integer() | yes | yes | domain = local (unix). Currently disabled due to a possible infinite loop when calling recv([peek]) the second time.
priority | integer() | yes | yes | none
protocol | protocol() | no | yes | Not on (some) Darwin (for instance)
rcvbuf | non_neg_integer() | yes | yes | none
rcvlowat | non_neg_integer() | yes | yes | none

rcvtimeo
timeval()
yes
yes
This option is not normally supported. OTP has to be explicitly built with the --enable-esock-rcvsndtime configure option for this to be available. Since our implementation is nonblocking, its unknown if and how this option works, or even if it may cause malfunctions. Therefore, we do not recommend setting this option. Instead, use the Timeout argument to, for instance, the recv/3 function.

reuseaddr | boolean() | yes | yes | none
reuseport | boolean() | yes | yes | domain = inet | inet6
sndbuf | non_neg_integer() | yes | yes | none
sndlowat | non_neg_integer() | yes | yes | not changeable on Linux

sndtimeo
timeval()
yes
yes
This option is not normally supported. OTP has to be explicitly built with the --enable-esock-rcvsndtime configure option for this to be available. Since our implementation is nonblocking, its unknown if and how this option works, or even if it may cause malfunctions. Therefore, we do not recommend setting this option. Instead, use the Timeout argument to, for instance, the send/3 function.

timestamp | boolean() | yes | yes | none
type | type() | no | yes | none

Table: socket options

Options for level ip:

Option Name | Value Type | Set | Get | Other Requirements and comments
add_membership | ip_mreq() | yes | no | none
add_source_membership | ip_mreq_source() | yes | no | none
block_source | ip_mreq_source() | yes | no | none
drop_membership | ip_mreq() | yes | no | none
drop_source_membership | ip_mreq_source() | yes | no | none
freebind | boolean() | yes | yes | none
hdrincl | boolean() | yes | yes | type = raw
minttl | integer() | yes | yes | type = raw
msfilter | null | ip_msfilter() | yes | no | none
mtu | integer() | no | yes | type = raw
mtu_discover | ip_pmtudisc() | yes | yes | none
multicast_all | boolean() | yes | yes | none
multicast_if | any | ip4_address() | yes | yes | none
multicast_loop | boolean() | yes | yes | none
multicast_ttl | uint8() | yes | yes | none
nodefrag | boolean() | yes | yes | type = raw
pktinfo | boolean() | yes | yes | type = dgram
recvdstaddr | boolean() | yes | yes | type = dgram
recverr | boolean() | yes | yes | none
recvif | boolean() | yes | yes | type = dgram | raw
recvopts | boolean() | yes | yes | type =/= stream
recvorigdstaddr | boolean() | yes | yes | none
recvttl | boolean() | yes | yes | type =/= stream
retopts | boolean() | yes | yes | type =/= stream
router_alert | integer() | yes | yes | type = raw
sendsrcaddr | boolean() | yes | yes | none
tos | ip_tos() | yes | yes | some high-priority levels may require superuser capability
transparent | boolean() | yes | yes | requires admin capability
ttl | integer() | yes | yes | none
unblock_source | ip_mreq_source() | yes | no | none

Table: ip options

Options for level ipv6:

Option Name | Value Type | Set | Get | Other Requirements and comments
addrform | inet | yes | no | allowed only for IPv6 sockets that are connected and bound to a v4-mapped-on-v6 address
add_membership | ipv6_mreq() | yes | no | none
authhdr | boolean() | yes | yes | type = dgram | raw, obsolete?
drop_membership | ipv6_mreq() | yes | no | none
dstopts | boolean() | yes | yes | type = dgram | raw, requires superuser privileges to update
flowinfo | boolean() | yes | yes | type = dgram | raw, requires superuser privileges to update
hoplimit | boolean() | yes | yes | type = dgram | raw. On some platforms (e.g. FreeBSD) is used to set in order to get hoplimit as a control message heeader. On others (e.g. Linux), recvhoplimit is set in order to get hoplimit.
hopopts | boolean() | yes | yes | type = dgram | raw, requires superuser privileges to update
mtu | boolean() | yes | yes | Get: Only after the socket has been connected
mtu_discover | ipv6_pmtudisc() | yes | yes | none
multicast_hops | default | uint8() | yes | yes | none
multicast_if | integer() | yes | yes | type = dgram | raw
multicast_loop | boolean() | yes | yes | none
recverr | boolean() | yes | yes | none
recvhoplimit | boolean() | yes | yes | type = dgram | raw. On some platforms (e.g. Linux), recvhoplimit is set in order to get hoplimit
recvpktinfo | pktinfo | boolean() | yes | yes | type = dgram | raw. On some platforms (e.g. FreeBSD) is used to set in order to get hoplimit as a control message heeader. On others (e.g. Linux), recvhoplimit is set in order to get hoplimit.
recvtclass | boolean() | yes | yes | type = dgram | raw. On some platforms is used to set (=true) in order to get the tclass control message heeader. On others, tclass is set in order to get tclass control message heeader.
router_alert | integer() | yes | yes | type = raw
rthdr | boolean() | yes | yes | type = dgram | raw, requires superuser privileges to update
tclass | integer() | yes | yes | Set the traffic class associated with outgoing packets. RFC3542.
unicast_hops | default | uint8() | yes | yes | none
v6only | boolean() | yes | no | none

Table: ipv6 options

Options for level tcp:

Option Name | Value Type | Set | Get | Other Requirements and comments
congestion | string() | yes | yes | none
cork | boolean() | yes | yes | 'nopush' one some platforms (FreeBSD)
keepcnt | integer() | yes | yes | On Windows (at least), it is illegal to set to
|  |  |  | a value greater than 255.
keepidle | integer() | yes | yes | none
keepintvl | integer() | yes | yes | none
maxseg | integer() | yes | yes | Set not allowed on all platforms.
nodelay | boolean() | yes | yes | none
nopush | boolean() | yes | yes | 'cork' on some platforms (Linux). On Darwin this has
|  |  |  | a different meaning than on, for instance, FreeBSD.
user_timeout | integer() >= 0 | yes | yes | none

Table: tcp options

Options for level udp:

Option Name | Value Type | Set | Get | Other Requirements and comments
cork | boolean() | yes | yes | none

Table: udp options

Options for level sctp:

Option Name | Value Type | Set | Get | Other Requirements and comments
adaption_layer | sctp_setadaption() | yes | yes | Maybe FreeBSD only
associnfo | sctp_assocparams() | yes | yes | none
autoclose | non_neg_integer() | yes | yes | none
disable_fragments | boolean() | yes | yes | none
default_send_param | sctp_snd_rcv_info() | yes | yes | none
events | sctp_event_subscribe() | yes | no | Note that not all events are
|  |  |  | supported on all platforms.
get_peer_addr_info | sctp_peer_address_info() | no | yes | Requires the assoc id and
|  |  |  | peer socket address in the
|  |  |  | form of a sparse
|  |  |  | sctp_peer_address_info() as a
|  |  |  | third argument: getopt/3
initmsg | sctp_initmsg() | yes | yes | none
i_want_mapped_v4_addr | boolean() | yes | no | none
maxseg | non_neg_integer() | yes | yes | none
nodelay | boolean() | yes | yes | none
primary_addr | sctp_set_peer_primary_address() | yes | no | none
rtoinfo | sctp_rtoinfo() | yes | yes | none
peer_addr_params | sctp_peer_address_parameters() | yes | yes | This type looks different on
|  |  |  | diffent platforms.
status | sctp_status() | no | yes | Requires the assoc id in the
|  |  |  | form of a sparse sctp_status()
|  |  |  | as a third argument: getopt/3

Table: sctp options

Socket Configure Flags

There are a couple of configure flags, that can be used when (configure and) building Erlang/OTP, which effect the functionality of the 'socket' nif.

Builtin Socket Support

Support for the builtin 'socket' (as a nif) can be explicitly enabled and disabled:

--enable-esock (default) | --disable-esock

RCVTIMEO/SNDTIMEO socket options

Support for these (socket) options has to be explicitly enabled. For details, see the specific option descriptions in the socket option table):

--enable-esock-rcvsndtimeo | --disable-esock-rcvsndtimeo (default)

Extended Error Info

The use of Extended Error Info (currently only used on Windows) can be explicitly enabled and disabled:

--enable-esock-extended-error-info (default) | --disable-esock-extended-error-info

Verbose Mutex Names

The 'socket' nif uses several mutex(s). Specifically, two for each socket; One for read and one for write. These mutex(s) are named as: esock.r[FD] & and esock.w[FD] (where FD is the file descriptor). Example: esock.r[10]. This is not normally a problem, but in some very specific debug scenarious, it can become a bottleneck. Therefor these names can be simplified to just e.g. "esock.r". (that is, all read mutex(s) have the same "name").

The use of these verbose mutex names (in the 'socket' nif) can be explicitly enabled and disabled:

--enable-esock-verbose-mtx-names (default) | --disable-esock-verbose-mtx-names

Counter Size

The 'socket' nif uses counters for various things (diagnistics and statistics). The size (in number of bits) of these counters can be explictly configured:

--with-esock-counter-size=SZ

Where SZ is one of 16 | 24 | 32 | 48 | 64. Defaults to 64.

Socket Registry

The socket registry keeps track of 'socket' sockets. This can be explicitly enabled and disabled:

--enable-esock-socket-registry (default) | --disable-esock-socket-registry

See socket registry for more info.

Logging

Erlang provides a standard API for logging through Logger, which is part of the Kernel application. Logger consists of the API for issuing log events, and a customizable backend where log handlers, filters and formatters can be plugged in.

By default, the Kernel application installs one log handler at system start. This handler is named default. It receives and processes standard log events produced by the Erlang runtime system, standard behaviours and different Erlang/OTP applications. The log events are by default written to the terminal.

You can also configure the system so that the default handler prints log events to a single file, or to a set of wrap logs via disk_log.

By configuration, you can also modify or disable the default handler, replace it by a custom handler, and install additional handlers.

Overview

A log event consists of a log level, the message to be logged, and metadata.

The Logger backend forwards log events from the API, first through a set of primary filters, then through a set of secondary filters attached to each log handler. The secondary filters are in the following named handler filters.

Each filter set consists of a log level check, followed by zero or more filter functions.

The following figure shows a conceptual overview of Logger. The figure shows two log handlers, but any number of handlers can be installed.

---
title: Conceptual Overview
---
flowchart TD
    DB[(Config DB)]
    API ---> ML[Module Level <hr> Global Level <hr> Global Filters]
    API -.Update configuration.-> DB
    ML -.-> DB
    ML ---> HL1[Handler Level <hr> Handler Filter]
    ML ---> HL2[Handler Level <hr> Handler Filter]
    HL1 ---> HC1[Handler Callback]
    HL2 ---> HC2[Handler Callback]
    HL1 -.-> DB
    HL2 -.-> DB
    subgraph Legend
        direction LR
        start1[ ] -->|Log event flow| stop1[ ]
        style start1 height:0px;
        style stop1 height:0px;
        start2[ ] -.->|Look up configuration| stop2[ ]
        style start2 height:0px;
        style stop2 height:0px;
    end

Log levels are expressed as atoms. Internally in Logger, the atoms are mapped to integer values, and a log event passes the log level check if the integer value of its log level is less than or equal to the currently configured log level. That is, the check passes if the event is equally or more severe than the configured level. See section Log Level for a listing and description of all log levels.

The primary log level can be overridden by a log level configured per module. This is to, for instance, allow more verbose logging from a specific part of the system.

Filter functions can be used for more sophisticated filtering than the log level check provides. A filter function can stop or pass a log event, based on any of the event's contents. It can also modify all parts of the log event. See section Filters for more details.

If a log event passes through all primary filters and all handler filters for a specific handler, Logger forwards the event to the handler callback. The handler formats and prints the event to its destination. See section Handlers for more details.

Everything up to and including the call to the handler callbacks is executed on the client process, that is, the process where the log event was issued. It is up to the handler implementation if other processes are involved or not.

The handlers are called in sequence, and the order is not defined.

Logger API

The API for logging consists of a set of macros, and a set of functions of the form logger:Level/1,2,3, which are all shortcuts for logger:log(Level,Arg1[,Arg2[,Arg3]]).

The macros are defined in logger.hrl, which is included in a module with the directive

-include_lib("kernel/include/logger.hrl").

The difference between using the macros and the exported functions is that macros add location (originator) information to the metadata, and performs lazy evaluation by wrapping the logger call in a case statement, so it is only evaluated if the log level of the event passes the primary log level check.

Log Level

The log level indicates the severity of a event. In accordance with the Syslog protocol, RFC 5424, eight log levels can be specified. The following table lists all possible log levels by name (atom), integer value, and description:

Level | Integer | Description
emergency | 0 | system is unusable
alert | 1 | action must be taken immediately
critical | 2 | critical conditions
error | 3 | error conditions
warning | 4 | warning conditions
notice | 5 | normal but significant conditions
info | 6 | informational messages
debug | 7 | debug-level messages

Table: Log Levels

Notice that the integer value is only used internally in Logger. In the API, you must always use the atom. To compare the severity of two log levels, use logger:compare_levels/2.

Log Message

The log message contains the information to be logged. The message can consist of a format string and arguments (given as two separate parameters in the Logger API), a string or a report.

Example, format string and arguments:

logger:error("The file does not exist: ~ts",[Filename])

Example, string:

logger:notice("Something strange happened!")

A report, which is either a map or a key-value list, is the preferred way to log using Logger as it makes it possible for different backends to filter and format the log event as it needs to.

Example, report:

?LOG_ERROR(#{ user => joe, filename => Filename, reason => enoent })

Reports can be accompanied by a report callback specified in the log event's metadata. The report callback is a convenience function that the formatter can use to convert the report to a format string and arguments, or directly to a string. The formatter can also use its own conversion function, if no callback is provided, or if a customized formatting is desired.

The report callback must be a fun with one or two arguments. If it takes one argument, this is the report itself, and the fun returns a format string and arguments:

fun((logger:report()) -> {io:format(),[term()]})

If it takes two arguments, the first is the report, and the second is a map containing extra data that allows direct conversion to a string:

fun((logger:report(),logger:report_cb_config()) -> unicode:chardata())

The fun must obey the depth and chars_limit parameters provided in the second argument, as the formatter cannot do anything useful of these parameters with the returned string. The extra data also contains a field named single_line, indicating if the printed log message may contain line breaks or not. This variant is used when the formatting of the report depends on the size or single line parameters.

Example, report, and metadata with report callback:

logger:debug(#{got => connection_request, id => Id, state => State},
             #{report_cb => fun(R) -> {"~p",[R]} end})

The log message can also be provided through a fun for lazy evaluation. The fun is only evaluated if the primary log level check passes, and is therefore recommended if it is expensive to generate the message. The lazy fun must return a string, a report, or a tuple with format string and arguments.

Metadata

Metadata contains additional data associated with a log message. Logger inserts some metadata fields by default, and the client can add custom metadata in three different ways:

Set primary metadata - Primary metadata applies is the base metadata given to all log events. At startup it can be set using the kernel configuration parameter logger_metadata. At run-time it can be set and updated using logger:set_primary_config/1 and logger:update_primary_config/1 respectively.

Set process metadata - Process metadata is set and updated with logger:set_process_metadata/1 and logger:update_process_metadata/1, respectively. This metadata applies to the process on which these calls are made, and Logger adds the metadata to all log events issued on that process.

Add metadata to a specific log event - Metadata associated with one specific log event is given as the last parameter to the log macro or Logger API function when the event is issued. For example:

?LOG_ERROR("Connection closed",#{context => server})

See the description of the logger:metadata/0 type for information about which default keys Logger inserts, and how the different metadata maps are merged.

Filters

Filters can be primary, or attached to a specific handler. Logger calls the primary filters first, and if they all pass, it calls the handler filters for each handler. Logger calls the handler callback only if all filters attached to the handler in question also pass.

A filter is defined as:

{FilterFun, Extra}

where FilterFun is a function of arity 2, and Extra is any term. When applying the filter, Logger calls the function with the log event as the first argument, and the value of Extra as the second argument. See logger:filter/0 for type definitions.

The filter function can return stop, ignore or the (possibly modified) log event.

If stop is returned, the log event is immediately discarded. If the filter is primary, no handler filters or callbacks are called. If it is a handler filter, the corresponding handler callback is not called, but the log event is forwarded to filters attached to the next handler, if any.

If the log event is returned, the next filter function is called with the returned value as the first argument. That is, if a filter function modifies the log event, the next filter function receives the modified event. The value returned from the last filter function is the value that the handler callback receives.

If the filter function returns ignore, it means that it did not recognize the log event, and thus leaves to other filters to decide the event's destiny.

The configuration option filter_default specifies the behaviour if all filter functions return ignore, or if no filters exist. filter_default is by default set to log, meaning that if all existing filters ignore a log event, Logger forwards the event to the handler callback. If filter_default is set to stop, Logger discards such events.

Primary filters are added with logger:add_primary_filter/2 and removed with logger:remove_primary_filter/1. They can also be added at system start via the Kernel configuration parameter logger.

Handler filters are added with logger:add_handler_filter/3 and removed with logger:remove_handler_filter/2. They can also be specified directly in the configuration when adding a handler with logger:add_handler/3 or via the Kernel configuration parameter logger.

To see which filters are currently installed in the system, use logger:get_config/0, or logger:get_primary_config/0 and logger:get_handler_config/1. Filters are listed in the order they are applied, that is, the first filter in the list is applied first, and so on.

For convenience, the following built-in filters exist:

logger_filters:domain/2 - Provides a way of filtering log events based on a domain field in Metadata.

logger_filters:level/2 - Provides a way of filtering log events based on the log level.

logger_filters:progress/2 - Stops or allows progress reports from supervisor and application_controller.

logger_filters:remote_gl/2 - Stops or allows log events originating from a process that has its group leader on a remote node.

Handlers

A handler is defined as a module exporting at least the following callback function:

log(LogEvent, Config) -> term()

This function is called when a log event has passed through all primary filters, and all handler filters attached to the handler in question. The function call is executed on the client process, and it is up to the handler implementation if other processes are involved or not.

Logger allows adding multiple instances of a handler callback. That is, if a callback module implementation allows it, you can add multiple handler instances using the same callback module. The different instances are identified by unique handler identities.

In addition to the mandatory callback function log/2, a handler module can export the optional callback functions adding_handler/1, changing_config/3, filter_config/1, and removing_handler/1. See logger_handler for more information about these function.

The following built-in handlers exist:

logger_std_h - This is the default handler used by OTP. Multiple instances can be started, and each instance will write log events to a given destination, terminal or file.

logger_disk_log_h - This handler behaves much like logger_std_h, except it uses disk_log as its destination.

error_logger - This handler is provided for backwards compatibility only. It is not started by default, but will be automatically started the first time an error_logger event handler is added with error_logger:add_report_handler/1,2.

The old error_logger event handlers in STDLIB and SASL still exist, but they are not added by Erlang/OTP 21.0 or later.

Formatters

A formatter can be used by the handler implementation to do the final formatting of a log event, before printing to the handler's destination. The handler callback receives the formatter information as part of the handler configuration, which is passed as the second argument to HModule:log/2.

The formatter information consist of a formatter module, FModule and its configuration, FConfig. FModule must export the following function, which can be called by the handler:

format(LogEvent,FConfig)
	-> FormattedLogEntry

The formatter information for a handler is set as a part of its configuration when the handler is added. It can also be changed during runtime with logger:set_handler_config(HandlerId,formatter,{Module,FConfig}) , which overwrites the current formatter information, or with logger:update_formatter_config/2,3, which only modifies the formatter configuration.

If the formatter module exports the optional callback function check_config(FConfig), Logger calls this function when the formatter information is set or modified, to verify the validity of the formatter configuration.

If no formatter information is specified for a handler, Logger uses logger_formatter as default. See the logger_formatter manual page for more information about this module.

Configuration

At system start, Logger is configured through Kernel configuration parameters. The parameters that apply to Logger are described in section Kernel Configuration Parameters. Examples are found in section Configuration Examples.

During runtime, Logger configuration is changed via API functions. See the logger manual page.

Primary Logger Configuration

Logger API functions that apply to the primary Logger configuration are:

get_primary_config/0

set_primary_config/1,2

update_primary_config/1

add_primary_filter/2

remove_primary_filter/1

The primary Logger configuration is a map with the following keys:

level =logger:level/0 | all | none - Specifies the primary log level, that is, log event that are equally or more severe than this level, are forwarded to the primary filters. Less severe log events are immediately discarded.

See section Log Level for a listing and description of possible log levels.

The initial value of this option is set by the Kernel configuration parameter logger_level. It is changed during runtime with logger:set_primary_config(level,Level).

Defaults to notice.

filters = [{FilterId,Filter}] - Specifies the primary filters.

FilterId = logger:filter_id/0

Filter = logger:filter/0

The initial value of this option is set by the Kernel configuration parameter logger. During runtime, primary filters are added and removed with logger:add_primary_filter/2 and logger:remove_primary_filter/1, respectively.

See section Filters for more detailed information.

Defaults to [].

filter_default = log | stop - Specifies what happens to a log event if all filters return ignore, or if no filters exist.

See section Filters for more information about how this option is used.

Defaults to log.

metadata =metadata() - The primary metadata to be used for all log calls.

See section Metadata for more information about how this option is used.

Defaults to #{}.

Handler Configuration

Logger API functions that apply to handler configuration are:

get_handler_config/0,1

set_handler_config/2,3

update_handler_config/2,3

add_handler_filter/3

remove_handler_filter/2

update_formatter_config/2,3

The configuration for a handler is a map with the following keys:

id = logger_handler:id/0 - Automatically inserted by Logger. The value is the same as the HandlerId specified when adding the handler, and it cannot be changed.

module = module() - Automatically inserted by Logger. The value is the same as the Module specified when adding the handler, and it cannot be changed.

level = logger:level/0 | all | none - Specifies the log level for the handler, that is, log events that are equally or more severe than this level, are forwarded to the handler filters for this handler.

See section Log Level for a listing and description of possible log levels.

The log level is specified when adding the handler, or changed during runtime with, for instance, logger:set_handler_config(HandlerId,level,Level).

Defaults to all.

filters = [{FilterId,Filter}] - Specifies the handler filters.

FilterId = logger:filter_id/0

Filter = logger:filter/0

Handler filters are specified when adding the handler, or added or removed during runtime with logger:add_handler_filter/3 and logger:remove_handler_filter/2, respectively.

See Filters for more detailed information.

Defaults to [].

filter_default = log | stop - Specifies what happens to a log event if all filters return ignore, or if no filters exist.

See section Filters for more information about how this option is used.

Defaults to log.

formatter = {FormatterModule,FormatterConfig} - Specifies a formatter that the handler can use for converting the log event term to a printable string.

FormatterModule = module()

FormatterConfig = logger:formatter_config/0

The formatter information is specified when adding the handler. The formatter configuration can be changed during runtime with logger:update_formatter_config/2,3, or the complete formatter information can be overwritten with, for instance, logger:set_handler_config/3.

See section Formatters for more detailed information.

Defaults to {logger_formatter,DefaultFormatterConfig}. See the logger_formatter manual page for information about this formatter and its default configuration.

config = term() - Handler specific configuration, that is, configuration data related to a specific handler implementation.

The configuration for the built-in handlers is described in the logger_std_h and logger_disk_log_h manual pages.

Notice that level and filters are obeyed by Logger itself before forwarding the log events to each handler, while formatter and all handler specific options are left to the handler implementation.

Kernel Configuration Parameters

The following Kernel configuration parameters apply to Logger:

logger = [Config] - Specifies the configuration for Logger, except the primary log level, which is specified with logger_level, and the compatibility with SASL Error Logging, which is specified with logger_sasl_compatible.

With this parameter, you can modify or disable the default handler, add custom handlers and primary logger filters, set log levels per module, and modify the proxy configuration.

Config is any (zero or more) of the following:

{handler, default, undefined} - Disables the default handler. This allows another application to add its own default handler.

Only one entry of this type is allowed.

{handler, HandlerId, Module, HandlerConfig} - If HandlerId is default, then this entry modifies the default handler, equivalent to calling

logger:remove_handler(default)

followed by

logger:add_handler(default, Module, HandlerConfig)

For all other values of HandlerId, this entry adds a new handler, equivalent to calling

logger:add_handler(HandlerId, Module, HandlerConfig)

Multiple entries of this type are allowed.

{filters, FilterDefault, [Filter]} - Adds the specified primary filters.

FilterDefault = log | stop

Filter = {FilterId, {FilterFun, FilterConfig}}

Equivalent to calling

logger:add_primary_filter(FilterId, {FilterFun, FilterConfig})

for each Filter.

FilterDefault specifies the behaviour if all primary filters return ignore, see section Filters.

Only one entry of this type is allowed.

{module_level, Level, [Module]} - Sets module log level for the given modules. Equivalent to calling

logger:set_module_level(Module, Level)

for each Module.

Multiple entries of this type are allowed.

{proxy, ProxyConfig} - Sets the proxy configuration, equivalent to calling

logger:set_proxy_config(ProxyConfig)

Only one entry of this type is allowed.

See section Configuration Examples for examples using the logger parameter for system configuration.

logger_metadata = map() - Specifies the primary metadata. See the kernel(6) manual page for more information about this parameter.

logger_level = Level - Specifies the primary log level. See the kernel(6) manual page for more information about this parameter.

logger_sasl_compatible = true | false - Specifies Logger's compatibility with SASL Error Logging. See the kernel(6) manual page for more information about this parameter.

Configuration Examples

The value of the Kernel configuration parameter logger is a list of tuples. It is possible to write the term on the command line when starting an erlang node, but as the term grows, a better approach is to use the system configuration file. See the config(4) manual page for more information about this file.

Each of the following examples shows a simple system configuration file that configures Logger according to the description.

Modify the default handler to print to a file instead of standard_io:

[{kernel,
  [{logger,
    [{handler, default, logger_std_h,  % {handler, HandlerId, Module,
      #{config => #{file => "log/erlang.log"}}}  % Config}
    ]}]}].

Modify the default handler to print each log event as a single line:

[{kernel,
  [{logger,
    [{handler, default, logger_std_h,
      #{formatter => {logger_formatter, #{single_line => true}}}}
    ]}]}].

Modify the default handler to print the pid of the logging process for each log event:

[{kernel,
  [{logger,
    [{handler, default, logger_std_h,
      #{formatter => {logger_formatter,
                        #{template => [time," ",pid," ",msg,"\n"]}}}}
    ]}]}].

Modify the default handler to only print errors and more severe log events to "log/erlang.log", and add another handler to print all log events to "log/debug.log".

[{kernel,
  [{logger,
    [{handler, default, logger_std_h,
      #{level => error,
        config => #{file => "log/erlang.log"}}},
     {handler, info, logger_std_h,
      #{level => debug,
        config => #{file => "log/debug.log"}}}
    ]}]}].

Backwards Compatibility with error_logger

Logger provides backwards compatibility with error_logger in the following ways:

API for Logging - The error_logger API still exists, but should only be used by legacy code. It will be removed in a later release.

Calls to error_logger:error_report/1,2, error_logger:error_msg/1,2, and corresponding functions for warning and info messages, are all forwarded to Logger as calls to logger:log(Level,Report,Metadata).

Level = error | warning | info and is taken from the function name. Report contains the actual log message, and Metadata contains additional information which can be used for creating backwards compatible events for legacy error_logger event handlers, see section Legacy Event Handlers.

Output Format - To get log events on the same format as produced by error_logger_tty_h and error_logger_file_h, use the default formatter, logger_formatter, with configuration parameter legacy_header set to true. This is the default configuration of the default handler started by Kernel.

Default Format of Log Events from OTP - By default, all log events originating from within OTP, except the former so called "SASL reports", look the same as before.

SASL Reports - By SASL reports we mean supervisor reports, crash reports and progress reports.

Prior to Erlang/OTP 21.0, these reports were only logged when the SASL application was running, and they were printed through SASL's own event handlers sasl_report_tty_h and sasl_report_file_h.

The destination of these log events was configured by SASL configuration parameters.

Due to the specific event handlers, the output format slightly differed from other log events.

As of Erlang/OTP 21.0, the concept of SASL reports is removed, meaning that the default behaviour is as follows:

Supervisor reports, crash reports, and progress reports are no longer connected to the SASL application.

Supervisor reports and crash reports are issued as error level log events, and are logged through the default handler started by Kernel.

Progress reports are issued as info level log events, and since the default primary log level is notice, these are not logged by default. To enable printing of progress reports, set the primary log level to info.

The output format is the same for all log events.

If the old behaviour is preferred, the Kernel configuration parameter logger_sasl_compatible can be set to true. The SASL configuration parameters can then be used as before, and the SASL reports will only be printed if the SASL application is running, through a second log handler named sasl.

All SASL reports have a metadata field domain which is set to [otp,sasl]. This field can be used by filters to stop or allow the log events.

See section SASL User's Guide for more information about the old SASL error logging functionality.

Legacy Event Handlers - To use event handlers written for error_logger, just add your event handler with

error_logger:add_report_handler/1,2.

This automatically starts the error logger event manager, and adds error_logger as a handler to Logger, with the following configuration:

#{level => info,
  filter_default => log,
  filters => []}.

Note

This handler ignores events that do not originate from the error_logger API, or from within OTP. This means that if your code uses the Logger API for logging, then your log events will be discarded by this handler.

The handler is not overload protected.

Error Handling

Logger does, to a certain extent, check its input data before forwarding a log event to filters and handlers. It does, however, not evaluate report callbacks, or check the validity of format strings and arguments. This means that all filters and handlers must be careful when formatting the data of a log event, making sure that it does not crash due to bad input data or faulty callbacks.

If a filter or handler still crashes, Logger will remove the filter or handler in question from the configuration, and print a short error message to the terminal. A debug event containing the crash reason and other details is also issued.

See section Log Message for more information about report callbacks and valid forms of log messages.

Example: Add a handler to log info events to file

When starting an Erlang node, the default behaviour is that all log events on level notice or more severe, are logged to the terminal via the default handler. To also log info events, you can either change the primary log level to info:

1> logger:set_primary_config(level, info).
ok

or set the level for one or a few modules only:

2> logger:set_module_level(mymodule, info).
ok

This allows info events to pass through to the default handler, and be printed to the terminal as well. If there are many info events, it can be useful to print these to a file instead.

First, set the log level of the default handler to notice, preventing it from printing info events to the terminal:

3> logger:set_handler_config(default, level, notice).
ok

Then, add a new handler which prints to file. You can use the handler module logger_std_h, and configure it to log to file:

4> Config = #{config => #{file => "./info.log"}, level => info}.
#{config => #{file => "./info.log"},level => info}
5> logger:add_handler(myhandler, logger_std_h, Config).
ok

Since filter_default defaults to log, this handler now receives all log events. If you want info events only in the file, you must add a filter to stop all non-info events. The built-in filter logger_filters:level/2 can do this:

6> logger:add_handler_filter(myhandler, stop_non_info,
                             {fun logger_filters:level/2, {stop, neq, info}}).
ok

See section Filters for more information about the filters and the filter_default configuration parameter.

Example: Implement a handler

logger_handler describes the callback functions that can be implemented for a Logger handler.

A handler callback module must export:

log(Log, Config)

It can optionally also export some, or all, of the following:

adding_handler(Config)

removing_handler(Config)

changing_config(SetOrUpdate, OldConfig, NewConfig)

filter_config(Config)

When a handler is added, by for example a call to logger:add_handler(Id, HModule, Config), Logger first calls HModule:adding_handler(Config). If this function returns {ok,Config1}, Logger writes Config1 to the configuration database, and the logger:add_handler/3 call returns. After this, the handler is installed and must be ready to receive log events as calls to HModule:log/2.

A handler can be removed by calling logger:remove_handler(Id). Logger calls HModule:removing_handler(Config), and removes the handler's configuration from the configuration database.

When logger:set_handler_config/2,3 or logger:update_handler_config/2,3 is called, Logger calls HModule:changing_config(SetOrUpdate, OldConfig, NewConfig). If this function returns {ok,NewConfig1}, Logger writes NewConfig1 to the configuration database.

When logger:get_config/0 or logger:get_handler_config/0,1 is called, Logger calls HModule:filter_config(Config). This function must return the handler configuration where internal data is removed.

A simple handler that prints to the terminal can be implemented as follows:

-module(myhandler1).
-export([log/2]).

log(LogEvent, #{formatter := {FModule, FConfig}}) ->
    io:put_chars(FModule:format(LogEvent, FConfig)).

Notice that the above handler does not have any overload protection, and all log events are printed directly from the client process.

For information and examples of overload protection, please refer to section Protecting the Handler from Overload, and the implementation of logger_std_h and logger_disk_log_h .

The following is a simpler example of a handler which logs to a file through one single process:

-module(myhandler2).
-export([adding_handler/1, removing_handler/1, log/2]).
-export([init/1, handle_call/3, handle_cast/2, terminate/2]).

adding_handler(Config) ->
    MyConfig = maps:get(config,Config,#{file => "myhandler2.log"}),
    {ok, Pid} = gen_server:start(?MODULE, MyConfig, []),
    {ok, Config#{config => MyConfig#{pid => Pid}}}.

removing_handler(#{config := #{pid := Pid}}) ->
    gen_server:stop(Pid).

log(LogEvent,#{config := #{pid := Pid}} = Config) ->
    gen_server:cast(Pid, {log, LogEvent, Config}).

init(#{file := File}) ->
    {ok, Fd} = file:open(File, [append, {encoding, utf8}]),
    {ok, #{file => File, fd => Fd}}.

handle_call(_, _, State) ->
    {reply, {error, bad_request}, State}.

handle_cast({log, LogEvent, Config}, #{fd := Fd} = State) ->
    do_log(Fd, LogEvent, Config),
    {noreply, State}.

terminate(_Reason, #{fd := Fd}) ->
    _ = file:close(Fd),
    ok.

do_log(Fd, LogEvent, #{formatter := {FModule, FConfig}}) ->
    String = FModule:format(LogEvent, FConfig),
    io:put_chars(Fd, String).

Protecting the Handler from Overload

The default handlers, logger_std_h and logger_disk_log_h, feature multiple overload protection mechanisms, which make it possible for the handlers to survive, and stay responsive, during periods of high load (when huge numbers of incoming log requests must be handled).

The mechanisms are as follows:

message queue length: the handler process tracks its message queue length and takes actions depending on its size, from turning on a sync mode to dropping messages.

limit the number of logs emitted: the handlers will handle a maximum number of log events per time unit, defaulting to 500 per second.

terminate an overloaded handler: a handler can be terminated and restarted automatically if it exceeds message queue length or memory thresholds - this is disabled by default.

These mechanisms are described in more detail in the following sections.

Message Queue Length

The handler process keeps track of the length of its message queue and takes some form of action when the current length exceeds a configurable threshold. The purpose is to keep the handler in, or to as quickly as possible get the handler into, a state where it can keep up with the pace of incoming log events. The memory use of the handler must never grow larger and larger, since that will eventually cause the handler to crash. These three thresholds, with associated actions, exist:

sync_mode_qlen - As long as the length of the message queue is lower than this value, all log events are handled asynchronously. This means that the client process sending the log event, by calling a log function in the Logger API, does not wait for a response from the handler but continues executing immediately after the event is sent. It is not affected by the time it takes the handler to print the event to the log device. If the message queue grows larger than this value, the handler starts handling log events synchronously instead, meaning that the client process sending the event must wait for a response. When the handler reduces the message queue to a level below the sync_mode_qlen threshold, asynchronous operation is resumed. The switch from asynchronous to synchronous mode can slow down the logging tempo of one, or a few, busy senders, but cannot protect the handler sufficiently in a situation of many busy concurrent senders.

Defaults to 10 messages.

drop_mode_qlen - When the message queue grows larger than this threshold, the handler switches to a mode in which it drops all new events that senders want to log. Dropping an event in this mode means that the call to the log function never results in a message being sent to the handler, but the function returns without taking any action. The handler keeps logging the events that are already in its message queue, and when the length of the message queue is reduced to a level below the threshold, synchronous or asynchronous mode is resumed. Notice that when the handler activates or deactivates drop mode, information about it is printed in the log. The emitted log message is on the :notice level and looks like this: Handler :default switched from :sync to :drop mode

Defaults to 200 messages.

flush_qlen - If the length of the message queue grows larger than this threshold, a flush (delete) operation takes place. To flush events, the handler discards the messages in the message queue by receiving them in a loop without logging. Client processes waiting for a response from a synchronous log request receive a reply from the handler indicating that the request is dropped. The handler process increases its priority during the flush loop to make sure that no new events are received during the operation. Notice that after the flush operation is performed, the handler prints information in the log about how many events have been deleted. The emitted log message is on the :notice level and looks like this: Handler :default flushed 1070 log events

Defaults to 1000 messages.

For the overload protection algorithm to work properly, it is required that:

sync_mode_qlen =< drop_mode_qlen =< flush_qlen

and that:

drop_mode_qlen > 1

To disable certain modes, do the following:

If sync_mode_qlen is set to 0, all log events are handled synchronously. That is, asynchronous logging is disabled.

If sync_mode_qlen is set to the same value as drop_mode_qlen, synchronous mode is disabled. That is, the handler always runs in asynchronous mode, unless dropping or flushing is invoked.

If drop_mode_qlen is set to the same value as flush_qlen, drop mode is disabled and can never occur.

During high load scenarios, the length of the handler message queue rarely grows in a linear and predictable way. Instead, whenever the handler process is scheduled in, it can have an almost arbitrary number of messages waiting in the message queue. It is for this reason that the overload protection mechanism is focused on acting quickly, and quite drastically, such as immediately dropping or flushing messages, when a large queue length is detected.

The values of the previously listed thresholds can be specified by the user. This way, a handler can be configured to, for example, not drop or flush messages unless the message queue length of the handler process grows extremely large. Notice that large amounts of memory can be required for the node under such circumstances. Another example of user configuration is when, for performance reasons, the client processes must never be blocked by synchronous log requests. It is possible, perhaps, that dropping or flushing events is still acceptable, since it does not affect the performance of the client processes sending the log events.

A configuration example:

logger:add_handler(my_standard_h, logger_std_h,
                   #{config => #{file => "./system_info.log",
                                 sync_mode_qlen => 100,
                                 drop_mode_qlen => 1000,
                                 flush_qlen => 2000}}).

Controlling Bursts of Log Requests

Large bursts of log events - many events received by the handler under a short period of time - can potentially cause problems, such as:

Log files grow very large, very quickly.

Circular logs wrap too quickly so that important data is overwritten.

Write buffers grow large, which slows down file sync operations.

Note that these examples apply to file-based logging. If you're logging to the console the protections discussed below should be safe to disable or tweak, as long as your system can handle the load of them.

For this reason, both built-in handlers offer the possibility to specify the maximum number of events to be handled within a certain time frame. With this burst control feature enabled, the handler can avoid choking the log with massive amounts of printouts. The configuration parameters are:

burst_limit_enable - Value true enables burst control and false disables it.

Defaults to true.

burst_limit_max_count - This is the maximum number of events to handle within a burst_limit_window_time time frame. After the limit is reached, successive events are dropped until the end of the time frame.

Defaults to 500 events.

burst_limit_window_time - See the previous description of burst_limit_max_count.

Defaults to 1000 milliseconds.

A configuration example:

logger:add_handler(my_disk_log_h, logger_disk_log_h,
                   #{config => #{file => "./my_disk_log",
                                 burst_limit_enable => true,
                                 burst_limit_max_count => 20,
                                 burst_limit_window_time => 500}}).

Terminating an Overloaded Handler

It is possible that a handler, even if it can successfully manage peaks of high load without crashing, can build up a large message queue, or use a large amount of memory. The overload protection mechanism includes an automatic termination and restart feature for the purpose of guaranteeing that a handler does not grow out of bounds. The feature is configured with the following parameters:

overload_kill_enable - Value true enables the feature and false disables it.

Defaults to false.

overload_kill_qlen - This is the maximum allowed queue length. If the message queue grows larger than this, the handler process is terminated.

Defaults to 20000 messages.

overload_kill_mem_size - This is the maximum memory size that the handler process is allowed to use. If the handler grows larger than this, the process is terminated.

Defaults to 3000000 bytes.

overload_kill_restart_after - If the handler is terminated, it restarts automatically after a delay specified in milliseconds. The value infinity prevents restarts.

Defaults to 5000 milliseconds.

If the handler process is terminated because of overload, it prints information about it in the log. It also prints information about when a restart has taken place, and the handler is back in action.

Note

The sizes of the log events affect the memory needs of the handler. For information about how to limit the size of log events, see the logger_formatter manual page.

Logger Proxy

The Logger proxy is an Erlang process which is part of the Kernel application's supervision tree. During startup, the proxy process registers itself as the system_logger, meaning that log events produced by the emulator are sent to this process.

When a log event is issued on a process which has its group leader on a remote node, Logger automatically forwards the log event to the group leader's node. To achieve this, it first sends the log event as an Erlang message from the original client process to the proxy on the local node, and the proxy in turn forwards the event to the proxy on the remote node.

When receiving a log event, either from the emulator or from a remote node, the proxy calls the Logger API to log the event.

The proxy process is overload protected in the same way as described in section Protecting the Handler from Overload, but with the following default values:

    #{sync_mode_qlen => 500,
      drop_mode_qlen => 1000,
      flush_qlen => 5000,
      burst_limit_enable => false,
      overload_kill_enable => false}

For log events from the emulator, synchronous message passing mode is not applicable, since all messages are passed asynchronously by the emulator. Drop mode is achieved by setting the system_logger to undefined, forcing the emulator to drop events until it is set back to the proxy pid again.

The proxy uses erlang:send_nosuspend/2 when sending log events to a remote node. If the message could not be sent without suspending the sender, it is dropped. This is to avoid blocking the proxy process.

See Also

disk_log, erlang, error_logger, logger, logger_disk_log_h, logger_filters, logger_formatter, logger_std_h, sasl(6)

Logging Cookbook

Using and especially configuring Logger can be difficult at times as there are many different options that can be changed and often more than one way to achieve the same result. This User's Guide tries to help by giving many different examples of how you can use logger.

For more examples of practical use-cases of using Logger, Fred Hebert's blog post Erlang/OTP 21's new logger is a great starting point.

Note

If you find that some common Logger usage is missing from this guide, please open a pull request on github with the suggested addition

Get Logger information

Print the primary Logger configurations.

1> logger:i(primary).
Primary configuration:
    Level: notice
    Filter Default: log
    Filters:
        (none)

It is also possible to fetch the configuration using logger:get_primary_config().

See also

logger:i()

Configuration in the Logging User's Guide

Print the configuration of all handlers.

2> logger:i(handlers).
Handler configuration:
    Id: default
        Module: logger_std_h
        Level:  all
        Formatter:
            Module: logger_formatter
            Config:
                legacy_header: true
                single_line: false
        Filter Default: stop
        Filters:
            Id: remote_gl
                Fun: fun logger_filters:remote_gl/2
                Arg: stop
            Id: domain
                Fun: fun logger_filters:domain/2
                Arg: {log,super,[otp,sasl]}
            Id: no_domain
                Fun: fun logger_filters:domain/2
                Arg: {log,undefined,[]}
        Handler Config:
            burst_limit_enable: true
            burst_limit_max_count: 500
            burst_limit_window_time: 1000
            drop_mode_qlen: 200
            filesync_repeat_interval: no_repeat
            flush_qlen: 1000
            overload_kill_enable: false
            overload_kill_mem_size: 3000000
            overload_kill_qlen: 20000
            overload_kill_restart_after: 5000
            sync_mode_qlen: 10
            type: standard_io

You can also print the configuration of a specific handler using logger:i(HandlerName), or fetch the configuration using logger:get_handler_config(), or logger:get_handler_config(HandlerName) for a specific handler.

See also

logger:i()

Configuration in the Logging User's Guide

Configure the Logger

Where did my progress reports go?

In OTP-21 the default primary log level is notice. The means that many log messages are by default not printed. This includes the progress reports of supervisors. In order to get progress reports you need to raise the primary log level to info

$ erl -kernel logger_level info
=PROGRESS REPORT==== 4-Nov-2019::16:33:11.742069 ===
    application: kernel
    started_at: nonode@nohost
=PROGRESS REPORT==== 4-Nov-2019::16:33:11.746546 ===
    application: stdlib
    started_at: nonode@nohost
Eshell V10.5.3  (abort with ^G)
1>

Configure Logger formatter

In order to fit better into your existing logging infrastructure Logger can format its logging messages any way you want to. Either you can use the built-in formatter, or you can build your own.

Single line configuration

Since single line logging is the default of the built-in formatter you only have to provide the empty map as the configuration. The example below uses the sys.config to change the formatter configuration.

$ cat sys.config
[{kernel,
  [{logger,
    [{handler, default, logger_std_h,
      #{ formatter => {logger_formatter, #{ }}}}]}]}].
$ erl -config sys
Eshell V10.5.1  (abort with ^G)
1> logger:error("Oh noes, an error").
1962-10-03T11:07:47.466763-04:00 error: Oh noes, an error

However, if you just want to change it for the current session you can also do that.

1> logger:set_handler_config(default, formatter, {logger_formatter, #{}}).
ok
2> logger:error("Oh noes, another error").
1962-10-04T15:34:02.648713-04:00 error: Oh noes, another error

See also

logger_formatter's Configuration

Formatters in the Logging User's Guide

logger:set_handler_config/3

Add file and line number to log entries

You can change what is printed to the log by using the formatter template:

$ cat sys.config
[{kernel,
  [{logger,
    [{handler, default, logger_std_h,
      #{ formatter => {logger_formatter,
        #{ template => [time," ", file,":",line," ",level,": ",msg,"\n"] }}}}]}]}].
$ erl -config sys
Eshell V10.5.1  (abort with ^G)
1> logger:error("Oh noes, more errors",#{ file => "shell.erl", line => 1 }).
1962-10-05T07:37:44.104241+02:00 shell.erl:1 error: Oh noes, more errors

Note that file and line have to be added in the metadata by the caller of logger:log/3 as otherwise Logger will not know from where it was called. The file and line number are automatically added if you use the ?LOG_ERROR macros in kernel/include/logger.hrl.

See also

logger_formatter's Configuration

logger_formatter's Template

Logger Macros

Metadata in the Logging User's Guide

Configuring handlers

Print logs to a file

Instead of printing the logs to stdout we print them to a rotating file log.

$ cat sys.config
[{kernel,
  [{logger,
    [{handler, default, logger_std_h,
      #{ config => #{ file => "log/erlang.log",
                      max_no_bytes => 4096,
                      max_no_files => 5},
         formatter => {logger_formatter, #{}}}}]}]}].
$ erl -config sys
Eshell V10.5.1  (abort with ^G)
1> logger:error("Oh noes, even more errors").
ok
2> erlang:halt().
$ cat log/erlang.log
2019-10-07T11:47:16.837958+02:00 error: Oh noes, even more errors

See also

logger_std_h

Handlers in the Logging User's Guide

Debug only handler

Add a handler that prints debug log events to a file, while the default handler prints only up to notice level events to standard out.

$ cat sys.config
[{kernel,
  [{logger_level, all},
   {logger,
    [{handler, default, logger_std_h,
      #{ level => notice }},
     {handler, debug, logger_std_h,
      #{ filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
         config => #{ file => "log/debug.log" } }}
    ]}]}].
$ erl -config sys
Eshell V10.5.1  (abort with ^G)
1> logger:error("Oh noes, even more errors").
=ERROR REPORT==== 9-Oct-2019::14:40:54.784162 ===
Oh noes, even more errors
ok
2> logger:debug("A debug event").
ok
3> erlang:halt().
$ cat log/debug.log
2019-10-09T14:41:03.680541+02:00 debug: A debug event

In the configuration above we first raise the primary log level to max in order for the debug log events to get to the handlers. Then we configure the default handler to only log notice and below events, the default log level for a handler is all. Then the debug handler is configured with a filter to stop any log message that is not a debug level message.

It is also possible to do the same changes in an already running system using the logger module. Then you do like this:

$ erl
1> logger:set_handler_config(default, level, notice).
ok
2> logger:add_handler(debug, logger_std_h, #{
  filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
  config => #{ file => "log/debug.log" } }).
ok
3> logger:set_primary_config(level, all).
ok

It is important that you do not raise the primary log level before adjusting the default handler's level as otherwise your standard out may be flooded by debug log messages.

See also

logger_std_h

Filters in the Logging User's Guide

Logging

What to log and how

The simplest way to log something is by using the Logger macros and give a report to the macro. For example if you want to log an error:

?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP }).

This will print the following in the default log:

=ERROR REPORT==== 10-Oct-2019::12:13:10.089073 ===
    dst: {8,8,4,4}
    src: {8,8,8,8}
    status: 418
    what: http_error

or the below if you use a single line formatter:

2019-10-10T12:14:11.921843+02:00 error: dst: {8,8,4,4}, src: {8,8,8,8}, status: 418, what: http_error

See also

Log Message in the Logging User's Guide

Report call-backs and printing of events

If you want to do structured logging, but still want to have some control of how the final log message is formatted you can give a report_cb as part of the metadata with your log event.

ReportCB = fun(#{ what := What, status := Status, src := Src, dst := Dst }) ->
                   {ok, #hostent{ h_name = SrcName }} = inet:gethostbyaddr(Src),
                   {ok, #hostent{ h_name = DstName }} = inet:gethostbyaddr(Dst),
                   {"What: ~p~nStatus: ~p~nSrc: ~s (~s)~nDst: ~s (~s)~n",
                    [What, Status, inet:ntoa(Src), SrcName, inet:ntoa(Dst), DstName]}
           end,
?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP },
           #{ report_cb => ReportCB }).

This will print the following:

=ERROR REPORT==== 10-Oct-2019::13:29:02.230863 ===
What: http_error
Status: 418
Src: 8.8.8.8 (dns.google)
Dst: 192.121.151.106 (erlang.org)

Note that the order that things are printed have changed, and also I added a reverse-dns lookup of the IP address. This will not print as nicely when using a single line formatter, however you can also use a report_cb fun with 2 arguments where the second argument is the formatting options.

See also

Log Message in the Logging User's Guide

Logger Report Callbacks

Filters

Filters are used to remove or change log events before they reach the handlers.

Process filters

If we only want debug messages from a specific process it is possible to do this with a filter like this:

%% Initial setup to use a filter for the level filter instead of the primary level
PrimaryLevel = maps:get(level, logger:get_primary_config()),
ok = logger:add_primary_filter(primary_level,
    {fun logger_filters:level/2, {log, gteq, PrimaryLevel}}),
logger:set_primary_config(filter_default, stop),
logger:set_primary_config(level, all),

%% Test that things work as they should
logger:notice("Notice should be logged"),
logger:debug("Should not be logged"),

%% Add the filter to allow PidToLog to send debug events
PidToLog = self(),
PidFilter = fun(LogEvent, _) when PidToLog =:= self() -> LogEvent;
               (_LogEvent, _) -> ignore end,
ok = logger:add_primary_filter(pid, {PidFilter,[]}),
logger:debug("Debug should be logged").

There is a bit of setup needed to allow filters to decide whether a specific process should be allowed to log. This is because the default primary log level is notice and it is enforced before the primary filters. So in order for the pid filter to be useful we have to raise the primary log level to all and then add a level filter that only lets certain messages at or greater than notice through. When the setup is done, it is simple to add a filter that allows a certain pid through.

Note that doing the primary log level filtering through a filter and not through the level is quite a lot more expensive, so make sure to test that your system can handle the extra load before you enable it on a production node.

See also

Filters in the Logging User's Guide

logger_filters:level/2

logger:set_primary_config/2

Domains

Domains are used to specify which subsystem a certain log event originates from. The default handler will by default only log events with the domain [otp] or without a domain. If you would like to include SSL log events into the default handler log you could do this:

1> logger:add_handler_filter(default,ssl_domain,
  {fun logger_filters:domain/2,{log,sub,[otp,ssl]}}).
2> application:ensure_all_started(ssl).
{ok,[crypto,asn1,public_key,ssl]}
3> ssl:connect("www.erlang.org",443,[{log_level,debug}]).
%% lots of text

See also

Filters in the Logging User's Guide

logger_filters:domain/2

logger:set_primary_config/2

EEP-48: Documentation storage and format

This User's Guide describes the documentation storage format initially described in EEP-48. By standardizing how API documentation is stored, it will be possible to write tools that work across languages.

To fetch the EEP-48 documentation for a module, use code:get_doc/1.

To render the EEP-48 documentation for an Erlang module, use shell_docs:render/2.

The "Docs" storage

To look for documentation for a module named example, a tool should:

Look for example.beam in the code path, parse the BEAM file, and retrieve the Docs chunk. If the chunk is not available, it should look for "example.beam" in the code path and find the doc/chunks/example.chunk file in the application that defines the example module. If no .chunk file exists, documentation is not available.

The choice of using a chunk or the filesystem is completely up to the language or library. In both cases, the documentation can be added or removed at any moment by stripping the Docs chunk (using beam_lib) or by removing the doc/chunks directory.

For example, languages such as Elixir and LFE attach the Docs chunk at compilation time, which can be controlled via a compiler flag, while other languages might want to generate the documentation separate from the compilation of the source code.

The "Docs" format

In both storages, the documentation is written in the exactly same format: an Erlang term serialized to binary via term_to_binary/1. The term can be optionally compressed when serialized. It must follow the type specification below:

{docs_v1,
 Anno :: erl_anno:anno(),
 BeamLanguage :: atom(),
 Format :: binary(),
 ModuleDoc :: #{DocLanguage := DocValue} | none | hidden,
 Metadata :: map(),
 Docs ::
   [{{Kind, Name, Arity},
     Anno :: erl_anno:anno(),
     Signature :: [binary()],
     Doc :: #{DocLanguage := DocValue} | none | hidden,
     Metadata :: map()
    }]} when DocLanguage :: binary(),
             DocValue :: binary() | term()

where in the root tuple we have:

Anno - annotation (line, column, file) of the module documentation (see erl_anno)

BeamLanguage - an atom representing the language, for example: erlang, elixir, lfe, alpaca, and so on

Format - the mime type of the documentation, such as <<"text/markdown">> or <<"application/erlang+html">>. For details of the format used by Erlang see the EEP-48 Chapter in EDoc's User's Guide.

ModuleDoc - a map with the documentation language as key, such as <<"en">> or <<"pt_BR">>, and the documentation as a binary value. It can be atom none if no documentation exists or the atom hidden if documentation has been explicitly disabled for this entry.

Metadata - a map of atom keys with any term as value. This can be used to add annotations like the authors of a module, deprecated, or anything else a language or documentation tool finds relevant.

Docs - a list of documentation for other entities (such as functions and types) in the module.

For each entry in Docs, we have:

{Kind, Name, Arity} - the kind, name and arity identifying the function, callback, type, and so on. The official entities are: function, type, and callback. Other languages will add their own. For instance, Elixir and LFE might add macro.

Anno - annotation (line, column, file) of the documentation entry (see erl_anno).

Signature - the signature of the entity. It is is a list of binaries. Each entry represents a binary in the signature that can be joined with whitespace or newline. For example, [<<"binary_to_atom(Binary, Encoding)">>, <<"when is_binary(Binary)">>] can be rendered as a single line or two lines. It exists exclusively for exhibition purposes.

Doc - a map with the documentation language as key, such as <<"en">> or <<"pt_BR">>, and the documentation as a value. The documentation can either be a binary or any Erlang term, both described by Format. If it is an Erlang term, then Format must be <<"application/erlang+SUFFIX">>, such as <<"application/erlang+html">> when the documentation is an Erlang representation of an HTML document. Doc can also be atom none if no documentation exists or the atom hidden if documentation has been explicitly disabled for this entry.

Metadata - a map of atom keys with any term as value.

This shared format is the heart of the EEP as it is what effectively allows cross-language collaboration.

The Metadata field exists to allow languages, tools, and libraries to add custom information to each entry. This EEP documents the following metadata keys:

authors := [binary()] - a list of authors as binaries.

behaviours := [module()] - a list of the behaviours implemented by this module.

cross_references := [module() | {module(), {Kind, Name, Arity}}] - a list of modules or module entries that can be used as cross references when generating documentation.

deprecated := binary() - when present, it means the current entry is deprecated with a binary that represents the reason for deprecation and a recommendation to replace the deprecated code.

group := binary() - when present, it allows tooling, such as shell autocompletion and documentation generators, to list all entries within the same group together, often using the group name as an indicator. It currently only applies to doc entries, not for module metadata.

since := binary() - a binary representing the version such entry was added, such as <<"1.3.0">> or <<"20.0">>.

source_annos := [erl_anno:anno()] - a list of source code locations. You may either store one for each clause or only for the first clause.

source_path := file:filename() - the absolute location of the source file for this module. Applies only to the module metadata.

Any key may be added to Metadata at any time. Keys that are frequently used by the community can be standardized in future versions.

See Also

erl_anno, shell_docs, EEP-48 Chapter in EDoc's User's Guide, code:get_doc/1

app

Application resource file.

Description

The application resource file specifies the resources an application uses, and how the application is started. There must always be one application resource file called Application.app for each application Application in the system.

The file is read by the application controller when an application is loaded/started. It is also used by the functions in systools, for example when generating start scripts.

File Syntax

The application resource file is to be called Application.app, where Application is the application name. The file is to be located in directory ebin for the application.

The file must contain a single Erlang term, which is called an application specification:

{application, Application,
  [{description,  Description},
   {id,           Id},
   {vsn,          Vsn},
   {modules,      Modules},
   {maxP,         MaxP},
   {maxT,         MaxT},
   {registered,   Names},
   {included_applications, Apps},
   {optional_applications, Apps},
   {applications, Apps},
   {env,          Env},
   {mod,          Start},
   {start_phases, Phases},
   {runtime_dependencies, RTDeps}]}.

             Value                Default
             -----                -------
Application  atom()               -
Description  string()             ""
Id           string()             ""
Vsn          string()             ""
Modules      [Module]             []
MaxP         int()                infinity
MaxT         int()                infinity
Names        [Name]               []
Apps         [App]                []
Env          [{Par,Val}]          []
Start        {Module,StartArgs}   []
Phases       [{Phase,PhaseArgs}]  undefined
RTDeps       [ApplicationVersion] []

Module = Name = App = Par = Phase = atom()
Val = StartArgs = PhaseArgs = term()
ApplicationVersion = string()

Application - Application name.

For the application controller, all keys are optional. The respective default values are used for any omitted keys.

The functions in systools require more information. If they are used, the following keys are mandatory:

description

vsn

modules

registered

applications

The other keys are ignored by systools.

description - A one-line description of the application.

id - Product identification, or similar.

vsn - Version of the application.

modules - All modules introduced by this application. systools uses this list when generating start scripts and tar files. A module can only be defined in one application.

maxP - Deprecated - is ignored

Maximum number of processes allowed in the application.

maxT - Maximum time, in milliseconds, that the application is allowed to run. After the specified time, the application terminates automatically.

registered - All names of registered processes started in this application. systools uses this list to detect name clashes between different applications.

included_applications - All applications included by this application. When this application is started, all included applications are loaded automatically, but not started, by the application controller. It is assumed that the top-most supervisor of the included application is started by a supervisor of this application.

applications - All applications that must be started before this application. If an application is also listed in optional_applications, then the application is not required to exist (but if it exists, it is also guaranteed to be started before this one).

systools uses this list to generate correct start scripts. Defaults to the empty list, but notice that all applications have dependencies to (at least) Kernel and STDLIB.

optional_applications - A list of applications that are optional. Note if you want an optional dependency to be automatically started before the current application whenever it is available, it must be listed on both applications and optional_applications.

env - Configuration parameters used by the application. The value of a configuration parameter is retrieved by calling application:get_env/1,2. The values in the application resource file can be overridden by values in a configuration file (see config(4)) or by command-line flags (see erts:erl(1)).

mod - Specifies the application callback module and a start argument, see application.

Key mod is necessary for an application implemented as a supervision tree, otherwise the application controller does not know how to start it. mod can be omitted for applications without processes, typically code libraries, for example, STDLIB.

start_phases - A list of start phases and corresponding start arguments for the application. If this key is present, the application master, in addition to the usual call to Module:start/2, also calls Module:start_phase(Phase,Type,PhaseArgs) for each start phase defined by key start_phases. Only after this extended start procedure, application:start(Application) returns.

Start phases can be used to synchronize startup of an application and its included applications. In this case, key mod must be specified as follows:

{mod, {application_starter,[Module,StartArgs]}}

The application master then calls Module:start/2 for the primary application, followed by calls to Module:start_phase/3 for each start phase (as defined for the primary application), both for the primary application and for each of its included applications, for which the start phase is defined.

This implies that for an included application, the set of start phases must be a subset of the set of phases defined for the primary application. For more information, see Applications in OTP Design Principles.

runtime_dependencies - A list of application versions that the application depends on. An example of such an application version is "kernel-3.0". Application versions specified as runtime dependencies are minimum requirements. That is, a larger application version than the one specified in the dependency satisfies the requirement. For information about how to compare application versions, see section Versions in the System Principles User's Guide.

Notice that the application version specifies a source code version. One more, indirect, requirement is that the installed binary application of the specified version is built so that it is compatible with the rest of the system.

Some dependencies can only be required in specific runtime scenarios. When such optional dependencies exist, these are specified and documented in the corresponding "App" documentation of the specific application.

See Also

application, systools

config

Configuration file.

Description

A configuration file contains values for configuration parameters for the applications in the system. The erl command-line argument -config Name tells the system to use data in the system configuration file Name.config.

The erl command-line argument -configfd works the same way as the -config option but specifies a file descriptor to read configuration data from instead of a file.

The configuration data from configuration files and file descriptors are read in the same order as they are given on the command line. For example, erl -config a -configfd 3 -config b -configfd 4 would cause the system to read configuration data in the following order a.config, file descriptor 3, b.config, and file descriptor 4. If a configuration parameter is specified more than once in the given files and file descriptors, the last one overrides the previous ones.

Configuration parameter values in a configuration file or file descriptor override the values in the application resource files (see app(4)). The values in the configuration file are always overridden by command-line flags (see erts:erl(1)).

The value of a configuration parameter is retrieved by calling application:get_env/1,2.

File Syntax

The configuration file is to be called Name.config, where Name is any name.

File .config contains a single Erlang term and has the following syntax:

[{Application1, [{Par11, Val11}, ...]},
 ...
 {ApplicationN, [{ParN1, ValN1}, ...]}].

Application = atom() - Application name.

Par = atom() - Name of a configuration parameter.

Val = term() - Value of a configuration parameter.

sys.config

When starting Erlang in embedded mode, it is assumed that exactly one system configuration file is used, named sys.config. This file is to be located in $ROOT/releases/Vsn, where $ROOT is the Erlang/OTP root installation directory and Vsn is the release version.

Release handling relies on this assumption. When installing a new release version, the new sys.config is read and used to update the application's configurations.

This means that specifying another .config file, or more .config files, leads to an inconsistent update of application configurations. There is, however, a way to point out other config files from a sys.config. How to do this is described in the next section.

Including Files from sys.config and -configfd Configurations

There is a way to include other configuration files from a sys.config file and from a configuration that comes from a file descriptor that has been pointed out with the -configfd command-line argument.

The syntax for including files can be described by the Erlang type language like this:

[{Application, [{Par, Val}]} | IncludeFile].

IncludeFile = string() - Name of a .config file. The extension .config can be omitted. It is recommended to use absolute paths. If a relative path is used in a sys.config, IncludeFile is searched, first, relative to the sys.config directory, then relative to the current working directory of the emulator. If a relative path is used in a -configfd configuration, IncludeFile is searched, first, relative to the dictionary containing the boot script (see also the -boot command-line argument) for the emulator, then relative to the current working directory of the emulator. This makes it possible to use sys.config for pointing out other .config files in a release or in a node started manually using -config or -configfd with the same result whatever the current working directory is.

When traversing the contents of a sys.config or a -configfd configuration and a filename is encountered, its contents are read and merged with the result so far. When an application configuration tuple {Application, Env} is found, it is merged with the result so far. Merging means that new parameters are added and existing parameter values are overwritten.

Example:

sys.config:

["/home/user/myconfig1"
 {myapp,[{par1,val1},{par2,val2}]},
 "/home/user/myconfig2"].

myconfig1.config:

[{myapp,[{par0,val0},{par1,val0},{par2,val0}]}].

myconfig2.config:

[{myapp,[{par2,val3},{par3,val4}]}].

This yields the following environment for myapp:

[{par0,val0},{par1,val1},{par2,val3},{par3,val4}]

The run-time system will abort before staring up if an include file specified in sys.config or a -configfd configuration does not exist, or is erroneous. However, installing a new release version will not fail if there is an error while loading an include file, but an error message is returned and the erroneous file is ignored.

See Also

app(4), erts:erl(1), OTP Design Principles

application behaviour

Generic OTP application functions

In OTP, application denotes a component implementing some specific functionality, that can be started and stopped as a unit, and that can be reused in other systems. This module interacts with application controller, a process started at every Erlang runtime system. This module contains functions for controlling applications (for example, starting and stopping applications), and functions to access information about applications (for example, configuration parameters).

An application is defined by an application specification. The specification is normally located in an application resource file named Application.app, where Application is the application name. For details about the application specification, see app.

This module can also be viewed as a behaviour for an application implemented according to the OTP design principles as a supervision tree. The definition of how to start and stop the tree is to be located in an application callback module, exporting a predefined set of functions.

For details about applications and behaviours, see OTP Design Principles.

See Also

OTP Design Principles, kernel, app

Summary

Types

application_opt()

The built-in options available to an application.

application_spec()

An application specification.

restart_type()

The type of restart behaviour an application should have.

start_type()

The reason for the application to be started on the current node.

tuple_of(T)

A tuple where the elements are of type T.

Callbacks

config_change(Changed, New, Removed)

This function is called by an application after a code replacement, if the configuration parameters have changed.

prep_stop(State)

This function is called when an application is about to be stopped, before shutting down the processes of the application.

start(Application, Type)

This function is called whenever an application is started using start/1,2, and is to start the processes of the application. If the application is structured according to the OTP design principles as a supervision tree, this means starting the top supervisor of the tree.

start_phase(Phase, StartType, PhaseArgs)

Starts an application with included applications, when synchronization is needed between processes in the different applications during startup.

stop(Application)

This function is called whenever an application has stopped. It is intended to be the opposite of Module:start/2 and is to do any necessary cleaning up. The return value is ignored.

Functions

ensure_all_started(Applications)

Equivalent to ensure_all_started(Applications, temporary, serial).

ensure_all_started(Applications, Type)

Equivalent to ensure_all_started(Applications, Type, serial).

ensure_all_started(Applications, Type, Mode)

Applications is either an an atom/0 or a list of atom/0 representing multiple applications.

ensure_started(Application)

Equivalent to start(Application) except it returns ok for already started applications.

ensure_started(Application, Type)

Equivalent to start(Application, Type) except it returns ok for already started applications.

get_all_env()

Equivalent to get_all_env(application:get_application()).

get_all_env(Application)

Returns the configuration parameters and their values for Application.

get_all_key()

Equivalent to get_all_key(application:get_application()).

get_all_key(Application)

Returns the application specification keys and their values for Application. If the argument is omitted, it defaults to the application of the calling process.

get_application()

Equivalent to get_application(self()).

get_application(PidOrModule)

Returns the name of the application to which the process Pid or the module Module belongs.

get_env(Par)

Equivalent to get_env(application:get_application(), Par).

get_env(Application, Par)

Returns the value of configuration parameter Par for Application.

get_env(Application, Par, Def)

Works like get_env/2 but returns value Def when configuration parameter Par does not exist.

get_key(Key)

Equivalent to get_key(application:get_application(), Key).

get_key(Application, Key)

Returns the value of the application specification key Key for Application.

get_supervisor(Application)

Returns the Pid of the supervisor running at the root of Application.

load(AppDescr)

Equivalent to load(AppDescr, []).

load(AppDescr, Distributed)

Loads the application specification for an application into the application controller. It also loads the application specifications for any included applications. Notice that the function does not load the Erlang object code.

loaded_applications()

Returns a list with information about the applications, and included applications, which are loaded using load/1,2. Application is the application name. Description and Vsn are the values of their description and vsn application specification keys, respectively.

permit(Application, Permission)

Changes the permission for Application to run at the current node. The application must be loaded using load/1,2 for the function to have effect.

set_env(Config)

Equivalent to set_env(Config, []).

set_env(Config, Opts)

Sets the configuration Config for multiple applications.

set_env(Application, Par, Val)

Equivalent to set_env(Application, Par, Val, []).

set_env(Application, Par, Val, Opts)

Sets the value of configuration parameter Par for Application.

start(Application)

Equivalent to start(Application, temporary).

start(Application, Type)

Starts Application. If it is not loaded, the application controller first loads it using load/1. It ensures that any included applications are loaded, but does not start them. That is assumed to be taken care of in the code for Application.

start_type()

This function is intended to be called by a process belonging to an application, when the application is started, to determine the start type, which is StartType or local.

stop(Application)

Stops Application. The application master calls Module:prep_stop/1, if such a function is defined, and then tells the top supervisor of the application to shut down (see supervisor).

takeover(Application, Type)

Takes over the distributed application Application, which executes at another node Node.

unload(Application)

Unloads the application specification for Application from the application controller. It also unloads the application specifications for any included applications. Notice that the function does not purge the Erlang object code.

unset_env(Application, Par)

Equivalent to unset_env(Application, Par, []).

unset_env(Application, Par, Opts)

Removes the configuration parameter Par and its value for Application.

which_applications()

Equivalent to which_applications(5000).

which_applications(Timeout)

Returns a list with information about the applications that are currently running.

Types

application_opt()

(not exported)

-type application_opt() ::
          {description, Description :: string()} |
          {vsn, Vsn :: string()} |
          {id, Id :: string()} |
          {modules, [Module :: module()]} |
          {registered, Names :: [Name :: atom()]} |
          {applications, [Application :: atom()]} |
          {included_applications, [Application :: atom()]} |
          {env, [{Par :: atom(), Val :: term()}]} |
          {start_phases, [{Phase :: atom(), PhaseArgs :: term()}] | undefined} |
          {maxT, MaxT :: timeout()} |
          {maxP, MaxP :: pos_integer() | infinity} |
          {mod, Start :: {Module :: module(), StartArgs :: term()}}.

The built-in options available to an application.

See app for descriptions of the options.

application_spec()

(not exported)

-type application_spec() :: {application, Application :: atom(), AppSpecKeys :: [application_opt()]}.

An application specification.

restart_type()

-type restart_type() :: permanent | transient | temporary.

The type of restart behaviour an application should have.

start_type()

-type start_type() :: normal | {takeover, Node :: node()} | {failover, Node :: node()}.

The reason for the application to be started on the current node.

tuple_of(T)

(not exported)

-type tuple_of(_T) :: tuple().

A tuple where the elements are of type T.

Callbacks

config_change(Changed, New, Removed)

(optional)

-callback config_change(Changed, New, Removed) -> ok
                           when
                               Changed :: [{Par, Val}],
                               New :: [{Par, Val}],
                               Removed :: [Par],
                               Par :: atom(),
                               Val :: term().

This function is called by an application after a code replacement, if the configuration parameters have changed.

Changed is a list of parameter-value tuples including all configuration parameters with changed values.

New is a list of parameter-value tuples including all added configuration parameters.

Removed is a list of all removed parameters.

prep_stop(State)

(optional)

-callback prep_stop(State) -> NewState when State :: term(), NewState :: term().

This function is called when an application is about to be stopped, before shutting down the processes of the application.

State is the state returned from Module:start/2, or [] if no state was returned. NewState is any term and is passed to Module:stop/1.

The function is optional. If it is not defined, the processes are terminated and then Module:stop(State) is called.

start(Application, Type)

-callback start(StartType :: start_type(), StartArgs :: term()) ->
                   {ok, pid()} | {ok, pid(), State :: term()} | {error, Reason :: term()}.

This function is called whenever an application is started using start/1,2, and is to start the processes of the application. If the application is structured according to the OTP design principles as a supervision tree, this means starting the top supervisor of the tree.

StartType defines the type of start:

normal if it is a normal startup.

normal also if the application is distributed and started at the current node because of a failover from another node, and the application specification key start_phases == undefined.

{takeover,Node} if the application is distributed and started at the current node because of a takeover from Node, either because takeover/2 has been called or because the current node has higher priority than Node.

{failover,Node} if the application is distributed and started at the current node because of a failover from Node, and the application specification key start_phases /= undefined.

StartArgs is the StartArgs argument defined by the application specification key mod.

The function is to return {ok,Pid} or {ok,Pid,State}, where Pid is the pid of the top supervisor and State is any term. If omitted, State defaults to []. If the application is stopped later, State is passed to Module:prep_stop/1.

start_phase(Phase, StartType, PhaseArgs)

(optional)

-callback start_phase(Phase, StartType, PhaseArgs) -> ok | {error, Reason}
                         when
                             Phase :: atom(),
                             StartType :: start_type(),
                             PhaseArgs :: term(),
                             Reason :: term().

Starts an application with included applications, when synchronization is needed between processes in the different applications during startup.

The start phases are defined by the application specification key start_phases == [{Phase,PhaseArgs}]. For included applications, the set of phases must be a subset of the set of phases defined for the including application.

The function is called for each start phase (as defined for the primary application) for the primary application and all included applications, for which the start phase is defined.

For a description of StartType, see Module:start/2.

stop(Application)

-callback stop(State :: term()) -> term().

This function is called whenever an application has stopped. It is intended to be the opposite of Module:start/2 and is to do any necessary cleaning up. The return value is ignored.

State is the return value of Module:prep_stop/1, if such a function exists. Otherwise State is taken from the return value of Module:start/2.

Functions

ensure_all_started(Applications)

(since OTP R16B02)

-spec ensure_all_started(Applications) -> {ok, Started} | {error, Reason}
                            when
                                Applications :: atom() | [atom()], Started :: [atom()], Reason :: term().

Equivalent to ensure_all_started(Applications, temporary, serial).

ensure_all_started(Applications, Type)

(since OTP R16B02)

-spec ensure_all_started(Applications, Type) -> {ok, Started} | {error, AppReason}
                            when
                                Applications :: atom() | [atom()],
                                Type :: restart_type(),
                                Started :: [atom()],
                                AppReason :: {atom(), term()}.

Equivalent to ensure_all_started(Applications, Type, serial).

ensure_all_started(Applications, Type, Mode)

(since OTP 26.0)

-spec ensure_all_started(Applications, Type, Mode) -> {ok, Started} | {error, AppReason}
                            when
                                Applications :: atom() | [atom()],
                                Type :: restart_type(),
                                Mode :: serial | concurrent,
                                Started :: [atom()],
                                AppReason :: {atom(), term()}.

Applications is either an an atom/0 or a list of atom/0 representing multiple applications.

This function is equivalent to calling start/1,2 repeatedly on all dependencies that are not yet started of each application. Optional dependencies will also be loaded and started if they are available.

The Mode argument controls if the applications should be started in serial mode (one at a time) or concurrent mode. In concurrent mode, a dependency graph is built and the leaves of the graph are started concurrently and recursively. In both modes, no assertion can be made about the order the applications are started. If not supplied, it defaults to serial.

Returns {ok, AppNames} for a successful start or for an already started application (which is, however, omitted from the AppNames list).

The function reports {error, {AppName,Reason}} for errors, where Reason is any possible reason returned by start/1,2 when starting a specific dependency.

If an error occurs, the applications started by the function are stopped to bring the set of running applications back to its initial state.

ensure_started(Application)

(since OTP R16B01)

-spec ensure_started(Application) -> ok | {error, Reason} when Application :: atom(), Reason :: term().

Equivalent to start(Application) except it returns ok for already started applications.

ensure_started(Application, Type)

(since OTP R16B01)

-spec ensure_started(Application, Type) -> ok | {error, Reason}
                        when Application :: atom(), Type :: restart_type(), Reason :: term().

Equivalent to start(Application, Type) except it returns ok for already started applications.

get_all_env()

-spec get_all_env() -> Env when Env :: [{Par :: atom(), Val :: term()}].

Equivalent to get_all_env(application:get_application()).

get_all_env(Application)

-spec get_all_env(Application) -> Env
                     when Application :: atom(), Env :: [{Par :: atom(), Val :: term()}].

Returns the configuration parameters and their values for Application.

If the specified application is not loaded, or if the process executing the call does not belong to any application, the function returns [].

get_all_key()

-spec get_all_key() -> [] | {ok, Keys} when Keys :: [{Key :: atom(), Val :: term()}, ...].

Equivalent to get_all_key(application:get_application()).

get_all_key(Application)

-spec get_all_key(Application) -> undefined | Keys
                     when Application :: atom(), Keys :: {ok, [{Key :: atom(), Val :: term()}, ...]}.

Returns the application specification keys and their values for Application. If the argument is omitted, it defaults to the application of the calling process.

If the specified application is not loaded, the function returns undefined. If the process executing the call does not belong to any application, the function returns [].

get_application()

-spec get_application() -> undefined | {ok, Application} when Application :: atom().

Equivalent to get_application(self()).

get_application(PidOrModule)

-spec get_application(PidOrModule) -> undefined | {ok, Application}
                         when
                             PidOrModule :: (Pid :: pid()) | (Module :: module()), Application :: atom().

Returns the name of the application to which the process Pid or the module Module belongs.

If the specified process does not belong to any application, or if the specified process or module does not exist, the function returns undefined.

get_env(Par)

-spec get_env(Par) -> undefined | {ok, Val} when Par :: atom(), Val :: term().

Equivalent to get_env(application:get_application(), Par).

get_env(Application, Par)

-spec get_env(Application, Par) -> undefined | {ok, Val}
                 when Application :: atom(), Par :: atom(), Val :: term().

Returns the value of configuration parameter Par for Application.

Returns undefined if any of the following applies:

The specified application is not loaded.

The configuration parameter does not exist.

The process executing the call does not belong to any application.

get_env(Application, Par, Def)

(since OTP R16B)

-spec get_env(Application, Par, Def) -> Val
                 when Application :: atom(), Par :: atom(), Def :: term(), Val :: term().

Works like get_env/2 but returns value Def when configuration parameter Par does not exist.

get_key(Key)

-spec get_key(Key) -> undefined | {ok, Val} when Key :: atom(), Val :: term().

Equivalent to get_key(application:get_application(), Key).

get_key(Application, Key)

-spec get_key(Application, Key) -> undefined | {ok, Val}
                 when Application :: atom(), Key :: atom(), Val :: term().

Returns the value of the application specification key Key for Application.

Returns undefined if any of the following applies:

The specified application is not loaded.

The specification key does not exist.

The process executing the call does not belong to any application.

get_supervisor(Application)

(since OTP 26.0)

-spec get_supervisor(Application) -> undefined | {ok, Pid} when Pid :: pid(), Application :: atom().

Returns the Pid of the supervisor running at the root of Application.

If the specified application does not exist or does not define a callback module, the function returns undefined.

load(AppDescr)

-spec load(AppDescr) -> ok | {error, Reason}
              when
                  AppDescr :: Application | (AppSpec :: application_spec()),
                  Application :: atom(),
                  Reason :: term().

Equivalent to load(AppDescr, []).

load(AppDescr, Distributed)

-spec load(AppDescr, Distributed) -> ok | {error, Reason}
              when
                  AppDescr :: Application | (AppSpec :: application_spec()),
                  Application :: atom(),
                  Distributed :: {Application, Nodes} | {Application, Time, Nodes} | default,
                  Nodes :: [node() | tuple_of(node())],
                  Time :: pos_integer(),
                  Reason :: term().

Loads the application specification for an application into the application controller. It also loads the application specifications for any included applications. Notice that the function does not load the Erlang object code.

The application can be specified by its name Application. In this case, the application controller searches the code path for the application resource file Application.app and loads the specification it contains.

The application specification can also be specified directly as a tuple AppSpec, having the format and contents as described in app.

If Distributed == {Application,[Time,]Nodes}, the application becomes distributed. The argument overrides the value for the application in the Kernel configuration parameter distributed. Application must be the application name (same as in the first argument). If a node crashes and Time is specified, the application controller waits for Time milliseconds before attempting to restart the application on another node. If Time is not specified, it defaults to 0 and the application is restarted immediately.

Nodes is a list of node names where the application can run, in priority from left to right. Node names can be grouped using tuples to indicate that they have the same priority.

Example:

Nodes = [cp1@cave, {cp2@cave, cp3@cave}]

This means that the application is preferably to be started at cp1@cave. If cp1@cave is down, the application is to be started at cp2@cave or cp3@cave.

If Distributed == default, the value for the application in the Kernel configuration parameter distributed is used.

loaded_applications()

-spec loaded_applications() -> [{Application, Description, Vsn}]
                             when Application :: atom(), Description :: string(), Vsn :: string().

Returns a list with information about the applications, and included applications, which are loaded using load/1,2. Application is the application name. Description and Vsn are the values of their description and vsn application specification keys, respectively.

permit(Application, Permission)

-spec permit(Application, Permission) -> ok | {error, Reason}
                when Application :: atom(), Permission :: boolean(), Reason :: term().

Changes the permission for Application to run at the current node. The application must be loaded using load/1,2 for the function to have effect.

If the permission of a loaded, but not started, application is set to false, start returns ok but the application is not started until the permission is set to true.

If the permission of a running application is set to false, the application is stopped. If the permission later is set to true, it is restarted.

If the application is distributed, setting the permission to false means that the application will be started at, or moved to, another node according to how its distribution is configured (see load/2).

The function does not return until the application is started, stopped, or successfully moved to another node. However, in some cases where permission is set to true, the function returns ok even though the application is not started. This is true when an application cannot start because of dependencies to other applications that are not yet started. When they are started, Application is started as well.

By default, all applications are loaded with permission true on all nodes. The permission can be configured using the Kernel configuration parameter permissions.

set_env(Config)

(since OTP 21.3)

-spec set_env(Config) -> ok
                 when
                     Config :: [{Application, Env}],
                     Application :: atom(),
                     Env :: [{Par :: atom(), Val :: term()}].

Equivalent to set_env(Config, []).

set_env(Config, Opts)

(since OTP 21.3)

-spec set_env(Config, Opts) -> ok
                 when
                     Config :: [{Application, Env}],
                     Application :: atom(),
                     Env :: [{Par :: atom(), Val :: term()}],
                     Opts :: [{timeout, timeout()} | {persistent, boolean()}].

Sets the configuration Config for multiple applications.

It is equivalent to calling set_env/4 on each application individually, except it is more efficient. The given Config is validated before the configuration is set.

set_env/2 uses the standard gen_server time-out value (5000 ms). Option timeout can be specified if another time-out value is useful, for example, in situations where the application controller is heavily loaded.

Option persistent can be set to true to guarantee that parameters set with set_env/2 are not overridden by those defined in the application resource file on load. This means that persistent values will stick after the application is loaded and also on application reload.

If an application is given more than once or if an application has the same key given more than once, the behaviour is undefined and a warning message will be logged. In future releases, an error will be raised.

Warning

Use this function only if you know what you are doing, that is, on your own applications. It is very application-dependent and configuration parameter-dependent when and how often the value is read by the application. Careless use of this function can put the application in a weird, inconsistent, and malfunctioning state.

set_env(Application, Par, Val)

-spec set_env(Application, Par, Val) -> ok when Application :: atom(), Par :: atom(), Val :: term().

Equivalent to set_env(Application, Par, Val, []).

set_env(Application, Par, Val, Opts)

-spec set_env(Application, Par, Val, Opts) -> ok
                 when
                     Application :: atom(),
                     Par :: atom(),
                     Val :: term(),
                     Opts :: [{timeout, timeout()} | {persistent, boolean()}].

Sets the value of configuration parameter Par for Application.

set_env/4 uses the standard gen_server time-out value (5000 ms). Option timeout can be specified if another time-out value is useful, for example, in situations where the application controller is heavily loaded.

If set_env/4 is called before the application is loaded, the application environment values specified in file Application.app override the ones previously set. This is also true for application reloads.

Option persistent can be set to true to guarantee that parameters set with set_env/4 are not overridden by those defined in the application resource file on load. This means that persistent values will stick after the application is loaded and also on application reload.

Warning

Use this function only if you know what you are doing, that is, on your own applications. It is very application-dependent and configuration parameter-dependent when and how often the value is read by the application. Careless use of this function can put the application in a weird, inconsistent, and malfunctioning state.

start(Application)

-spec start(Application) -> ok | {error, Reason} when Application :: atom(), Reason :: term().

Equivalent to start(Application, temporary).

start(Application, Type)

-spec start(Application, Type) -> ok | {error, Reason}
               when Application :: atom(), Type :: restart_type(), Reason :: term().

Starts Application. If it is not loaded, the application controller first loads it using load/1. It ensures that any included applications are loaded, but does not start them. That is assumed to be taken care of in the code for Application.

The application controller checks the value of the application specification key applications, to ensure that all applications needed to be started before this application are running. If an application is missing and the application is not marked as optional, {error,{not_started,App}} is returned, where App is the name of the missing application. Note this function makes no attempt to start any of the applications listed in applications, not even optional ones. See ensure_all_started/1,2 for recursively starting the current application and its dependencies.

Once validated, the application controller then creates an application master for the application. The application master becomes the group leader of all the processes in the application. I/O is forwarded to the previous group leader, though, this is just a way to identify processes that belong to the application. Used for example to find itself from any process, or, reciprocally, to kill them all when it terminates.

The application master starts the application by calling the application callback function Module:start/2 as defined by the application specification key mod.

Argument Type specifies the type of the application. If omitted, it defaults to temporary.

If a permanent application terminates, all other applications and the entire Erlang node are also terminated.

If a transient application terminates:

with Reason == normal, this is reported but no other applications are terminated.

abnormally, all other applications and the entire Erlang node are also terminated.

If a temporary application terminates, this is reported but no other applications are terminated.

Notice that an application can always be stopped explicitly by calling stop/1. Regardless of the type of the application, no other applications are affected.

Notice also that the transient type is of little practical use, because when a supervision tree terminates, the reason is set to shutdown, not normal.

start_type()

-spec start_type() -> StartType | undefined | local when StartType :: start_type().

This function is intended to be called by a process belonging to an application, when the application is started, to determine the start type, which is StartType or local.

For a description of StartType, see Module:start/2.

local is returned if only parts of the application are restarted (by a supervisor), or if the function is called outside a startup.

If the process executing the call does not belong to any application, the function returns undefined.

stop(Application)

-spec stop(Application) -> ok | {error, Reason} when Application :: atom(), Reason :: term().

Stops Application. The application master calls Module:prep_stop/1, if such a function is defined, and then tells the top supervisor of the application to shut down (see supervisor).

This means that the entire supervision tree, including included applications, is terminated in reversed start order. After the shutdown, the application master calls Module:stop/1. Module is the callback module as defined by the application specification key mod.

Last, the application master terminates. Notice that all processes with the application master as group leader, that is, processes spawned from a process belonging to the application, are also terminated.

When stopped, the application is still loaded.

To stop a distributed application, stop/1 must be called on all nodes where it can execute (that is, on all nodes where it has been started). The call to stop/1 on the node where the application currently executes stops its execution. The application is not moved between nodes, as stop/1 is called on the node where the application currently executes before stop/1 is called on the other nodes.

takeover(Application, Type)

-spec takeover(Application, Type) -> ok | {error, Reason}
                  when Application :: atom(), Type :: restart_type(), Reason :: term().

Takes over the distributed application Application, which executes at another node Node.

At the current node, the application is restarted by calling Module:start({takeover,Node},StartArgs). Module and StartArgs are retrieved from the loaded application specification. The application at the other node is not stopped until the startup is completed, that is, when Module:start/2 and any calls to Module:start_phase/3 have returned.

Thus, two instances of the application run simultaneously during the takeover, so that data can be transferred from the old to the new instance. If this is not an acceptable behavior, parts of the old instance can be shut down when the new instance is started. However, the application cannot be stopped entirely, at least the top supervisor must remain alive.

For a description of Type, see start/1,2.

unload(Application)

-spec unload(Application) -> ok | {error, Reason} when Application :: atom(), Reason :: term().

Unloads the application specification for Application from the application controller. It also unloads the application specifications for any included applications. Notice that the function does not purge the Erlang object code.

unset_env(Application, Par)

-spec unset_env(Application, Par) -> ok when Application :: atom(), Par :: atom().

Equivalent to unset_env(Application, Par, []).

unset_env(Application, Par, Opts)

-spec unset_env(Application, Par, Opts) -> ok
                   when
                       Application :: atom(),
                       Par :: atom(),
                       Opts :: [{timeout, timeout()} | {persistent, boolean()}].

Removes the configuration parameter Par and its value for Application.

unset_env/3 uses the standard gen_server time-out value (5000 ms). Option timeout can be specified if another time-out value is useful, for example, in situations where the application controller is heavily loaded.

unset_env/3 also allows the persistent option to be passed (see set_env/4).

Warning

Use this function only if you know what you are doing, that is, on your own applications. It is very application-dependent and configuration parameter-dependent when and how often the value is read by the application. Careless use of this function can put the application in a weird, inconsistent, and malfunctioning state.

which_applications()

-spec which_applications() -> [{Application, Description, Vsn}]
                            when Application :: atom(), Description :: string(), Vsn :: string().

Equivalent to which_applications(5000).

which_applications(Timeout)

-spec which_applications(Timeout) -> [{Application, Description, Vsn}]
                            when
                                Timeout :: timeout(),
                                Application :: atom(),
                                Description :: string(),
                                Vsn :: string().

Returns a list with information about the applications that are currently running.

Application is the application name. Description and Vsn are the values of their description and vsn application specification keys, respectively.

A Timeout argument can be specified in situations where the application controller is heavily loaded.

data_publisher behaviour

A behavior for building eventually consistent, replicated data stores across distributed nodes.

This module provides the infrastructure for:

Replicating data across all nodes running the same scope

Automatic peer discovery

Subscription-based notifications for data changes

Version translation for rolling upgrades

Implementing modules define how data is stored, updated, and how changes are calculated and propagated. This is a generalization of the pg module.

Summary

Types

global_view()

local_data()

options()

scope()

state()

subscribe_result()

subscription()

subscriptions()

update()

version()

Callbacks

data_diff(Old, New)

init_global_view/2

init_local_data/1

new_subscription/2

stop_global_view/1

translate_local_data/3

translate_message/2

translate_update/3

update_global_view_and_notify/4

update_local_data/2

version()

Functions

handle_call/3

handle_cast(Message, State)

handle_info/2

init/1

start(Scope, Module)

start(Scope, Module, Options)

start_link(Scope, Module)

start_link(Scope, Module, Options)

subscribe(Scope, Subscription)

terminate/2

unsubscribe(Scope, Ref)

update(Scope, Update)

Types

global_view()

(not exported) (since OTP 29.0)

-type global_view() :: dynamic().

local_data()

(not exported) (since OTP 29.0)

-type local_data() :: dynamic().

options()

(not exported) (since OTP 29.0)

-type options() :: #{standalone => boolean(), dynamic() => dynamic()}.

scope()

(not exported) (since OTP 29.0)

-type scope() :: atom().

state()

(not exported) (since OTP 29.0)

-type state() ::
          #state{scope :: atom(),
                 module :: module(),
                 options :: options(),
                 version :: version(),
                 global_view :: global_view(),
                 local_data :: local_data(),
                 peers :: #{pid() => {reference(), version(), local_data()}},
                 subscriptions :: subscriptions(),
                 subscribe_refs :: #{reference() => subscription()}}.

subscribe_result()

(not exported) (since OTP 29.0)

-type subscribe_result() :: dynamic().

subscription()

(not exported) (since OTP 29.0)

-type subscription() :: dynamic().

subscriptions()

(not exported) (since OTP 29.0)

-type subscriptions() :: #{subscription() => #{reference() => pid()}}.

update()

(not exported) (since OTP 29.0)

-type update() :: dynamic().

version()

(not exported) (since OTP 29.0)

-type version() :: dynamic().

Callbacks

data_diff(Old, New)

(since OTP 29.0)

-callback data_diff(Old :: local_data(), New :: local_data()) -> update().

init_global_view/2

(since OTP 29.0)

-callback init_global_view(scope(), options()) -> global_view().

init_local_data/1

(since OTP 29.0)

-callback init_local_data(options()) -> local_data().

new_subscription/2

(since OTP 29.0)

-callback new_subscription(subscription(), global_view()) -> subscribe_result().

stop_global_view/1

(since OTP 29.0)

-callback stop_global_view(global_view()) -> term().

translate_local_data/3

(since OTP 29.0)

-callback translate_local_data(MyVersion :: version(), PeerVersion :: version(), local_data()) ->
                                  local_data() | {'$plain_message', dynamic()}.

translate_message/2

(since OTP 29.0) (optional)

-callback translate_message(dynamic(), global_view()) ->
                               {update, update(), global_view()} |
                               {drop, global_view()} |
                               {update, pid(), update(), global_view()} |
                               {local_data, pid(), version(), local_data(), global_view()} |
                               {discover, pid(), version(), global_view()}.

translate_update/3

(since OTP 29.0)

-callback translate_update(MyVersion :: version(), PeerVersion :: version(), update()) ->
                              update() | {'$plain_messages', [dynamic()]}.

update_global_view_and_notify/4

(since OTP 29.0)

-callback update_global_view_and_notify(node(), update(), subscriptions(), global_view()) -> global_view().

update_local_data/2

(since OTP 29.0)

-callback update_local_data(update(), local_data()) -> local_data().

version()

(since OTP 29.0)

-callback version() -> version().

Functions

handle_call/3

(since OTP 29.0)

-spec handle_call({update, update()}, gen_server:from(), state()) -> {reply, ok, state()};
                 ({subscribe, subscription()}, gen_server:from(), state()) ->
                     {reply, {reference(), subscribe_result()}, state()};
                 ({unsubscribe, reference()}, gen_server:from(), state()) -> {reply, ok, state()}.

handle_cast(Message, State)

(since OTP 29.0)

-spec handle_cast(Message, state()) -> {noreply, state()}
                     when Message :: {local_data, pid(), version(), local_data()} | dynamic().

handle_info/2

(since OTP 29.0)

-spec handle_info(Message, state()) -> {noreply, state()}
                     when
                         Message ::
                             {discover, pid(), version()} |
                             {local_data, pid(), version(), local_data()} |
                             {update, pid(), update()} |
                             {nodeup, node()} |
                             {nodedown, node()} |
                             {{'DOWN', subscribe}, reference(), process, pid(), dynamic()} |
                             {{'DOWN', peer}, reference(), process, pid(), dynamic()} |
                             dynamic().

init/1

(since OTP 29.0)

-spec init({scope(), module(), options()}) -> {ok, state()}.

start(Scope, Module)

(since OTP 29.0)

-spec start(scope(), module()) -> {ok, pid()} | {error, term()}.

start(Scope, Module, Options)

(since OTP 29.0)

-spec start(scope(), module(), options()) -> {ok, pid()} | {error, term()}.

start_link(Scope, Module)

(since OTP 29.0)

-spec start_link(scope(), module()) -> {ok, pid()} | {error, term()}.

start_link(Scope, Module, Options)

(since OTP 29.0)

-spec start_link(scope(), module(), options()) -> {ok, pid()} | {error, term()}.

subscribe(Scope, Subscription)

(since OTP 29.0)

-spec subscribe(scope(), subscription()) -> {reference(), subscribe_result()}.

terminate/2

(since OTP 29.0)

-spec terminate(dynamic(), state()) -> term().

unsubscribe(Scope, Ref)

(since OTP 29.0)

-spec unsubscribe(scope(), reference()) -> ok.

update(Scope, Update)

(since OTP 29.0)

-spec update(scope(), update()) -> ok.

error_handler

Default system error handler.

This module defines what happens when certain types of errors occur.

You can change the error handler of a process by calling erlang:process_flag(error_handler, NewErrorHandler).

Notes

The code in error_handler is complex. Do not change it without fully understanding the interaction between the error handler, the init process of the code server, and the I/O mechanism of the code.

Code changes that seem small can cause a deadlock, as unforeseen consequences can occur. The use of input is dangerous in this type of code.

Summary

Functions

raise_undef_exception(Module, Function, Args)

Raises an undef exception with a stacktrace, indicating that Module:Function/N is undefined.

undefined_function(Module, Function, Args)

This function is called by the runtime system if a call is made to Module:Function(Arg1,.., ArgN) and Module:Function/N is undefined. Notice that this function is evaluated inside the process making the original call.

undefined_lambda(Module, Fun, Args)

This function is evaluated if a call is made to Fun(Arg1,.., ArgN) when the module defining the fun is not loaded. The function is evaluated inside the process making the original call.

Functions

raise_undef_exception(Module, Function, Args)

(since OTP R16B)

-spec raise_undef_exception(Module, Function, Args) -> no_return()
                               when Module :: atom(), Function :: atom(), Args :: list().

Raises an undef exception with a stacktrace, indicating that Module:Function/N is undefined.

undefined_function(Module, Function, Args)

-spec undefined_function(Module, Function, Args) -> any()
                            when Module :: atom(), Function :: atom(), Args :: list().

This function is called by the runtime system if a call is made to Module:Function(Arg1,.., ArgN) and Module:Function/N is undefined. Notice that this function is evaluated inside the process making the original call.

This function first attempts to autoload Module. If that is not possible, an undef exception is raised.

If it is possible to load Module and function Function/N is exported, it is called.

Otherwise, if function '$handle_undefined_function'/2 is exported, it is called as '$handle_undefined_function'(Function, Args).

Warning

Defining '$handle_undefined_function'/2 in ordinary application code is highly discouraged. It is very easy to make subtle errors that can take a long time to debug. Furthermore, none of the tools for static code analysis (such as Dialyzer and Xref) supports the use of '$handle_undefined_function'/2 and no such support will be added. Only use this function after having carefully considered other, less dangerous, solutions. One example of potential legitimate use is creating stubs for other sub-systems during testing and debugging.

Otherwise an undef exception is raised.

undefined_lambda(Module, Fun, Args)

-spec undefined_lambda(Module, Fun, Args) -> term() when Module :: atom(), Fun :: fun(), Args :: list().

This function is evaluated if a call is made to Fun(Arg1,.., ArgN) when the module defining the fun is not loaded. The function is evaluated inside the process making the original call.

If Module is interpreted, the interpreter is invoked and the return value of the interpreted Fun(Arg1,.., ArgN) call is returned.

Otherwise, it returns, if possible, the value of apply(Fun, Args) after an attempt is made to autoload Module. If this is not possible, the call fails with exit reason undef.

file

File interface module.

This module provides an interface to the file system.

Warning

File operations are only guaranteed to appear atomic when going through the same file server. A NIF or other OS process may observe intermediate steps on certain operations on some operating systems, eg. renaming an existing file on Windows, or write_file_info/2 on any OS at the time of writing.

Regarding filename encoding, the Erlang VM can operate in two modes. The current mode can be queried using function native_name_encoding/0. It returns latin1 or utf8.

In latin1 mode, the Erlang VM does not change the encoding of filenames. In utf8 mode, filenames can contain Unicode characters greater than 255 and the VM converts filenames back and forth to the native filename encoding (usually UTF-8, but UTF-16 on Windows).

The default mode depends on the operating system. Windows, MacOS X and Android enforce consistent filename encoding and therefore the VM uses utf8 mode.

On operating systems with transparent naming (for example, all Unix systems except MacOS X), default is utf8 if the terminal supports UTF-8, otherwise latin1. The default can be overridden using +fnl (to force latin1 mode) or +fnu (to force utf8 mode) when starting erl.

On operating systems with transparent naming, files can be inconsistently named, for example, some files are encoded in UTF-8 while others are encoded in ISO Latin-1. The concept of raw filenames is introduced to handle file systems with inconsistent naming when running in utf8 mode.

A raw filename is a filename specified as a binary. The Erlang VM does not translate a filename specified as a binary on systems with transparent naming.

When running in utf8 mode, functions list_dir/1 and read_link/1 never return raw filenames. To return all filenames including raw filenames, use functions list_dir_all/1 and read_link_all/1.

See also section Notes About Raw Filenames in the STDLIB User's Guide.

Note

File operations used to accept filenames containing null characters (integer value zero). This caused the name to be truncated and in some cases arguments to primitive operations to be mixed up. Filenames containing null characters inside the filename are now rejected and will cause primitive file operations fail.

POSIX Error Codes

eacces - Permission denied

eagain - Resource temporarily unavailable

ebadf - Bad file number

ebusy - File busy

edquot - Disk quota exceeded

eexist - File already exists

efault - Bad address in system call argument

efbig - File too large

eintr - Interrupted system call

einval - Invalid argument

eio - I/O error

eisdir - Illegal operation on a directory

eloop - Too many levels of symbolic links

emfile - Too many open files

emlink - Too many links

enametoolong - Filename too long

enfile - File table overflow

enodev - No such device

enoent - No such file or directory

enomem - Not enough memory

enospc - No space left on device

enotblk - Block device required

enotdir - Not a directory

enotsup - Operation not supported

enxio - No such device or address

eperm - Not owner

epipe - Broken pipe

erofs - Read-only file system

espipe - Invalid seek

esrch - No such process

estale - Stale remote file handle

exdev - Cross-device link

Performance

For increased performance, raw files are recommended.

A normal file is really a process so it can be used as an I/O device (see io). Therefore, when data is written to a normal file, the sending of the data to the file process, copies all data that are not binaries. Opening the file in binary mode and writing binaries is therefore recommended. If the file is opened on another node, or if the file server runs as slave to the file server of another node, also binaries are copied.

Note

Raw files use the file system of the host machine of the node. For normal files (non-raw), the file server is used to find the files, and if the node is running its file server as slave to the file server of another node, and the other node runs on some other host machine, they can have different file systems. However, this is seldom a problem.

open/2 can be given the options delayed_write and read_ahead to turn on caching, which will reduce the number of operating system calls and greatly improve performance for small reads and writes. However, the overhead won't disappear completely and it's best to keep the number of file operations to a minimum. As a contrived example, the following function writes 4MB in 2.5 seconds when tested:

create_file_slow(Name) ->
    {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
    create_file_slow_1(Fd, 4 bsl 20),
    file:close(Fd).

create_file_slow_1(_Fd, 0) ->
    ok;
create_file_slow_1(Fd, M) ->
    ok = file:write(Fd, <<0>>),
    create_file_slow_1(Fd, M - 1).

The following functionally equivalent code writes 128 bytes per call to write/2 and so does the same work in 0.08 seconds, which is roughly 30 times faster:

create_file(Name) ->
    {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
    create_file_1(Fd, 4 bsl 20),
    file:close(Fd),
    ok.

create_file_1(_Fd, 0) ->
    ok;
create_file_1(Fd, M) when M >= 128 ->
    ok = file:write(Fd, <<0:(128)/unit:8>>),
    create_file_1(Fd, M - 128);
create_file_1(Fd, M) ->
    ok = file:write(Fd, <<0:(M)/unit:8>>),
    create_file_1(Fd, M - 1).

When writing data it's generally more efficient to write a list of binaries rather than a list of integers. It is not needed to flatten a deep list before writing. On Unix hosts, scatter output, which writes a set of buffers in one operation, is used when possible. In this way write(FD, [Bin1, Bin2 | Bin3]) writes the contents of the binaries without copying the data at all, except for perhaps deep down in the operating system kernel.

Warning

If an error occurs when accessing an open file with module io, the process handling the file exits. The dead file process can hang if a process tries to access it later. This will be fixed in a future release.

See Also

filename

Summary

Types

date_time()

Must denote a valid date and time.

deep_list()

delete_option()

fd()

A file descriptor representing a file opened in raw mode.

file_info()

file_info_option()

filename()

A file name as returned from file API functions.

filename_all()

A file name as returned from file API functions.

io_device()

An IO device as returned by open/2.

io_server()

A process handling the I/O protocol.

location()

mode()

name()

A restricted file name used as input into file API functions.

name_all()

A file name used as input into file API functions.

posix()

An atom that is named from the POSIX error codes used in Unix, and in the runtime libraries of most C compilers.

posix_file_advise()

read_file_option()

sendfile_option()

Functions

advise(IoDevice, Offset, Length, Advise)

advise/4 can be used to announce an intention to access file data in a specific pattern in the future, thus allowing the operating system to perform appropriate optimizations.

allocate(File, Offset, Length)

allocate/3 can be used to preallocate space for a file.

change_group(Filename, Gid)

Changes group of a file. See write_file_info/2.

change_mode(Filename, Mode)

Changes permissions of a file. See write_file_info/2.

change_owner(Filename, Uid)

Changes owner of a file. See write_file_info/2.

change_owner(Filename, Uid, Gid)

Changes owner and group of a file. See write_file_info/2.

change_time(Filename, Mtime)

Changes the modification and access times of a file. See write_file_info/2.

change_time(Filename, Atime, Mtime)

Changes the modification and last access times of a file. See write_file_info/2.

close(IoDevice)

Closes the file referenced by IoDevice. It mostly returns ok, except for some severe errors such as out of memory.

consult(Filename)

Reads Erlang terms, separated by ., from Filename. Returns one of the following

copy(Source, Destination)

Equivalent to copy(Source, Destination, infinity).

copy(Source, Destination, ByteCount)

Copies ByteCount bytes from Source to Destination. Source and Destination refer to either filenames or IO devices from, for example, open/2.

datasync(IoDevice)

Ensures that any buffers kept by the operating system (not by the Erlang runtime system) are written to disk. In many ways it resembles fsync but it does not update some of the metadata of the file, such as the access time. On some platforms this function has no effect.

del_dir(Dir)

Tries to delete directory Dir. The directory must be empty before it can be deleted. Returns ok if successful.

del_dir_r(File)

Deletes file or directory File. If File is a directory, its contents is first recursively deleted. Returns

delete(Filename)

Equivalent to delete(Filename, []).

delete(Filename, Opts)

Tries to delete file Filename. Returns ok if successful.

eval(Filename)

Reads and evaluates Erlang expressions, separated by . (or ,, a sequence of expressions is also an expression) from Filename. The result of the evaluation is not returned; any expression sequence in the file must be there for its side effect.

eval(Filename, Bindings)

The same as eval/1, but the variable bindings Bindings are used in the evaluation. For information about the variable bindings, see erl_eval.

format_error(Reason)

Given the error reason returned by any function in this module, returns a descriptive string of the error in English.

get_cwd()

Returns {ok, Dir}, where Dir is the current working directory of the file server.

get_cwd(Drive)

Returns {ok, Dir} or {error, Reason}, where Dir is the current working directory of the specified drive.

list_dir(Dir)

Lists all files in a directory, except files with raw filenames. Returns {ok, Filenames} if successful, otherwise {error, Reason}. Filenames is a list of the names of all the files in the directory. The names are not sorted.

list_dir_all(Dir)

Lists all the files in a directory, including files with raw filenames. Returns {ok, Filenames} if successful, otherwise {error, Reason}. Filenames is a list of the names of all the files in the directory. The names are not sorted.

make_dir(Dir)

Tries to create directory Dir. Missing parent directories are not created. Returns ok if successful.

make_link(Existing, New)

Makes a hard link from Existing to New on platforms supporting links (Unix and Windows). This function returns ok if the link was successfully created, otherwise {error, Reason}. On platforms not supporting links, {error,enotsup} is returned.

make_symlink(Existing, New)

Creates a symbolic link New to the file or directory Existing on platforms supporting symbolic links (most Unix systems and Windows, beginning with Vista). Existing does not need to exist. Returns ok if the link is successfully created, otherwise {error, Reason}. On platforms not supporting symbolic links, {error, enotsup} is returned.

native_name_encoding()

Returns the filename encoding mode. If it is latin1, the system translates no filenames. If it is utf8, filenames are converted back and forth to the native filename encoding (usually UTF-8, but UTF-16 on Windows).

open(File, Modes)

Opens file File in the mode determined by Modes, which can contain one or more of the following options

path_consult(Path, Filename)

Searches the path Path (a list of directory names) until the file Filename is found. If Filename is an absolute filename, Path is ignored. Then reads Erlang terms, separated by ., from the file.

path_eval(Path, Filename)

Searches the path Path (a list of directory names) until the file Filename is found. If Filename is an absolute filename, Path is ignored. Then reads and evaluates Erlang expressions, separated by . (or ,, a sequence of expressions is also an expression), from the file. The result of evaluation is not returned; any expression sequence in the file must be there for its side effect.

path_open(Path, Filename, Modes)

Searches the path Path (a list of directory names) until the file Filename is found. If Filename is an absolute filename, Path is ignored. Then opens the file in the mode determined by Modes.

path_script(Path, Filename)

Searches the path Path (a list of directory names) until the file Filename is found. If Filename is an absolute filename, Path is ignored. Then reads and evaluates Erlang expressions, separated by . (or ,, a sequence of expressions is also an expression), from the file.

path_script(Path, Filename, Bindings)

The same as path_script/2 but the variable bindings Bindings are used in the evaluation. See erl_eval about variable bindings.

position(IoDevice, Location)

Sets the position of the file referenced by IoDevice to Location. Returns {ok, NewPosition} (as absolute offset) if successful, otherwise {error, Reason}. Location is one of the following

pread(IoDevice, LocNums)

Performs a sequence of pread/3 in one operation, which is more efficient than calling them one at a time. Returns {ok, [Data, ...]} or {error, Reason}, where each Data, the result of the corresponding pread, is either a list or a binary depending on the mode of the file, or eof if the requested position is beyond end of file.

pread(IoDevice, Location, Number)

Combines position/2 and read/2 in one operation, which is more efficient than calling them one at a time.

pwrite(IoDevice, LocBytes)

Performs a sequence of pwrite/3 in one operation, which is more efficient than calling them one at a time. Returns ok or {error, {N, Reason}}, where N is the number of successful writes done before the failure.

pwrite(IoDevice, Location, Bytes)

Combines position/2 and write/2 in one operation, which is more efficient than calling them one at a time.

read(IoDevice, Number)

Reads Number bytes/characters from the file referenced by IoDevice.

read_file(Filename)

Equivalent to read_file(Filename, []).

read_file(Filename, Opts)

Returns {ok, Binary}, where Binary is a binary data object that contains the contents of Filename, or {error, Reason} if an error occurs.

read_file_info(File)

Equivalent to read_file_info(File, []).

read_file_info(File, Opts)

Retrieves information about a file. Returns {ok, FileInfo} if successful, otherwise {error, Reason}.

read_line(IoDevice)

Reads a line of bytes/characters from the file referenced by IoDevice.

read_link(Name)

Returns {ok, Filename} if Name refers to a symbolic link that is not a raw filename, or {error, Reason} otherwise. On platforms that do not support symbolic links, the return value is {error,enotsup}.

read_link_all(Name)

Returns {ok, Filename} if Name refers to a symbolic link or {error, Reason} otherwise. On platforms that do not support symbolic links, the return value is {error, enotsup}.

read_link_info(Name)

Equivalent to read_link_info(Name, []).

read_link_info(Name, Opts)

Works like read_file_info/1,2 except that if Name is a symbolic link, information about the link is returned in the file_info record and the type field of the record is set to symlink.

rename(Source, Destination)

Tries to rename the file Source to Destination. It can be used to move files (and directories) between directories, but it is not sufficient to specify the destination only. The destination filename must also be specified. For example, if bar is a normal file and foo and baz are directories, rename("foo/bar", "baz") returns an error, but rename("foo/bar", "baz/bar") succeeds. Returns ok if it is successful.

script(Filename)

Reads and evaluates Erlang expressions, separated by . (or ,, a sequence of expressions is also an expression), from the file.

script(Filename, Bindings)

The same as script/1 but the variable bindings Bindings are used in the evaluation. See erl_eval about variable bindings.

sendfile(Filename, Socket)

Sends the file Filename to Socket. Returns {ok, BytesSent} if successful, otherwise {error, Reason}.

sendfile(RawFile, Socket, Offset, Bytes, Opts)

Sends Bytes from the file referenced by RawFile beginning at Offset to Socket. Returns {ok, BytesSent} if successful, otherwise {error, Reason}. If Bytes is set to 0 all data after the specified Offset is sent.

set_cwd(Dir)

Sets the current working directory of the file server to Dir. Returns ok if successful.

sync(IoDevice)

Ensures that any buffers kept by the operating system (not by the Erlang runtime system) are written to disk. On some platforms, this function might have no effect.

truncate(IoDevice)

Truncates the file referenced by IoDevice at the current position. Returns ok if successful, otherwise {error, Reason}.

write(IoDevice, Bytes)

Writes Bytes to the file referenced by IoDevice. This function is the only way to write to a file opened in raw mode (although it works for normally opened files too). Returns ok if successful, and {error, Reason} otherwise.

write_file(Filename, Bytes)

Writes the contents of the iodata term Bytes to file Filename. The file is created if it does not exist. If it exists, the previous contents are overwritten. Returns ok if successful, otherwise {error, Reason}.

write_file(Filename, Bytes, Modes)

Same as write_file/2, but takes a third argument Modes, a list of possible modes, see open/2. The mode flags binary and write are implicit, so they are not to be used.

write_file_info(Filename, FileInfo)

Equivalent to write_file_info(Filename, FileInfo, []).

write_file_info(Filename, FileInfo, Opts)

Changes file information. Returns ok if successful, otherwise {error, Reason}.

Types

date_time()

-type date_time() :: calendar:datetime().

Must denote a valid date and time.

deep_list()

(not exported)

-type deep_list() :: [char() | atom() | deep_list()].

delete_option()

(not exported)

-type delete_option() :: raw.

fd()

-type fd() :: file_descriptor().

A file descriptor representing a file opened in raw mode.

file_info()

-type file_info() ::
          #file_info{size :: non_neg_integer() | undefined,
                     type :: device | directory | other | regular | symlink | undefined,
                     access :: read | write | read_write | none | undefined,
                     atime :: file:date_time() | non_neg_integer() | undefined,
                     mtime :: file:date_time() | non_neg_integer() | undefined,
                     ctime :: file:date_time() | non_neg_integer() | undefined,
                     mode :: non_neg_integer() | undefined,
                     links :: non_neg_integer() | undefined,
                     major_device :: non_neg_integer() | undefined,
                     minor_device :: non_neg_integer() | undefined,
                     inode :: non_neg_integer() | undefined,
                     uid :: non_neg_integer() | undefined,
                     gid :: non_neg_integer() | undefined}.

file_info_option()

(not exported)

-type file_info_option() :: {time, local} | {time, universal} | {time, posix} | raw.

filename()

-type filename() :: string().

A file name as returned from file API functions.

See the documentation of the name_all/0 type.

filename_all()

-type filename_all() :: string() | (RawFilename :: binary()).

A file name as returned from file API functions.

See the documentation of the name_all/0 type.

io_device()

-type io_device() :: io_server() | fd().

An IO device as returned by open/2.

io_server/0 is returned by default and fd/0 is returned if the raw option is given.

io_server()

-type io_server() :: pid().

A process handling the I/O protocol.

location()

-type location() ::
          integer() |
          {bof, Offset :: integer()} |
          {cur, Offset :: integer()} |
          {eof, Offset :: integer()} |
          bof | cur | eof.

mode()

-type mode() ::
          read | write | append | exclusive | raw | binary |
          {delayed_write, Size :: non_neg_integer(), Delay :: non_neg_integer()} |
          delayed_write |
          {read_ahead, Size :: pos_integer()} |
          read_ahead | compressed | compressed_one |
          {zstd, zstd:compress_parameters() | zstd:decompress_parameters()} |
          {encoding, unicode:encoding()} |
          sync.

name()

-type name() :: string() | atom() | deep_list().

A restricted file name used as input into file API functions.

If VM is in Unicode filename mode, string/0 and char/0 are allowed to be > 255. See also the documentation of the name_all/0 type.

name_all()

-type name_all() :: string() | atom() | deep_list() | (RawFilename :: binary()).

A file name used as input into file API functions.

If VM is in Unicode filename mode, characters are allowed to be > 255. RawFilename is a filename not subject to Unicode translation, meaning that it can contain characters not conforming to the Unicode encoding expected from the file system (that is, non-UTF-8 characters although the VM is started in Unicode filename mode). Null characters (integer value zero) are not allowed in filenames (not even at the end).

posix()

-type posix() ::
          eacces | eagain | ebadf | ebadmsg | ebusy | edeadlk | edeadlock | edquot | eexist | efault |
          efbig | eftype | eintr | einval | eio | eisdir | eloop | emfile | emlink | emultihop |
          enametoolong | enfile | enobufs | enodev | enolck | enolink | enoent | enomem | enospc |
          enosr | enostr | enosys | enotblk | enotdir | enotsup | enxio | eopnotsupp | eoverflow |
          eperm | epipe | erange | erofs | espipe | esrch | estale | etxtbsy | exdev.

An atom that is named from the POSIX error codes used in Unix, and in the runtime libraries of most C compilers.

posix_file_advise()

(not exported)

-type posix_file_advise() :: normal | sequential | random | no_reuse | will_need | dont_need.

read_file_option()

(not exported)

-type read_file_option() :: raw.

sendfile_option()

(not exported)

-type sendfile_option() :: {chunk_size, non_neg_integer()} | {use_threads, boolean()}.

Functions

advise(IoDevice, Offset, Length, Advise)

(since OTP R14B)

-spec advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason}
                when
                    IoDevice :: io_device(),
                    Offset :: integer(),
                    Length :: integer(),
                    Advise :: posix_file_advise(),
                    Reason :: posix() | badarg.

advise/4 can be used to announce an intention to access file data in a specific pattern in the future, thus allowing the operating system to perform appropriate optimizations.

On some platforms, this function might have no effect.

allocate(File, Offset, Length)

(since OTP R16B)

-spec allocate(File, Offset, Length) -> ok | {error, posix()}
                  when File :: io_device(), Offset :: non_neg_integer(), Length :: non_neg_integer().

allocate/3 can be used to preallocate space for a file.

This function only succeeds in platforms that provide this feature.

change_group(Filename, Gid)

-spec change_group(Filename, Gid) -> ok | {error, Reason}
                      when Filename :: name_all(), Gid :: integer(), Reason :: posix() | badarg.

Changes group of a file. See write_file_info/2.

change_mode(Filename, Mode)

(since OTP R14B)

-spec change_mode(Filename, Mode) -> ok | {error, Reason}
                     when Filename :: name_all(), Mode :: integer(), Reason :: posix() | badarg.

Changes permissions of a file. See write_file_info/2.

change_owner(Filename, Uid)

-spec change_owner(Filename, Uid) -> ok | {error, Reason}
                      when Filename :: name_all(), Uid :: integer(), Reason :: posix() | badarg.

Changes owner of a file. See write_file_info/2.

change_owner(Filename, Uid, Gid)

-spec change_owner(Filename, Uid, Gid) -> ok | {error, Reason}
                      when
                          Filename :: name_all(),
                          Uid :: integer(),
                          Gid :: integer(),
                          Reason :: posix() | badarg.

Changes owner and group of a file. See write_file_info/2.

change_time(Filename, Mtime)

-spec change_time(Filename, Mtime) -> ok | {error, Reason}
                     when Filename :: name_all(), Mtime :: date_time(), Reason :: posix() | badarg.

Changes the modification and access times of a file. See write_file_info/2.

change_time(Filename, Atime, Mtime)

-spec change_time(Filename, Atime, Mtime) -> ok | {error, Reason}
                     when
                         Filename :: name_all(),
                         Atime :: date_time(),
                         Mtime :: date_time(),
                         Reason :: posix() | badarg.

Changes the modification and last access times of a file. See write_file_info/2.

close(IoDevice)

-spec close(IoDevice) -> ok | {error, Reason}
               when IoDevice :: io_device(), Reason :: posix() | badarg | terminated.

Closes the file referenced by IoDevice. It mostly returns ok, except for some severe errors such as out of memory.

Notice that if option delayed_write was used when opening the file, close/1 can return an old write error and not even try to close the file. See open/2.

consult(Filename)

-spec consult(Filename) -> {ok, Terms} | {error, Reason}
                 when
                     Filename :: name_all(),
                     Terms :: [term()],
                     Reason ::
                         posix() |
                         badarg | terminated | system_limit |
                         {Line :: integer(), Mod :: module(), Term :: term()}.

Reads Erlang terms, separated by ., from Filename. Returns one of the following:

{ok, Terms} - The file was successfully read.

{error, atom()} - An error occurred when opening the file or reading it. For a list of typical error codes, see open/2.

{error, {Line, Mod, Term}} - An error occurred when interpreting the Erlang terms in the file. To convert the three-element tuple to an English description of the error, use format_error/1.

Example:

f.txt:  {person, "kalle", 25}.
        {person, "pelle", 30}.

1> file:consult("f.txt").
{ok,[{person,"kalle",25},{person,"pelle",30}]}

The encoding of Filename can be set by a comment, as described in epp.

copy(Source, Destination)

-spec copy(Source, Destination) -> {ok, BytesCopied} | {error, Reason}
              when
                  Source :: io_device() | Filename | {Filename, Modes},
                  Destination :: io_device() | Filename | {Filename, Modes},
                  Filename :: name_all(),
                  Modes :: [mode()],
                  BytesCopied :: non_neg_integer(),
                  Reason :: posix() | badarg | terminated.

Equivalent to copy(Source, Destination, infinity).

copy(Source, Destination, ByteCount)

-spec copy(Source, Destination, ByteCount) -> {ok, BytesCopied} | {error, Reason}
              when
                  Source :: io_device() | Filename | {Filename, Modes},
                  Destination :: io_device() | Filename | {Filename, Modes},
                  Filename :: name_all(),
                  Modes :: [mode()],
                  ByteCount :: non_neg_integer() | infinity,
                  BytesCopied :: non_neg_integer(),
                  Reason :: posix() | badarg | terminated.

Copies ByteCount bytes from Source to Destination. Source and Destination refer to either filenames or IO devices from, for example, open/2.

Argument Modes is a list of possible modes, see open/2, and defaults to [].

If both Source and Destination refer to filenames, the files are opened with [read, binary] and [write, binary] prepended to their mode lists, respectively, to optimize the copy.

If Source refers to a filename, it is opened with read mode prepended to the mode list before the copy, and closed when done.

If Destination refers to a filename, it is opened with write mode prepended to the mode list before the copy, and closed when done.

Returns {ok, BytesCopied}, where BytesCopied is the number of bytes that was copied, which can be less than ByteCount if end of file was encountered on the source. If the operation fails, {error, Reason} is returned.

Typical error reasons: as for open/2 if a file had to be opened, and as for read/2 and write/2.

datasync(IoDevice)

(since OTP R14B)

-spec datasync(IoDevice) -> ok | {error, Reason}
                  when IoDevice :: io_device(), Reason :: posix() | badarg | terminated.

Ensures that any buffers kept by the operating system (not by the Erlang runtime system) are written to disk. In many ways it resembles fsync but it does not update some of the metadata of the file, such as the access time. On some platforms this function has no effect.

Applications that access databases or log files often write a tiny data fragment (for example, one line in a log file) and then call fsync() immediately to ensure that the written data is physically stored on the hard disk. Unfortunately, fsync() always initiates two write operations: one for the newly written data and another one to update the modification time stored in the inode. If the modification time is not a part of the transaction concept, fdatasync() can be used to avoid unnecessary inode disk write operations.

Available only in some POSIX systems, this call results in a call to fsync(), or has no effect in systems not providing the fdatasync() syscall.

del_dir(Dir)

-spec del_dir(Dir) -> ok | {error, Reason} when Dir :: name_all(), Reason :: posix() | badarg.

Tries to delete directory Dir. The directory must be empty before it can be deleted. Returns ok if successful.

Typical error reasons:

eacces - Missing search or write permissions for the parent directories of Dir.

eexist - The directory is not empty.

enoent - The directory does not exist.

enotdir - A component of Dir is not a directory. On some platforms, enoent is returned instead.

einval - Attempt to delete the current directory. On some platforms, eacces is returned instead.

del_dir_r(File)

(since OTP 23.0)

-spec del_dir_r(File) -> ok | {error, Reason} when File :: name_all(), Reason :: posix() | badarg.

Deletes file or directory File. If File is a directory, its contents is first recursively deleted. Returns:

ok - The operation completed without errors.

{error, posix()} - An error occurred when accessing or deleting File. If some file or directory under File could not be deleted, File cannot be deleted as it is non-empty, and {error, eexist} is returned.

delete(Filename)

-spec delete(Filename) -> ok | {error, Reason} when Filename :: name_all(), Reason :: posix() | badarg.

Equivalent to delete(Filename, []).

delete(Filename, Opts)

(since OTP 24.0)

-spec delete(Filename, Opts) -> ok | {error, Reason}
                when Filename :: name_all(), Opts :: [delete_option()], Reason :: posix() | badarg.

Tries to delete file Filename. Returns ok if successful.

If the option raw is set, the file server is not called. This can be useful in particular during the early boot stage when the file server is not yet registered, to still be able to delete local files.

Typical error reasons:

enoent - The file does not exist.

eacces - Missing permission for the file or one of its parents.

eperm - The file is a directory and the user is not superuser.

enotdir - A component of the filename is not a directory. On some platforms, enoent is returned instead.

einval - Filename has an improper type, such as tuple.

Warning

In a future release, a bad type for argument Filename will probably generate an exception.

eval(Filename)

-spec eval(Filename) -> ok | {error, Reason}
              when
                  Filename :: name_all(),
                  Reason ::
                      posix() |
                      badarg | terminated | system_limit |
                      {Line :: integer(), Mod :: module(), Term :: term()}.

Reads and evaluates Erlang expressions, separated by . (or ,, a sequence of expressions is also an expression) from Filename. The result of the evaluation is not returned; any expression sequence in the file must be there for its side effect.

Returns one of the following:

ok - The file was read and evaluated.

{error, atom()} - An error occurred when opening the file or reading it. For a list of typical error codes, see open/2.

{error, {Line, Mod, Term}} - An error occurred when interpreting the Erlang expressions in the file. To convert the three-element tuple to an English description of the error, use format_error/1.

The encoding of Filename can be set by a comment, as described in epp.

eval(Filename, Bindings)

-spec eval(Filename, Bindings) -> ok | {error, Reason}
              when
                  Filename :: name_all(),
                  Bindings :: erl_eval:binding_struct(),
                  Reason ::
                      posix() |
                      badarg | terminated | system_limit |
                      {Line :: integer(), Mod :: module(), Term :: term()}.

The same as eval/1, but the variable bindings Bindings are used in the evaluation. For information about the variable bindings, see erl_eval.

format_error(Reason)

-spec format_error(Reason) -> Chars
                      when
                          Reason ::
                              posix() |
                              badarg | terminated | system_limit |
                              {Line :: integer(), Mod :: module(), Term :: term()},
                          Chars :: string().

Given the error reason returned by any function in this module, returns a descriptive string of the error in English.

get_cwd()

-spec get_cwd() -> {ok, Dir} | {error, Reason} when Dir :: filename(), Reason :: posix().

Returns {ok, Dir}, where Dir is the current working directory of the file server.

Note

In rare circumstances, this function can fail on Unix. It can occur if read permission does not exist for the parent directories of the current directory.

A typical error reason:

eacces - Missing read permission for one of the parents of the current directory.

get_cwd(Drive)

-spec get_cwd(Drive) -> {ok, Dir} | {error, Reason}
                 when Drive :: string(), Dir :: filename(), Reason :: posix() | badarg.

Returns {ok, Dir} or {error, Reason}, where Dir is the current working directory of the specified drive.

Drive is to be of the form Letter:, for example, c:.

Returns {error, enotsup} on platforms that have no concept of current drive (Unix, for example).

Typical error reasons:

enotsup - The operating system has no concept of drives.

eacces - The drive does not exist.

einval - The format of Drive is invalid.

list_dir(Dir)

-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason}
                  when
                      Dir :: name_all(),
                      Filenames :: [filename()],
                      Reason :: posix() | badarg | {no_translation, Filename :: unicode:latin1_binary()}.

Lists all files in a directory, except files with raw filenames. Returns {ok, Filenames} if successful, otherwise {error, Reason}. Filenames is a list of the names of all the files in the directory. The names are not sorted.

Typical error reasons:

eacces - Missing search or write permissions for Dir or one of its parent directories.

enoent - The directory does not exist.

{no_translation, Filename} - Filename is a binary/0 with characters coded in ISO Latin-1 and the VM was started with parameter +fnue.

list_dir_all(Dir)

(since OTP R16B)

-spec list_dir_all(Dir) -> {ok, Filenames} | {error, Reason}
                      when Dir :: name_all(), Filenames :: [filename_all()], Reason :: posix() | badarg.

Lists all the files in a directory, including files with raw filenames. Returns {ok, Filenames} if successful, otherwise {error, Reason}. Filenames is a list of the names of all the files in the directory. The names are not sorted.

Typical error reasons:

eacces - Missing search or write permissions for Dir or one of its parent directories.

enoent - The directory does not exist.

make_dir(Dir)

-spec make_dir(Dir) -> ok | {error, Reason} when Dir :: name_all(), Reason :: posix() | badarg.

Tries to create directory Dir. Missing parent directories are not created. Returns ok if successful.

Typical error reasons:

eacces - Missing search or write permissions for the parent directories of Dir.

eexist - A file or directory named Dir exists already.

enoent - A component of Dir does not exist.

enospc - No space is left on the device.

enotdir - A component of Dir is not a directory. On some platforms, enoent is returned instead.

make_link(Existing, New)

-spec make_link(Existing, New) -> ok | {error, Reason}
                   when Existing :: name_all(), New :: name_all(), Reason :: posix() | badarg.

Makes a hard link from Existing to New on platforms supporting links (Unix and Windows). This function returns ok if the link was successfully created, otherwise {error, Reason}. On platforms not supporting links, {error,enotsup} is returned.

Typical error reasons:

eacces - Missing read or write permissions for the parent directories of Existing or New.

eexist - New already exists.

enotsup - Hard links are not supported on this platform.

make_symlink(Existing, New)

-spec make_symlink(Existing, New) -> ok | {error, Reason}
                      when Existing :: name_all(), New :: name_all(), Reason :: posix() | badarg.

Creates a symbolic link New to the file or directory Existing on platforms supporting symbolic links (most Unix systems and Windows, beginning with Vista). Existing does not need to exist. Returns ok if the link is successfully created, otherwise {error, Reason}. On platforms not supporting symbolic links, {error, enotsup} is returned.

Typical error reasons:

eacces - Missing read or write permissions for the parent directories of Existing or New.

eexist - New already exists.

enotsup - Symbolic links are not supported on this platform.

eperm - User does not have privileges to create symbolic links (SeCreateSymbolicLinkPrivilege on Windows).

native_name_encoding()

(since OTP R14B01)

-spec native_name_encoding() -> latin1 | utf8.

Returns the filename encoding mode. If it is latin1, the system translates no filenames. If it is utf8, filenames are converted back and forth to the native filename encoding (usually UTF-8, but UTF-16 on Windows).

open(File, Modes)

-spec open(File, Modes) -> {ok, IoDevice} | {error, Reason}
              when
                  File :: Filename | iodata(),
                  Filename :: name_all(),
                  Modes :: [mode() | ram | directory],
                  IoDevice :: io_device(),
                  Reason :: posix() | badarg | system_limit.

Opens file File in the mode determined by Modes, which can contain one or more of the following options:

read - The file, which must exist, is opened for reading.

write - The file is opened for writing. It is created if it does not exist. If the file exists and write is not combined with read, the file is truncated.

append - The file is opened for writing. It is created if it does not exist. Every write operation to a file opened with append takes place at the end of the file.

exclusive - The file is opened for writing. It is created if it does not exist. If the file exists, {error, eexist} is returned.

Warning

This option does not guarantee exclusiveness on file systems not supporting O_EXCL properly, such as NFS. Do not depend on this option unless you know that the file system supports it (in general, local file systems are safe).

raw - Allows faster access to a file, as no Erlang process is needed to handle the file. However, a file opened in this way has the following limitations:

The functions in the io module cannot be used, as they can only talk to an Erlang process. Instead, use functions read/2, read_line/1, and write/2.

Especially if read_line/1 is to be used on a raw file, it is recommended to combine this option with option {read_ahead, Size} as line-oriented I/O is inefficient without buffering.

Only the Erlang process that opened the file can use it.

A remote Erlang file server cannot be used. The computer on which the Erlang node is running must have access to the file system (directly or through NFS).

binary - Read operations on the file return binaries rather than lists.

{delayed_write, Size, Delay} - Data in subsequent write/2 calls is buffered until at least Size bytes are buffered, or until the oldest buffered data is Delay milliseconds old. Then all buffered data is written in one operating system call. The buffered data is also flushed before some other file operation than write/2 is executed.

The purpose of this option is to increase performance by reducing the number of operating system calls. Thus, the write/2 calls must be for sizes significantly less than Size, and not interspersed by too many other file operations.

When this option is used, the result of write/2 calls can prematurely be reported as successful, and if a write error occurs, the error is reported as the result of the next file operation, which is not executed.

For example, when delayed_write is used, after a number of write/2 calls, close/1 can return {error, enospc}, as there is not enough space on the disc for previously written data. close/1 must probably be called again, as the file is still open.

delayed_write - The same as {delayed_write, Size, Delay} with reasonable default values for Size and Delay (roughly some 64 KB, 2 seconds).

{read_ahead, Size} - Activates read data buffering. If read/2 calls are for significantly less than Size bytes, read operations to the operating system are still performed for blocks of Size bytes. The extra data is buffered and returned in subsequent read/2 calls, giving a performance gain as the number of operating system calls is reduced.

The read_ahead buffer is also highly used by function read_line/1 in raw mode, therefore this option is recommended (for performance reasons) when accessing raw files using that function.

If read/2 calls are for sizes not significantly less than, or even greater than Size bytes, no performance gain can be expected.

read_ahead - The same as {read_ahead, Size} with a reasonable default value for Size (roughly some 64 KB).

compressed - Makes it possible to read or write gzip compressed files. Option compressed must be combined with read or write, but not both. Notice that the file size obtained with read_file_info/1 does probably not match the number of bytes that can be read from a compressed file.

{zstd, Opts} - Makes it possible to read or write zstd compressed files. Option compressed must be combined with read or write, but not both. Notice that the file size obtained with read_file_info/1 does probably not match the number of bytes that can be read from a compressed file.

compressed_one - Read one member of a gzip compressed file. Option compressed_one can only be combined with read.

{encoding, Encoding} - Makes the file perform automatic translation of characters to and from a specific (Unicode) encoding. Notice that the data supplied to write/2 or returned by read/2 still is byte-oriented; this option denotes only how data is stored in the disk file.

Depending on the encoding, different methods of reading and writing data is preferred. The default encoding of latin1 implies using this module (file) for reading and writing data as the interfaces provided here work with byte-oriented data. Using other (Unicode) encodings makes the io functions get_chars, get_line, and put_chars more suitable, as they can work with the full Unicode range.

If data is sent to an io_device/0 in a format that cannot be converted to the specified encoding, or if data is read by a function that returns data in a format that cannot cope with the character range of the data, an error occurs and the file is closed.

Allowed values for Encoding:

latin1 - The default encoding. Bytes supplied to the file, that is, write/2 are written "as is" on the file. Likewise, bytes read from the file, that is, read/2 are returned "as is". If module io is used for writing, the file can only cope with Unicode characters up to code point 255 (the ISO Latin-1 range).

unicode or utf8 - Characters are translated to and from UTF-8 encoding before they are written to or read from the file. A file opened in this way can be readable using function read/2, as long as no data stored on the file lies beyond the ISO Latin-1 range (0..255), but failure occurs if the data contains Unicode code points beyond that range. The file is best read with the functions in the Unicode aware module io.

Bytes written to the file by any means are translated to UTF-8 encoding before being stored on the disk file.

utf16 or {utf16,big} - Works like unicode, but translation is done to and from big endian UTF-16 instead of UTF-8.

{utf16,little} - Works like unicode, but translation is done to and from little endian UTF-16 instead of UTF-8.

utf32 or {utf32,big} - Works like unicode, but translation is done to and from big endian UTF-32 instead of UTF-8.

{utf32,little} - Works like unicode, but translation is done to and from little endian UTF-32 instead of UTF-8.

The Encoding can be changed for a file "on the fly" by using function io:setopts/2. So a file can be analyzed in latin1 encoding for, for example, a BOM, positioned beyond the BOM and then be set for the right encoding before further reading. For functions identifying BOMs, see module unicode.

This option is not allowed on raw files.

ram - File must be iodata/0. Returns an fd/0, which lets module file operate on the data in-memory as if it is a file.

sync - On platforms supporting it, enables the POSIX O_SYNC synchronous I/O flag or its platform-dependent equivalent (for example, FILE_FLAG_WRITE_THROUGH on Windows) so that writes to the file block until the data is physically written to disk. However, be aware that the exact semantics of this flag differ from platform to platform. For example, none of Linux or Windows guarantees that all file metadata are also written before the call returns. For precise semantics, check the details of your platform documentation. On platforms with no support for POSIX O_SYNC or equivalent, use of the sync flag causes open to return {error, enotsup}.

directory - Allows open to work on directories.

Returns:

{ok, IoDevice} - The file is opened in the requested mode. IoDevice is a reference to the file.

{error, Reason} - The file cannot be opened.

IoDevice is really the pid of the process that handles the file. This process monitors the process that originally opened the file (the owner process). If the owner process terminates, the file is closed and the process itself terminates too. An IoDevice returned from this call can be used as an argument to the I/O functions (see io).

Warning

While this function can be used to open any file, we recommend against using it for NFS-mounted files, FIFOs, devices, or similar since they can cause IO threads to hang forever.

If your application needs to interact with these kinds of files we recommend breaking out those parts to a port program instead.

Note

In previous versions of file, modes were specified as one of the atoms read, write, or read_write instead of a list. This is still allowed for reasons of backwards compatibility, but is not to be used for new code. Also note that read_write is not allowed in a mode list.

Typical error reasons:

enoent - The file does not exist.

eacces - Missing permission for reading the file or searching one of the parent directories.

eisdir - The named file is a directory.

enotdir - A component of the filename is not a directory, or the filename itself is not a directory if directory mode was specified. On some platforms, enoent is returned instead.

enospc - There is no space left on the device (if write access was specified).

path_consult(Path, Filename)

-spec path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason}
                      when
                          Path :: [Dir],
                          Dir :: name_all(),
                          Filename :: name_all(),
                          Terms :: [term()],
                          FullName :: filename_all(),
                          Reason ::
                              posix() |
                              badarg | terminated | system_limit |
                              {Line :: integer(), Mod :: module(), Term :: term()}.

Searches the path Path (a list of directory names) until the file Filename is found. If Filename is an absolute filename, Path is ignored. Then reads Erlang terms, separated by ., from the file.

Returns one of the following:

{ok, Terms, FullName} - The file is successfully read. FullName is the full name of the file.

{error, enoent} - The file cannot be found in any of the directories in Path.

{error, atom()} - An error occurred when opening the file or reading it. For a list of typical error codes, see open/2.

{error, {Line, Mod, Term}} - An error occurred when interpreting the Erlang terms in the file. Use format_error/1 to convert the three-element tuple to an English description of the error.

The encoding of Filename can be set by a comment as described in epp.

path_eval(Path, Filename)

-spec path_eval(Path, Filename) -> {ok, FullName} | {error, Reason}
                   when
                       Path :: [Dir :: name_all()],
                       Filename :: name_all(),
                       FullName :: filename_all(),
                       Reason ::
                           posix() |
                           badarg | terminated | system_limit |
                           {Line :: integer(), Mod :: module(), Term :: term()}.

Searches the path Path (a list of directory names) until the file Filename is found. If Filename is an absolute filename, Path is ignored. Then reads and evaluates Erlang expressions, separated by . (or ,, a sequence of expressions is also an expression), from the file. The result of evaluation is not returned; any expression sequence in the file must be there for its side effect.

Returns one of the following:

{ok, FullName} - The file is read and evaluated. FullName is the full name of the file.

{error, enoent} - The file cannot be found in any of the directories in Path.

{error, atom()} - An error occurred when opening the file or reading it. For a list of typical error codes, see open/2.

{error, {Line, Mod, Term}} - An error occurred when interpreting the Erlang expressions in the file. Use format_error/1 to convert the three-element tuple to an English description of the error.

The encoding of Filename can be set by a comment as described in epp.

path_open(Path, Filename, Modes)

-spec path_open(Path, Filename, Modes) -> {ok, IoDevice, FullName} | {error, Reason}
                   when
                       Path :: [Dir :: name_all()],
                       Filename :: name_all(),
                       Modes :: [mode() | directory],
                       IoDevice :: io_device(),
                       FullName :: filename_all(),
                       Reason :: posix() | badarg | system_limit.

Searches the path Path (a list of directory names) until the file Filename is found. If Filename is an absolute filename, Path is ignored. Then opens the file in the mode determined by Modes.

Returns one of the following:

{ok, IoDevice, FullName} - The file is opened in the requested mode. IoDevice is a reference to the file and FullName is the full name of the file.

{error, enoent} - The file cannot be found in any of the directories in Path.

{error, atom()} - The file cannot be opened.

path_script(Path, Filename)

-spec path_script(Path, Filename) -> {ok, Value, FullName} | {error, Reason}
                     when
                         Path :: [Dir :: name_all()],
                         Filename :: name_all(),
                         Value :: term(),
                         FullName :: filename_all(),
                         Reason ::
                             posix() |
                             badarg | terminated | system_limit |
                             {Line :: integer(), Mod :: module(), Term :: term()}.

Searches the path Path (a list of directory names) until the file Filename is found. If Filename is an absolute filename, Path is ignored. Then reads and evaluates Erlang expressions, separated by . (or ,, a sequence of expressions is also an expression), from the file.

Returns one of the following:

{ok, Value, FullName} - The file is read and evaluated. FullName is the full name of the file and Value the value of the last expression.

{error, enoent} - The file cannot be found in any of the directories in Path.

{error, atom()} - An error occurred when opening the file or reading it. For a list of typical error codes, see open/2.

{error, {Line, Mod, Term}} - An error occurred when interpreting the Erlang expressions in the file. Use format_error/1 to convert the three-element tuple to an English description of the error.

The encoding of Filename can be set by a comment as described in epp.

path_script(Path, Filename, Bindings)

-spec path_script(Path, Filename, Bindings) -> {ok, Value, FullName} | {error, Reason}
                     when
                         Path :: [Dir :: name_all()],
                         Filename :: name_all(),
                         Bindings :: erl_eval:binding_struct(),
                         Value :: term(),
                         FullName :: filename_all(),
                         Reason ::
                             posix() |
                             badarg | terminated | system_limit |
                             {Line :: integer(), Mod :: module(), Term :: term()}.

The same as path_script/2 but the variable bindings Bindings are used in the evaluation. See erl_eval about variable bindings.

position(IoDevice, Location)

-spec position(IoDevice, Location) -> {ok, NewPosition} | {error, Reason}
                  when
                      IoDevice :: io_device(),
                      Location :: location(),
                      NewPosition :: integer(),
                      Reason :: posix() | badarg | terminated.

Sets the position of the file referenced by IoDevice to Location. Returns {ok, NewPosition} (as absolute offset) if successful, otherwise {error, Reason}. Location is one of the following:

Offset - The same as {bof, Offset}.

{bof, Offset} - Absolute offset.

{cur, Offset} - Offset from the current position.

{eof, Offset} - Offset from the end of file.

bof | cur | eof - The same as above with Offset 0.

Notice that offsets are counted in bytes, not in characters. If the file is opened using some other encoding than latin1, one byte does not correspond to one character. Positioning in such a file can only be done to known character boundaries. That is, to a position earlier retrieved by getting a current position, to the beginning/end of the file or to some other position known to be on a correct character boundary by some other means (typically beyond a byte order mark in the file, which has a known byte-size).

A typical error reason is:

einval - Either Location is illegal, or it is evaluated to a negative offset in the file. Notice that if the resulting position is a negative value, the result is an error, and after the call the file position is undefined.

pread(IoDevice, LocNums)

-spec pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason}
               when
                   IoDevice :: io_device(),
                   LocNums :: [{Location :: location(), Number :: non_neg_integer()}],
                   DataL :: [Data],
                   Data :: string() | binary() | eof,
                   Reason :: posix() | badarg | terminated.

Performs a sequence of pread/3 in one operation, which is more efficient than calling them one at a time. Returns {ok, [Data, ...]} or {error, Reason}, where each Data, the result of the corresponding pread, is either a list or a binary depending on the mode of the file, or eof if the requested position is beyond end of file.

As the position is specified as a byte-offset, take special caution when working with files where encoding is set to something else than latin1, as not every byte position is a valid character boundary on such a file.

pread(IoDevice, Location, Number)

-spec pread(IoDevice, Location, Number) -> {ok, Data} | eof | {error, Reason}
               when
                   IoDevice :: io_device(),
                   Location :: location(),
                   Number :: non_neg_integer(),
                   Data :: string() | binary(),
                   Reason :: posix() | badarg | terminated.

Combines position/2 and read/2 in one operation, which is more efficient than calling them one at a time.

Location is only allowed to be an integer for raw and ram modes.

The current position of the file after the operation is undefined for raw mode and unchanged for ram mode.

As the position is specified as a byte-offset, take special caution when working with files where encoding is set to something else than latin1, as not every byte position is a valid character boundary on such a file.

pwrite(IoDevice, LocBytes)

-spec pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}}
                when
                    IoDevice :: io_device(),
                    LocBytes :: [{Location :: location(), Bytes :: iodata()}],
                    N :: non_neg_integer(),
                    Reason :: posix() | badarg | terminated.

Performs a sequence of pwrite/3 in one operation, which is more efficient than calling them one at a time. Returns ok or {error, {N, Reason}}, where N is the number of successful writes done before the failure.

When positioning in a file with other encoding than latin1, caution must be taken to set the position on a correct character boundary. For details, see position/2.

pwrite(IoDevice, Location, Bytes)

-spec pwrite(IoDevice, Location, Bytes) -> ok | {error, Reason}
                when
                    IoDevice :: io_device(),
                    Location :: location(),
                    Bytes :: iodata(),
                    Reason :: posix() | badarg | terminated.

Combines position/2 and write/2 in one operation, which is more efficient than calling them one at a time.

Location is only allowed to be an integer for raw and ram modes.

The current position of the file after the operation is undefined for raw mode and unchanged for ram mode.

When positioning in a file with other encoding than latin1, caution must be taken to set the position on a correct character boundary. For details, see position/2.

read(IoDevice, Number)

-spec read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason}
              when
                  IoDevice :: io_device() | io:device(),
                  Number :: non_neg_integer(),
                  Data :: string() | binary(),
                  Reason :: posix() | badarg | terminated | {no_translation, unicode, latin1}.

Reads Number bytes/characters from the file referenced by IoDevice.

The functions read/2, pread/3, and read_line/1 are the only ways to read from a file opened in raw mode (although they work for normally opened files, too).

For files where encoding is set to something else than latin1, one character can be represented by more than one byte on the file. The parameter Number always denotes the number of characters read from the file, while the position in the file can be moved much more than this number when reading a Unicode file.

Also, if encoding is set to something else than latin1, the read/2 call fails if the data contains characters larger than 255, which is why io:get_chars/3 is to be preferred when reading such a file.

The function returns:

{ok, Data} - If the file was opened in binary mode, the read bytes are returned in a binary, otherwise in a list. The list or binary is shorter than the number of bytes requested if end of file was reached.

eof - Returned if Number>0 and end of file was reached before anything at all could be read.

{error, Reason} - An error occurred.

Typical error reasons:

ebadf - The file is not opened for reading.

{no_translation, unicode, latin1} - The file is opened with another encoding than latin1 and the data in the file cannot be translated to the byte-oriented data that this function returns.

read_file(Filename)

-spec read_file(Filename) -> {ok, Binary} | {error, Reason}
                   when
                       Filename :: name_all(),
                       Binary :: binary(),
                       Reason :: posix() | badarg | terminated | system_limit.

Equivalent to read_file(Filename, []).

read_file(Filename, Opts)

(since OTP 27.0)

-spec read_file(Filename, Opts) -> {ok, Binary} | {error, Reason}
                   when
                       Filename :: name_all(),
                       Opts :: [read_file_option()],
                       Binary :: binary(),
                       Reason :: posix() | badarg | terminated | system_limit.

Returns {ok, Binary}, where Binary is a binary data object that contains the contents of Filename, or {error, Reason} if an error occurs.

If the option raw is set, the file server is not called.

Typical error reasons:

enoent - The file does not exist.

eacces - Missing permission for reading the file, or for searching one of the parent directories.

eisdir - The named file is a directory.

enotdir - A component of the filename is not a directory. On some platforms, enoent is returned instead.

enomem - There is not enough memory for the contents of the file.

read_file_info(File)

-spec read_file_info(File) -> {ok, FileInfo} | {error, Reason}
                        when
                            File :: name_all() | io_device(),
                            FileInfo :: file_info(),
                            Reason :: posix() | badarg.

Equivalent to read_file_info(File, []).

read_file_info(File, Opts)

(since OTP R15B)

-spec read_file_info(File, Opts) -> {ok, FileInfo} | {error, Reason}
                        when
                            File :: name_all() | io_device(),
                            Opts :: [file_info_option()],
                            FileInfo :: file_info(),
                            Reason :: posix() | badarg.

Retrieves information about a file. Returns {ok, FileInfo} if successful, otherwise {error, Reason}.

FileInfo is a record file_info, defined in the Kernel include file file.hrl. Include the following directive in the module from which the function is called:

-include_lib("kernel/include/file.hrl").

The time type returned in atime, mtime, and ctime is dependent on the time type set in Opts :: {time, Type} as follows:

local - Returns local time.

universal - Returns universal time.

posix - Returns seconds since or before Unix time epoch, which is 1970-01-01 00:00 UTC.

Default is {time, local}.

If the option raw is set, the file server is not called and only information about local files is returned. Note that this will break this module's atomicity guarantees as it can race with a concurrent call to write_file_info/1,2 .

This option has no effect when the function is given an I/O device instead of a file name. Use open/2 with the raw mode to obtain a file descriptor first.

Note

As file times are stored in POSIX time on most OS, it is faster to query file information with option posix.

The record file_info contains the following fields:

size = non_neg_integer/0 - Size of file in bytes.

type = device | directory | other | regular - The type of the file. Can also contain symlink when returned from read_link_info/1,2.

access = read | write | read_write | none - The current system access to the file.

atime = date_time/0 | non_neg_integer/0 - The last time the file was read.

mtime = date_time/0 | non_neg_integer/0 - The last time the file was written.

ctime = date_time/0 | non_neg_integer/0 - The interpretation of this time field depends on the operating system. On Unix, it is the last time the file or the inode was changed. In Windows, it is the create time.

mode = non_neg_integer/0 - The file permissions as the sum of the following bit values:

8#00400 - read permission: owner

8#00200 - write permission: owner

8#00100 - execute permission: owner

8#00040 - read permission: group

8#00020 - write permission: group

8#00010 - execute permission: group

8#00004 - read permission: other

8#00002 - write permission: other

8#00001 - execute permission: other

16#800 - set user id on execution

16#400 - set group id on execution

On Unix platforms, other bits than those listed above may be set.

links = non_neg_integer/0 - Number of links to the file (this is always 1 for file systems that have no concept of links).

major_device = non_neg_integer/0 - Identifies the file system where the file is located. In Windows, the number indicates a drive as follows: 0 means A:, 1 means B:, and so on.

minor_device = non_neg_integer/0 - Only valid for character devices on Unix. In all other cases, this field is zero.

inode = non_neg_integer/0 - Gives the inode number. On non-Unix file systems, this field is zero.

uid = non_neg_integer/0 - Indicates the owner of the file. On non-Unix file systems, this field is zero.

gid = non_neg_integer/0 - Gives the group that the owner of the file belongs to. On non-Unix file systems, this field is zero.

Typical error reasons:

eacces - Missing search permission for one of the parent directories of the file.

enoent - The file does not exist.

enotdir - A component of the filename is not a directory. On some platforms, enoent is returned instead.

read_line(IoDevice)

-spec read_line(IoDevice) -> {ok, Data} | eof | {error, Reason}
                   when
                       IoDevice :: io_device() | io:device(),
                       Data :: string() | binary(),
                       Reason :: posix() | badarg | terminated | {no_translation, unicode, latin1}.

Reads a line of bytes/characters from the file referenced by IoDevice.

Lines are defined to be delimited by the linefeed (LF, \n) character, but any carriage return (CR, \r) followed by a newline is also treated as a single LF character (the carriage return is silently ignored). The line is returned including the LF, but excluding any CR immediately followed by an LF. This behaviour is consistent with the behaviour of io:get_line/2. If end of file is reached without any LF ending the last line, a line with no trailing LF is returned.

The function can be used on files opened in raw mode. However, it is inefficient to use it on raw files if the file is not opened with option {read_ahead, Size} specified. Thus, combining raw and {read_ahead, Size} is highly recommended when opening a text file for raw line-oriented reading.

If encoding is set to something else than latin1, the read_line/1 call fails if the data contains characters larger than 255, why io:get_line/2 is to be preferred when reading such a file.

The function returns:

{ok, Data} - One line from the file is returned, including the trailing LF, but with CRLF sequences replaced by a single LF (see above).

If the file is opened in binary mode, the read bytes are returned in a binary, otherwise in a list.

eof - Returned if end of file was reached before anything at all could be read.

{error, Reason} - An error occurred.

Typical error reasons:

ebadf - The file is not opened for reading.

{no_translation, unicode, latin1} - The file is opened with another encoding than latin1 and the data on the file cannot be translated to the byte-oriented data that this function returns.

read_link(Name)

-spec read_link(Name) -> {ok, Filename} | {error, Reason}
                   when Name :: name_all(), Filename :: filename(), Reason :: posix() | badarg.

Returns {ok, Filename} if Name refers to a symbolic link that is not a raw filename, or {error, Reason} otherwise. On platforms that do not support symbolic links, the return value is {error,enotsup}.

Typical error reasons:

einval - Name does not refer to a symbolic link or the name of the file that it refers to does not conform to the expected encoding.

enoent - The file does not exist.

enotsup - Symbolic links are not supported on this platform.

read_link_all(Name)

(since OTP R16B)

-spec read_link_all(Name) -> {ok, Filename} | {error, Reason}
                       when Name :: name_all(), Filename :: filename_all(), Reason :: posix() | badarg.

Returns {ok, Filename} if Name refers to a symbolic link or {error, Reason} otherwise. On platforms that do not support symbolic links, the return value is {error, enotsup}.

Notice that Filename can be either a list or a binary.

Typical error reasons:

einval - Name does not refer to a symbolic link.

enoent - The file does not exist.

enotsup - Symbolic links are not supported on this platform.

read_link_info(Name)

-spec read_link_info(Name) -> {ok, FileInfo} | {error, Reason}
                        when Name :: name_all(), FileInfo :: file_info(), Reason :: posix() | badarg.

Equivalent to read_link_info(Name, []).

read_link_info(Name, Opts)

(since OTP R15B)

-spec read_link_info(Name, Opts) -> {ok, FileInfo} | {error, Reason}
                        when
                            Name :: name_all(),
                            Opts :: [file_info_option()],
                            FileInfo :: file_info(),
                            Reason :: posix() | badarg.

Works like read_file_info/1,2 except that if Name is a symbolic link, information about the link is returned in the file_info record and the type field of the record is set to symlink.

If the option raw is set, the file server is not called and only information about local files is returned. Note that this will break this module's atomicity guarantees as it can race with a concurrent call to write_file_info/1,2

If Name is not a symbolic link, this function returns the same result as read_file_info/1. On platforms that do not support symbolic links, this function is always equivalent to read_file_info/1.

rename(Source, Destination)

-spec rename(Source, Destination) -> ok | {error, Reason}
                when Source :: name_all(), Destination :: name_all(), Reason :: posix() | badarg.

Tries to rename the file Source to Destination. It can be used to move files (and directories) between directories, but it is not sufficient to specify the destination only. The destination filename must also be specified. For example, if bar is a normal file and foo and baz are directories, rename("foo/bar", "baz") returns an error, but rename("foo/bar", "baz/bar") succeeds. Returns ok if it is successful.

Note

Renaming of open files is not allowed on most platforms (see eacces below).

Typical error reasons:

eacces - Missing read or write permissions for the parent directories of Source or Destination. On some platforms, this error is given if either Source or Destination is open.

eexist - Destination is not an empty directory. On some platforms, also given when Source and Destination are not of the same type.

einval - Source is a root directory, or Destination is a subdirectory of Source.

eisdir - Destination is a directory, but Source is not.

enoent - Source does not exist.

enotdir - Source is a directory, but Destination is not.

exdev - Source and Destination are on different file systems.

script(Filename)

-spec script(Filename) -> {ok, Value} | {error, Reason}
                when
                    Filename :: name_all(),
                    Value :: term(),
                    Reason ::
                        posix() |
                        badarg | terminated | system_limit |
                        {Line :: integer(), Mod :: module(), Term :: term()}.

Reads and evaluates Erlang expressions, separated by . (or ,, a sequence of expressions is also an expression), from the file.

Returns one of the following:

{ok, Value} - The file is read and evaluated. Value is the value of the last expression.

{error, atom()} - An error occurred when opening the file or reading it. For a list of typical error codes, see open/2.

{error, {Line, Mod, Term}} - An error occurred when interpreting the Erlang expressions in the file. Use format_error/1 to convert the three-element tuple to an English description of the error.

The encoding of Filename can be set by a comment as described in epp.

script(Filename, Bindings)

-spec script(Filename, Bindings) -> {ok, Value} | {error, Reason}
                when
                    Filename :: name_all(),
                    Bindings :: erl_eval:binding_struct(),
                    Value :: term(),
                    Reason ::
                        posix() |
                        badarg | terminated | system_limit |
                        {Line :: integer(), Mod :: module(), Term :: term()}.

The same as script/1 but the variable bindings Bindings are used in the evaluation. See erl_eval about variable bindings.

sendfile(Filename, Socket)

(since OTP R15B)

-spec sendfile(Filename, Socket) ->
                  {ok, non_neg_integer()} | {error, inet:posix() | closed | badarg | not_owner}
                  when
                      Filename :: name_all(),
                      Socket ::
                          inet:socket() |
                          socket:socket() |
                          fun((iolist()) -> ok | {error, inet:posix() | closed}).

Sends the file Filename to Socket. Returns {ok, BytesSent} if successful, otherwise {error, Reason}.

sendfile(RawFile, Socket, Offset, Bytes, Opts)

(since OTP R15B)

-spec sendfile(RawFile, Socket, Offset, Bytes, Opts) ->
                  {ok, non_neg_integer()} | {error, inet:posix() | closed | badarg | not_owner}
                  when
                      RawFile :: fd(),
                      Socket ::
                          inet:socket() |
                          socket:socket() |
                          fun((iolist()) -> ok | {error, inet:posix() | closed}),
                      Offset :: non_neg_integer(),
                      Bytes :: non_neg_integer(),
                      Opts :: [sendfile_option()].

Sends Bytes from the file referenced by RawFile beginning at Offset to Socket. Returns {ok, BytesSent} if successful, otherwise {error, Reason}. If Bytes is set to 0 all data after the specified Offset is sent.

The file used must be opened using the raw flag, and the process calling sendfile must be the controlling process of the socket. See gen_tcp:controlling_process/2 or module socket's level otp socket option controlling_process.

If the OS used does not support non-blocking sendfile, an Erlang fallback using read/2 and gen_tcp:send/2 is used.

The option list can contain the following options:

chunk_size - The chunk size used by the Erlang fallback to send data. If using the fallback, set this to a value that comfortably fits in the systems memory. Default is 20 MB.

set_cwd(Dir)

-spec set_cwd(Dir) -> ok | {error, Reason}
                 when
                     Dir :: name() | EncodedBinary,
                     EncodedBinary :: binary(),
                     Reason :: posix() | badarg | no_translation.

Sets the current working directory of the file server to Dir. Returns ok if successful.

The functions in the module file usually treat binaries as raw filenames, that is, they are passed "as is" even when the encoding of the binary does not agree with native_name_encoding(). However, this function expects binaries to be encoded according to the value returned by native_name_encoding/0.

Typical error reasons are:

enoent - The directory does not exist.

enotdir - A component of Dir is not a directory. On some platforms, enoent is returned.

eacces - Missing permission for the directory or one of its parents.

badarg - Dir has an improper type, such as tuple.

no_translation - Dir is a binary/0 with characters coded in ISO-latin-1 and the VM is operating with unicode filename encoding.

Warning

In a future release, a bad type for argument Dir will probably generate an exception.

sync(IoDevice)

-spec sync(IoDevice) -> ok | {error, Reason}
              when IoDevice :: io_device(), Reason :: posix() | badarg | terminated.

Ensures that any buffers kept by the operating system (not by the Erlang runtime system) are written to disk. On some platforms, this function might have no effect.

A typical error reason is:

enospc - Not enough space left to write the file.

truncate(IoDevice)

-spec truncate(IoDevice) -> ok | {error, Reason}
                  when IoDevice :: io_device(), Reason :: posix() | badarg | terminated.

Truncates the file referenced by IoDevice at the current position. Returns ok if successful, otherwise {error, Reason}.

write(IoDevice, Bytes)

-spec write(IoDevice, Bytes) -> ok | {error, Reason}
               when
                   IoDevice :: io_device() | io:device(),
                   Bytes :: iodata(),
                   Reason :: posix() | badarg | terminated.

Writes Bytes to the file referenced by IoDevice. This function is the only way to write to a file opened in raw mode (although it works for normally opened files too). Returns ok if successful, and {error, Reason} otherwise.

If the file is opened with encoding set to something else than latin1, each byte written can result in many bytes being written to the file, as the byte range 0..255 can represent anything between one and four bytes depending on value and UTF encoding type. If you want to write unicode:chardata/0 to the IoDevice you should use io:put_chars/2 instead.

Typical error reasons:

ebadf - The file is not opened for writing.

enospc - No space is left on the device.

write_file(Filename, Bytes)

-spec write_file(Filename, Bytes) -> ok | {error, Reason}
                    when
                        Filename :: name_all(),
                        Bytes :: iodata(),
                        Reason :: posix() | badarg | terminated | system_limit.

Writes the contents of the iodata term Bytes to file Filename. The file is created if it does not exist. If it exists, the previous contents are overwritten. Returns ok if successful, otherwise {error, Reason}.

Typical error reasons:

enoent - A component of the filename does not exist.

enotdir - A component of the filename is not a directory. On some platforms, enoent is returned instead.

enospc - No space is left on the device.

eacces - Missing permission for writing the file or searching one of the parent directories.

eisdir - The named file is a directory.

write_file(Filename, Bytes, Modes)

-spec write_file(Filename, Bytes, Modes) -> ok | {error, Reason}
                    when
                        Filename :: name_all(),
                        Bytes :: iodata(),
                        Modes :: [mode()],
                        Reason :: posix() | badarg | terminated | system_limit.

Same as write_file/2, but takes a third argument Modes, a list of possible modes, see open/2. The mode flags binary and write are implicit, so they are not to be used.

write_file_info(Filename, FileInfo)

-spec write_file_info(Filename, FileInfo) -> ok | {error, Reason}
                         when
                             Filename :: name_all(), FileInfo :: file_info(), Reason :: posix() | badarg.

Equivalent to write_file_info(Filename, FileInfo, []).

write_file_info(Filename, FileInfo, Opts)

(since OTP R15B)

-spec write_file_info(Filename, FileInfo, Opts) -> ok | {error, Reason}
                         when
                             Filename :: name_all(),
                             Opts :: [file_info_option()],
                             FileInfo :: file_info(),
                             Reason :: posix() | badarg.

Changes file information. Returns ok if successful, otherwise {error, Reason}.

FileInfo is a record file_info, defined in the Kernel include file file.hrl. Include the following directive in the module from which the function is called:

-include_lib("kernel/include/file.hrl").

The time type set in atime, mtime, and ctime depends on the time type set in Opts :: {time, Type} as follows:

local - Interprets the time set as local.

universal - Interprets it as universal time.

posix - Must be seconds since or before Unix time epoch, which is 1970-01-01 00:00 UTC.

Default is {time, local}.

If the option raw is set, the file server is not called and only information about local files is returned.

The following fields are used from the record, if they are specified:

atime = date_time/0 | non_neg_integer/0 - The last time the file was read.

mtime = date_time/0 | non_neg_integer/0 - The last time the file was written.

ctime = date_time/0 | non_neg_integer/0 - On Unix, any value specified for this field is ignored (the "ctime" for the file is set to the current time). On Windows, this field is the new creation time to set for the file.

mode = non_neg_integer/0 - The file permissions as the sum of the following bit values:

8#00400 - Read permission: owner

8#00200 - Write permission: owner

8#00100 - Execute permission: owner

8#00040 - Read permission: group

8#00020 - Write permission: group

8#00010 - Execute permission: group

8#00004 - Read permission: other

8#00002 - Write permission: other

8#00001 - Execute permission: other

16#800 - Set user id on execution

16#400 - Set group id on execution

On Unix platforms, other bits than those listed above may be set.

uid = non_neg_integer/0 - Indicates the file owner. Ignored for non-Unix file systems.

gid = non_neg_integer/0 - Gives the group that the file owner belongs to. Ignored for non-Unix file systems.

Typical error reasons:

eacces - Missing search permission for one of the parent directories of the file.

enoent - The file does not exist.

enotdir - A component of the filename is not a directory. On some platforms, enoent is returned instead.

heart

Heartbeat monitoring of an Erlang runtime system.

This modules contains the interface to the heart process. heart sends periodic heartbeats to an external port program, which is also named heart. The purpose of the heart port program is to check that the Erlang runtime system it is supervising is still running. If the port program has not received any heartbeats within HEART_BEAT_TIMEOUT seconds (defaults to 60 seconds), the system can be rebooted.

An Erlang runtime system to be monitored by a heart program is to be started with command-line flag -heart (see also erl(1)). The heart process is then started automatically:

% erl -heart ...

If the system is to be rebooted because of missing heartbeats, or a terminated Erlang runtime system, environment variable HEART_COMMAND must be set before the system is started. If this variable is not set, a warning text is printed but the system does not reboot.

To reboot on Windows, HEART_COMMAND can be set to heart -shutdown (included in the Erlang delivery) or to any other suitable program that can activate a reboot.

The environment variable HEART_BEAT_TIMEOUT can be used to configure the heart time-outs; it can be set in the operating system shell before Erlang is started or be specified at the command line:

% erl -heart -env HEART_BEAT_TIMEOUT 30 ...

The value (in seconds) must be in the range 10 < X <= 65535.

When running on OSs lacking support for monotonic time, heart is susceptible to system clock adjustments of more than HEART_BEAT_TIMEOUT seconds. When this happens, heart times out and tries to reboot the system. This can occur, for example, if the system clock is adjusted automatically by use of the Network Time Protocol (NTP).

If a crash occurs, an erl_crash.dump is not written unless environment variable ERL_CRASH_DUMP_SECONDS is set:

% erl -heart -env ERL_CRASH_DUMP_SECONDS 10 ...

If a regular core dump is wanted, let heart know by setting the kill signal to abort using environment variable HEART_KILL_SIGNAL=SIGABRT. If unset, or not set to SIGABRT, the default behavior is a kill signal using SIGKILL:

% erl -heart -env HEART_KILL_SIGNAL SIGABRT ...

If heart should not kill the Erlang runtime system, this can be indicated using the environment variable HEART_NO_KILL=TRUE. This can be useful if the command executed by heart takes care of this, for example as part of a specific cleanup sequence. If unset, or not set to TRUE, the default behaviour will be to kill as described above.

% erl -heart -env HEART_NO_KILL 1 ...

Furthermore, ERL_CRASH_DUMP_SECONDS has the following behavior on heart:

ERL_CRASH_DUMP_SECONDS=0 - Suppresses the writing of a crash dump file entirely, thus rebooting the runtime system immediately. This is the same as not setting the environment variable.

ERL_CRASH_DUMP_SECONDS=-1 - Setting the environment variable to a negative value does not reboot the runtime system until the crash dump file is completely written.

ERL_CRASH_DUMP_SECONDS=S - heart waits for S seconds to let the crash dump file be written. After S seconds, heart reboots the runtime system, whether the crash dump file is written or not.

In the following descriptions, all functions fail with reason badarg if heart is not started.

Summary

Types

heart_option()

Functions

clear_callback()

Removes the validation callback call before heartbeats.

clear_cmd()

Clears the temporary boot command. If the system terminates, the normal HEART_COMMAND is used to reboot.

get_callback()

Get the validation callback. If the callback is cleared, none will be returned.

get_cmd()

Gets the temporary reboot command. If the command is cleared, the empty string is returned.

get_options()

Returns {ok, Options} where Options is a list of current options enabled for heart. If the callback is cleared, none will be returned.

set_callback(Module, Function)

This validation callback will be executed before any heartbeat is sent to the port program. For the validation to succeed it needs to return with the value ok.

set_cmd(Cmd)

Sets a temporary reboot command. This command is used if a HEART_COMMAND other than the one specified with the environment variable is to be used to reboot the system. The new Erlang runtime system uses (if it misbehaves) environment variable HEART_COMMAND to reboot.

set_options(Options)

Valid options set_options are

Types

heart_option()

(not exported)

-type heart_option() :: check_schedulers.

Functions

clear_callback()

(since OTP 18.3)

-spec clear_callback() -> ok.

Removes the validation callback call before heartbeats.

clear_cmd()

-spec clear_cmd() -> ok.

Clears the temporary boot command. If the system terminates, the normal HEART_COMMAND is used to reboot.

get_callback()

(since OTP 18.3)

-spec get_callback() -> {ok, {Module, Function}} | none when Module :: atom(), Function :: atom().

Get the validation callback. If the callback is cleared, none will be returned.

get_cmd()

-spec get_cmd() -> {ok, Cmd} when Cmd :: string().

Gets the temporary reboot command. If the command is cleared, the empty string is returned.

get_options()

(since OTP 18.3)

-spec get_options() -> {ok, Options} | none when Options :: [atom()].

Returns {ok, Options} where Options is a list of current options enabled for heart. If the callback is cleared, none will be returned.

set_callback(Module, Function)

(since OTP 18.3)

-spec set_callback(Module, Function) -> ok | {error, {bad_callback, {Module, Function}}}
                      when Module :: atom(), Function :: atom().

This validation callback will be executed before any heartbeat is sent to the port program. For the validation to succeed it needs to return with the value ok.

An exception within the callback will be treated as a validation failure.

The callback will be removed if the system reboots.

set_cmd(Cmd)

-spec set_cmd(Cmd) -> ok | {error, {bad_cmd, Cmd}} when Cmd :: string().

Sets a temporary reboot command. This command is used if a HEART_COMMAND other than the one specified with the environment variable is to be used to reboot the system. The new Erlang runtime system uses (if it misbehaves) environment variable HEART_COMMAND to reboot.

Limitations: Command string Cmd is sent to the heart program as an ISO Latin-1 or UTF-8 encoded binary, depending on the filename encoding mode of the emulator (see file:native_name_encoding/0). The size of the encoded binary must be less than 2047 bytes.

set_options(Options)

(since OTP 18.3)

-spec set_options(Options) -> ok | {error, {bad_options, Options}} when Options :: [heart_option()].

Valid options set_options are:

check_schedulers - If enabled, a signal will be sent to each scheduler to check its responsiveness. The system check occurs before any heartbeat sent to the port program. If any scheduler is not responsive enough the heart program will not receive its heartbeat and thus eventually terminate the node.

Returns with the value ok if the options are valid.

os

Operating system-specific functions.

The functions in this module are operating system-specific. Careless use of these functions results in programs that will only run on a specific platform. On the other hand, with careful use, these functions can be of help in enabling a program to run on most platforms.

Note

The functions in this module will raise a badarg exception if their arguments contain invalid characters according to the description in the "Data Types" section.

Summary

Types

env_var_name()

A string containing valid characters on the specific OS for environment variable names using file:native_name_encoding() encoding.

env_var_name_value()

Assuming that environment variables has been correctly set, a strings containing valid characters on the specific OS for environment variable names and values using file:native_name_encoding() encoding.

env_var_value()

A string containing valid characters on the specific OS for environment variable values using file:native_name_encoding() encoding.

os_command()

All characters needs to be valid characters on the specific OS using file:native_name_encoding() encoding. Null characters (integer value zero) are not allowed.

os_command_opts()

Options for os:cmd/2.

Functions

cmd(Command)

Equivalent to cmd(Command, #{}).

cmd(Command, Options)

Executes Command in a command shell of the target OS, captures the standard output and standard error of the command, and returns this result as a string.

env()

Returns a list of all environment variables. Each environment variable is expressed as a tuple {VarName,Value}, where VarName is the name of the variable and Value its value.

find_executable(Name)

Equivalent to find_executable(Name, Path) where Path is the current execution path (that is, the environment variable PATH on Unix and Windows).

find_executable(Name, Path)

Look up an executable program, with the specified name and a search path, in the same way as the underlying OS.

getenv()

Returns a list of all environment variables. Each environment variable is expressed as a single string on the format "VarName=Value", where VarName is the name of the variable and Value its value.

getenv(VarName)

Returns the Value of the environment variable VarName, or false if the environment variable is undefined.

getenv(VarName, DefaultValue)

Returns the Value of the environment variable VarName, or DefaultValue if the environment variable is undefined.

getpid()

Returns the process identifier of the current Erlang emulator in the format most commonly used by the OS environment.

perf_counter()

Returns the current performance counter value in perf_counter time unit. This is a highly optimized call that might not be traceable.

perf_counter(Unit)

Returns a performance counter that can be used as a very fast and high resolution timestamp.

putenv(VarName, Value)

Sets a new Value for environment variable VarName.

set_signal(Signal, Option)

Enables or disables OS signals.

system_time()

Returns the current OS system time in native time unit.

system_time(Unit)

Returns the current OS system time converted into the Unit passed as argument.

timestamp()

Returns the current OS system time in the same format as erlang:timestamp/0.

type()

Returns the Osfamily and, in some cases, the Osname of the current OS.

unsetenv(VarName)

Deletes the environment variable VarName.

version()

Returns the OS version. On most systems, this function returns a tuple, but a string is returned instead if the system has versions that cannot be expressed as three numbers.

Types

env_var_name()

-type env_var_name() :: nonempty_string().

A string containing valid characters on the specific OS for environment variable names using file:native_name_encoding() encoding.

Null characters (integer value zero) are not allowed. On Unix, = characters are not allowed. On Windows, a = character is only allowed as the very first character in the string.

env_var_name_value()

-type env_var_name_value() :: nonempty_string().

Assuming that environment variables has been correctly set, a strings containing valid characters on the specific OS for environment variable names and values using file:native_name_encoding() encoding.

The first = characters appearing in the string separates environment variable name (on the left) from environment variable value (on the right).

env_var_value()

-type env_var_value() :: string().

A string containing valid characters on the specific OS for environment variable values using file:native_name_encoding() encoding.

Null characters (integer value zero) are not allowed.

os_command()

-type os_command() :: atom() | io_lib:chars().

All characters needs to be valid characters on the specific OS using file:native_name_encoding() encoding. Null characters (integer value zero) are not allowed.

os_command_opts()

-type os_command_opts() ::
          #{max_size => non_neg_integer() | infinity, exception_on_failure => boolean()}.

Options for os:cmd/2.

max_size - The maximum size of the data returned by the os:cmd/2 call. See the os:cmd/2 documentation for more details.

Since OTP 20.2.3

exception_on_failure - If set to true, cmd/2 will throw an error exception if the command exits with a non-zero exit code.

Since OTP 28.0

Functions

cmd(Command)

-spec cmd(Command) -> string() when Command :: os_command().

Equivalent to cmd(Command, #{}).

cmd(Command, Options)

(since OTP 20.2.3)

-spec cmd(Command, Options) -> string() when Command :: os_command(), Options :: os_command_opts().

Executes Command in a command shell of the target OS, captures the standard output and standard error of the command, and returns this result as a string.

Examples:

LsOut = os:cmd("ls"), % on unix platform
DirOut = os:cmd("dir"), % on Win32 platform

Notice that in some cases, standard output of a command when called from another program can differ, compared with the standard output of the command when called directly from an OS command shell.

The possible options are:

max_size - The maximum size of the data returned by the os:cmd/2 call. This option is a safety feature that should be used when the command executed can return a very large, possibly infinite, result.

Example:

> os:cmd("cat /dev/zero", #{ max_size => 20 }).
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

Since OTP 20.2.3

exception_on_failure - If set to true, os:cmd/2 will throw an error exception if the command exits with a non-zero exit code. The exception reason looks like this: {command_failed, ResultBeforeFailure, ExitCode} where ResultBeforeFailure is the result written to stdout by the command before the error happened and ExitCode is the exit code from the command.

Example:

> catch os:cmd("echo hello && exit 123", #{ exception_on_failure => true }).
{'EXIT',{{command_failed,"hello\n",123},
         [{os,cmd,2,[{file,"os.erl"},{line,579}]},
...

Since OTP 28.0

The command shell can be set using the kernel configuration parameter, by default the shell is detected upon system startup.

env()

(since OTP 24.0)

-spec env() -> [{env_var_name(), env_var_value()}].

Returns a list of all environment variables. Each environment variable is expressed as a tuple {VarName,Value}, where VarName is the name of the variable and Value its value.

If Unicode filename encoding is in effect (see the erl manual page), the strings can contain characters with codepoints > 255.

find_executable(Name)

-spec find_executable(Name) -> Filename | false when Name :: string(), Filename :: string().

Equivalent to find_executable(Name, Path) where Path is the current execution path (that is, the environment variable PATH on Unix and Windows).

find_executable(Name, Path)

-spec find_executable(Name, Path) -> Filename | false
                         when Name :: string(), Path :: string(), Filename :: string().

Look up an executable program, with the specified name and a search path, in the same way as the underlying OS.

Path is to conform to the syntax of execution paths on the OS. Returns the absolute filename of the executable program Name, or false if the program is not found.

getenv()

-spec getenv() -> [env_var_name_value()].

Returns a list of all environment variables. Each environment variable is expressed as a single string on the format "VarName=Value", where VarName is the name of the variable and Value its value.

If Unicode filename encoding is in effect (see the erl manual page), the strings can contain characters with codepoints > 255.

Consider using env/0 for a nicer 2-tuple format.

getenv(VarName)

-spec getenv(VarName) -> Value | false when VarName :: env_var_name(), Value :: env_var_value().

Returns the Value of the environment variable VarName, or false if the environment variable is undefined.

If Unicode filename encoding is in effect (see the erl manual page), the strings VarName and Value can contain characters with codepoints > 255.

getenv(VarName, DefaultValue)

(since OTP 18.0)

-spec getenv(VarName, DefaultValue) -> Value
                when
                    VarName :: env_var_name(), DefaultValue :: env_var_value(), Value :: env_var_value().

Returns the Value of the environment variable VarName, or DefaultValue if the environment variable is undefined.

If Unicode filename encoding is in effect (see the erl manual page), the strings VarName and Value can contain characters with codepoints > 255.

getpid()

-spec getpid() -> Value when Value :: string().

Returns the process identifier of the current Erlang emulator in the format most commonly used by the OS environment.

Returns Value as a string containing the (usually) numerical identifier for a process.

On Unix, this is typically the return value of the getpid/0 system call.

On Windows, the process id as returned by the GetCurrentProcessId() system call is used.

perf_counter()

(since OTP 19.0)

-spec perf_counter() -> Counter when Counter :: integer().

Returns the current performance counter value in perf_counter time unit. This is a highly optimized call that might not be traceable.

perf_counter(Unit)

(since OTP 19.0)

-spec perf_counter(Unit) -> integer() when Unit :: erlang:time_unit().

Returns a performance counter that can be used as a very fast and high resolution timestamp.

This counter is read directly from the hardware or operating system with the same guarantees. This means that two consecutive calls to the function are not guaranteed to be monotonic, though it most likely will be. The performance counter will be converted to the resolution passed as an argument.

1> T1 = os:perf_counter(1000),receive after 10000 -> ok end,T2 = os:perf_counter(1000).
176525861
2> T2 - T1.
10004

putenv(VarName, Value)

-spec putenv(VarName, Value) -> true when VarName :: env_var_name(), Value :: env_var_value().

Sets a new Value for environment variable VarName.

If Unicode filename encoding is in effect (see the erl manual page), the strings VarName and Value can contain characters with codepoints > 255.

On Unix platforms, the environment is set using UTF-8 encoding if Unicode filename translation is in effect. On Windows, the environment is set using wide character interfaces.

set_signal(Signal, Option)

(since OTP 20.0)

-spec set_signal(Signal, Option) -> ok
                    when
                        Signal ::
                            sighup | sigquit | sigabrt | sigalrm | sigterm | sigusr1 | sigusr2 |
                            sigchld | sigstop | sigtstp | sigcont | sigwinch | siginfo,
                        Option :: default | handle | ignore.

Enables or disables OS signals.

Each signal my be set to one of the following options:

ignore - This signal will be ignored.

default - This signal will use the default signal handler for the operating system.

handle - This signal will notify erl_signal_server when it is received by the Erlang runtime system.

system_time()

(since OTP 18.0)

-spec system_time() -> integer().

Returns the current OS system time in native time unit.

Note

This time is not a monotonically increasing time.

system_time(Unit)

(since OTP 18.0)

-spec system_time(Unit) -> integer() when Unit :: erlang:time_unit().

Returns the current OS system time converted into the Unit passed as argument.

Calling os:system_time(Unit) is equivalent to erlang:convert_time_unit(os:system_time(), native, Unit).

Note

This time is not a monotonically increasing time.

timestamp()

-spec timestamp() -> Timestamp when Timestamp :: erlang:timestamp().

Returns the current OS system time in the same format as erlang:timestamp/0.

The tuple can be used together with function calendar:now_to_universal_time/1 or calendar:now_to_local_time/1 to get calendar time. Using the calendar time, together with the MicroSecs part of the return tuple from this function, allows you to log time stamps in high resolution and consistent with the time in the rest of the OS.

Example of code formatting a string in format "DD Mon YYYY HH:MM:SS.mmmmmm", where DD is the day of month, Mon is the textual month name, YYYY is the year, HH:MM:SS is the time, and mmmmmm is the microseconds in six positions:

-module(print_time).
-export([format_utc_timestamp/0]).
format_utc_timestamp() ->
    TS = {_,_,Micro} = os:timestamp(),
    {{Year,Month,Day},{Hour,Minute,Second}} =
calendar:now_to_universal_time(TS),
    Mstr = element(Month,{"Jan","Feb","Mar","Apr","May","Jun","Jul",
    "Aug","Sep","Oct","Nov","Dec"}),
    io_lib:format("~2w ~s ~4w ~2w:~2..0w:~2..0w.~6..0w",
    [Day,Mstr,Year,Hour,Minute,Second,Micro]).

This module can be used as follows:

1> io:format("~s~n",[print_time:format_utc_timestamp()]).
29 Apr 2009  9:55:30.051711

OS system time can also be retrieved by system_time/0 and system_time/1.

type()

-spec type() -> {Osfamily, Osname} when Osfamily :: unix | win32, Osname :: atom().

Returns the Osfamily and, in some cases, the Osname of the current OS.

On Unix, Osname has the same value as uname -s returns, but in lower case. For example, on Solaris 1 and 2, it is sunos.

On Windows, Osname is nt.

Note

Think twice before using this function. Use module filename if you want to inspect or build filenames in a portable way. Avoid matching on atom Osname.

unsetenv(VarName)

(since OTP R16B03)

-spec unsetenv(VarName) -> true when VarName :: env_var_name().

Deletes the environment variable VarName.

If Unicode filename encoding is in effect (see the erl manual page), the string VarName can contain characters with codepoints > 255.

version()

-spec version() -> VersionString | {Major, Minor, Release}
                 when
                     VersionString :: string(),
                     Major :: non_neg_integer(),
                     Minor :: non_neg_integer(),
                     Release :: non_neg_integer().

Returns the OS version. On most systems, this function returns a tuple, but a string is returned instead if the system has versions that cannot be expressed as three numbers.

Note

Think twice before using this function. If you still need to use it, always call os:type() first.

gen_sctp

Interface to SCTP sockets.

This module provides functions for communicating over SCTP sockets. The implementation assumes that the OS kernel supports SCTP (RFC 2960) through the user-level Sockets API Extensions.

During development, this implementation was tested on:

Linux Fedora Core 5.0 (kernel 2.6.15-2054 or later is needed)

Solaris 10, 11

During OTP adaptation it was tested on:

SUSE Linux Enterprise Server 10 (x86_64) kernel 2.6.16.27-0.6-smp, with lksctp-tools-1.0.6

Briefly on Solaris 10

SUSE Linux Enterprise Server 10 Service Pack 1 (x86_64) kernel 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7

FreeBSD 8.2

This module was written for one-to-many style sockets (type seqpacket). With the addition of peeloff/2, one-to-one style sockets (type stream) were introduced.

Record definitions for this module can be found using:

-include_lib("kernel/include/inet_sctp.hrl").

These record definitions use the "new" spelling 'adaptation', not the deprecated 'adaption', regardless of which spelling the underlying C API uses.

SCTP Socket Options

The set of admissible SCTP socket options is by construction orthogonal to the sets of TCP, UDP, and generic inet options. Here are only options listed that are allowed for SCTP sockets.

Options can be set on the socket when calling open/1,2, and changed when calling connect/4,5 or by calling inet:setopts/2. They can be retrieved using inet:getopts/2.

{mode, list|binary} | list | binary - Determines the type of data returned from recv/1,2 or in active mode data messages.

{active, false|true|once|N}

If false (passive mode, the default), the caller must do an explicit recv call to retrieve the available data from the socket.

If true|once|N (active modes) received data or events are sent to the owning process. See open/0..2 for the message format.

If true (fully active mode) there is no flow control.

Note

Note that this can cause the message queue to overflow causing for example the virtual machine to run out of memory and crash.

If once, only one message is automatically placed in the message queue, and the mode resets to passive. This provides flow control and the possibility for the receiver to listen for incoming SCTP data interleaved with other inter-process messages.

If active is specified as an integer N in the range -32768 to 32767 (inclusive), that number is added to the socket's data messages counter. If the result of the addition is negative, the counter is set to 0. Once the counter reaches 0, either through the delivery of messages or by being explicitly set with inet:setopts/2, the socket mode resets to passive ({active, false}). When a socket in {active, N} mode transitions to passive mode, the message {sctp_passive, Socket} is sent to the controlling process to notify that if it wants to receive more data messages from the socket, it must call inet:setopts/2 to set the socket back into an active mode.

{tos, integer()} - Sets the Type-Of-Service field on the IP datagrams that are sent, to the specified value. This effectively determines a prioritization policy for the outbound packets. The acceptable values are system-dependent.

{priority, integer()} - A protocol-independent equivalent of tos above. Setting priority implies setting tos as well.

{dontroute, true|false} - Defaults to false. If true, the kernel does not send packets through any gateway, but only sends them to directly connected hosts.

{reuseaddr, true|false} - Defaults to false. If true, the local binding address {IP,Port} of the socket can be reused immediately. No waiting in state CLOSE_WAIT is performed (can be required for some types of servers).

{sndbuf, integer()} - The size, in bytes, of the OS kernel send buffer for this socket. Sending errors would occur for datagrams larger than val(sndbuf). Setting this option also adjusts the size of the driver buffer (see buffer above).

{recbuf, integer()} - The size, in bytes, of the OS kernel receive buffer for this socket. Sending errors would occur for datagrams larger than val(recbuf). Setting this option also adjusts the size of the driver buffer (see buffer above).

{non_block_send, boolean()} - A send call that would otherwise block (hang), will instead immediately return with e.g. {error, eagain} if this option has been set to true. Defaults to false.

{sctp_module, module()} - Overrides which callback module is used. Defaults to inet_sctp for IPv4 and inet6_sctp for IPv6.

{sctp_rtoinfo, #sctp_rtoinfo{}}

#sctp_rtoinfo{
      assoc_id = assoc_id(),
      initial  = integer(),
      max      = integer(),
      min      = integer()
}

Determines retransmission time-out parameters, in milliseconds, for the association(s) specified by assoc_id.

assoc_id = 0 (default) indicates the whole endpoint. See RFC 2960 and Sockets API Extensions for SCTP for the exact semantics of the field values.

{sctp_associnfo, #sctp_assocparams{}}

#sctp_assocparams{
      assoc_id                 = assoc_id(),
      asocmaxrxt               = integer(),
      number_peer_destinations = integer(),
      peer_rwnd                = integer(),
      local_rwnd               = integer(),
      cookie_life              = integer()
}

Determines association parameters for the association(s) specified by assoc_id.

assoc_id = 0 (default) indicates the whole endpoint. See Sockets API Extensions for SCTP for the discussion of their semantics. Rarely used.

{sctp_initmsg, #sctp_initmsg{}}

#sctp_initmsg{
     num_ostreams   = integer(),
     max_instreams  = integer(),
     max_attempts   = integer(),
     max_init_timeo = integer()
}

Determines the default parameters that this socket tries to negotiate with its peer while establishing an association with it. Is to be set after open/* but before the first connect/*. #sctp_initmsg{} can also be used as ancillary data with the first call of send/* to a new peer (when a new association is created).

num_ostreams - Number of outbound streams

max_instreams - Maximum number of inbound streams

max_attempts - Maximum retransmissions while establishing an association

max_init_timeo - Time-out, in milliseconds, for establishing an association

{sctp_autoclose, integer() >= 0} - Determines the time, in seconds, after which an idle association is automatically closed. 0 means that the association is never automatically closed.

{sctp_nodelay, true|false} - Turns off (true) / on (false) the Nagle algorithm for merging small packets into larger ones. This improves throughput at the expense of latency.

{sctp_disable_fragments, true|false} - If true, induces an error on an attempt to send a message larger than the current PMTU size (which would require fragmentation/reassembling). Notice that message fragmentation does not affect the logical atomicity of its delivery; this option is provided for performance reasons only.

{sctp_i_want_mapped_v4_addr, true|false} - Turns on|off automatic mapping of IPv4 addresses into IPv6 ones (if the socket address family is AF_INET6).

{sctp_maxseg, integer()} - Determines the maximum chunk size if message fragmentation is used. If 0, the chunk size is limited by the Path MTU only.

{sctp_primary_addr, #sctp_prim{}}

#sctp_prim{
      assoc_id = assoc_id(),
      addr     = {IP, Port}
}
 IP = ip_address()
 Port = port_number()

For the association specified by assoc_id, {IP,Port} must be one of the peer addresses. This option determines that the specified address is treated by the local SCTP stack as the primary address of the peer.

{sctp_set_peer_primary_addr, #sctp_setpeerprim{}}

#sctp_setpeerprim{
      assoc_id = assoc_id(),
      addr     = {IP, Port}
}
 IP = ip_address()
 Port = port_number()

When set, informs the peer to use {IP, Port} as the primary address of the local endpoint for the association specified by assoc_id.

{sctp_adaptation_layer, #sctp_setadaptation{}}

#sctp_setadaptation{
      adaptation_ind = integer()
}

When set, requests that the local endpoint uses the value specified by adaptation_ind as the Adaptation Indication parameter for establishing new associations. For details, see RFC 2960 and Sockets API Extensions for SCTP.

{sctp_peer_addr_params, #sctp_paddrparams{}}

#sctp_paddrparams{
      assoc_id   = assoc_id(),
      address    = {IP, Port},
      hbinterval = integer(),
      pathmaxrxt = integer(),
      pathmtu    = integer(),
      sackdelay  = integer(),
      flags      = list()
}
IP = ip_address()
Port = port_number()

Determines various per-address parameters for the association specified by assoc_id and the peer address address (the SCTP protocol supports multi-homing, so more than one address can correspond to a specified association).

hbinterval - Heartbeat interval, in milliseconds

pathmaxrxt - Maximum number of retransmissions before this address is considered unreachable (and an alternative address is selected)

pathmtu - Fixed Path MTU, if automatic discovery is disabled (see flags below)

sackdelay - Delay, in milliseconds, for SAC messages (if the delay is enabled, see flags below)

flags - The following flags are available:

hb_enable - Enables heartbeat

hb_disable - Disables heartbeat

hb_demand - Initiates heartbeat immediately

pmtud_enable - Enables automatic Path MTU discovery

pmtud_disable - Disables automatic Path MTU discovery

sackdelay_enable - Enables SAC delay

sackdelay_disable - Disables SAC delay

{sctp_default_send_param, #sctp_sndrcvinfo{}}

#sctp_sndrcvinfo{
      stream     = integer(),
      ssn        = integer(),
      flags      = list(),
      ppid       = integer(),
      context    = integer(),
      timetolive = integer(),
      tsn        = integer(),
      cumtsn     = integer(),
      assoc_id   = assoc_id()
}

#sctp_sndrcvinfo{} is used both in this socket option, and as ancillary data while sending or receiving SCTP messages. When set as an option, it provides default values for subsequent send calls on the association specified by assoc_id.

assoc_id = 0 (default) indicates the whole endpoint.

The following fields typically must be specified by the sender:

sinfo_stream - Stream number (0-base) within the association to send the messages through;

sinfo_flags - The following flags are recognised:

unordered - The message is to be sent unordered

addr_over - The address specified in send overwrites the primary peer address

abort - Aborts the current association without flushing any unsent data

eof - Gracefully shuts down the current association, with flushing of unsent data

Other fields are rarely used. For complete information, see RFC 2960 and Sockets API Extensions for SCTP.

{sctp_events, #sctp_event_subscribe{}}

#sctp_event_subscribe{
        data_io_event          = true | false,
        association_event      = true | false,
        address_event          = true | false,
        send_failure_event     = true | false,
        peer_error_event       = true | false,
        shutdown_event         = true | false,
        partial_delivery_event = true | false,
        adaptation_layer_event = true | false
}

This option determines which SCTP Events that are to be received (through recv/*) along with the data. The only exception is data_io_event, which enables or disables receiving of #sctp_sndrcvinfo{} ancillary data, not events. By default, all flags except adaptation_layer_event are enabled, although sctp_data_io_event and association_event are used by the driver itself and not exported to the user level.

{sctp_delayed_ack_time, #sctp_assoc_value{}}

#sctp_assoc_value{
      assoc_id    = assoc_id(),
      assoc_value = integer()
}

Rarely used. Determines the ACK time (specified by assoc_value, in milliseconds) for the specified association or the whole endpoint if assoc_value = 0 (default).

{sctp_status, #sctp_status{}}

#sctp_status{
      assoc_id            = assoc_id(),
      state               = atom(),
      rwnd                = integer(),
      unackdata           = integer(),
      penddata            = integer(),
      instrms             = integer(),
      outstrms            = integer(),
      fragmentation_point = integer(),
      primary             = #sctp_paddrinfo{}
}

This option is read-only. It determines the status of the SCTP association specified by assoc_id. The following are the possible values of state (the state designations are mostly self-explanatory):

sctp_state_empty - Default. Means that no other state is active.

sctp_state_closed

sctp_state_cookie_wait

sctp_state_cookie_echoed

sctp_state_established

sctp_state_shutdown_pending

sctp_state_shutdown_sent

sctp_state_shutdown_received

sctp_state_shutdown_ack_sent

Semantics of the other fields:

sstat_rwnd - Current receiver window size of the association

sstat_unackdata - Number of unacked data chunks

sstat_penddata - Number of data chunks pending receipt

sstat_instrms - Number of inbound streams

sstat_outstrms - Number of outbound streams

sstat_fragmentation_point - Message size at which SCTP fragmentation occurs

sstat_primary - Information on the current primary peer address (see below for the format of #sctp_paddrinfo{})

{sctp_get_peer_addr_info, #sctp_paddrinfo{}}

#sctp_paddrinfo{
      assoc_id  = assoc_id(),
      address   = {IP, Port},
      state     = inactive | active | unconfirmed,
      cwnd      = integer(),
      srtt      = integer(),
      rto       = integer(),
      mtu       = integer()
}
IP = ip_address()
Port = port_number()

This option is read-only. It determines the parameters specific to the peer address specified by address within the association specified by assoc_id. Field address fmust be set by the caller; all other fields are filled in on return. If assoc_id = 0 (default), the address is automatically translated into the corresponding association ID. This option is rarely used. For the semantics of all fields, see RFC 2960 and Sockets API Extensions for SCTP.

SCTP Examples

Example of an Erlang SCTP server that receives SCTP messages and prints them on the standard output:

-module(sctp_server).

-export([server/0,server/1,server/2]).
-include_lib("kernel/include/inet.hrl").
-include_lib("kernel/include/inet_sctp.hrl").

server() ->
    server(any, 2006).

server([Host,Port]) when is_list(Host), is_list(Port) ->
    {ok, #hostent{h_addr_list = [IP|_]}} = inet:gethostbyname(Host),
    io:format("~w -> ~w~n", [Host, IP]),
    server([IP, list_to_integer(Port)]).

server(IP, Port) when is_tuple(IP) orelse IP == any orelse IP == loopback,
                      is_integer(Port) ->
    {ok,S} = gen_sctp:open(Port, [{recbuf,65536}, {ip,IP}]),
    io:format("Listening on ~w:~w. ~w~n", [IP,Port,S]),
    ok     = gen_sctp:listen(S, true),
    server_loop(S).

server_loop(S) ->
    case gen_sctp:recv(S) of
    {error, Error} ->
        io:format("SCTP RECV ERROR: ~p~n", [Error]);
    Data ->
        io:format("Received: ~p~n", [Data])
    end,
    server_loop(S).

Example of an Erlang SCTP client interacting with the above server. Note that in this example the client creates an association with the server with 5 outbound streams. Therefore, sending of "Test 0" over stream 0 succeeds, but sending of "Test 5" over stream 5 fails. The client then aborts the association, which results in that the corresponding event is received on the server side.

-module(sctp_client).

-export([client/0, client/1, client/2]).
-include_lib("kernel/include/inet.hrl").
-include_lib("kernel/include/inet_sctp.hrl").

client() ->
    client([localhost]).

client([Host]) ->
    client(Host, 2006);

client([Host, Port]) when is_list(Host), is_list(Port) ->
    client(Host,list_to_integer(Port)),
    init:stop().

client(Host, Port) when is_integer(Port) ->
    {ok,S}     = gen_sctp:open(),
    {ok,Assoc} = gen_sctp:connect
        (S, Host, Port, [{sctp_initmsg,#sctp_initmsg{num_ostreams=5}}]),
    io:format("Connection Successful, Assoc=~p~n", [Assoc]),

    io:write(gen_sctp:send(S, Assoc, 0, <<"Test 0">>)),
    io:nl(),
    timer:sleep(10000),
    io:write(gen_sctp:send(S, Assoc, 5, <<"Test 5">>)),
    io:nl(),
    timer:sleep(10000),
    io:write(gen_sctp:abort(S, Assoc)),
    io:nl(),

    timer:sleep(1000),
    gen_sctp:close(S).

A simple Erlang SCTP client that uses the connect_init API:

-module(ex3).

-export([client/4]).
-include_lib("kernel/include/inet.hrl").
-include_lib("kernel/include/inet_sctp.hrl").

client(Peer1, Port1, Peer2, Port2)
  when is_tuple(Peer1), is_integer(Port1), is_tuple(Peer2), is_integer(Port2) ->
    {ok,S}     = gen_sctp:open(),
    SctpInitMsgOpt = {sctp_initmsg,#sctp_initmsg{num_ostreams=5}},
    ActiveOpt = {active, true},
    Opts = [SctpInitMsgOpt, ActiveOpt],
    ok = gen_sctp:connect(S, Peer1, Port1, Opts),
    ok = gen_sctp:connect(S, Peer2, Port2, Opts),
    io:format("Connections initiated~n", []),
    client_loop(S, Peer1, Port1, undefined, Peer2, Port2, undefined).

client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) ->
    receive
        {sctp, S, Peer1, Port1, {_Anc, SAC}}
          when is_record(SAC, sctp_assoc_change), AssocId1 == undefined ->
            io:format("Association 1 connect result: ~p. AssocId: ~p~n",
                      [SAC#sctp_assoc_change.state,
                       SAC#sctp_assoc_change.assoc_id]),
            client_loop(S, Peer1, Port1, SAC#sctp_assoc_change.assoc_id,
                        Peer2, Port2, AssocId2);

        {sctp, S, Peer2, Port2, {_Anc, SAC}}
          when is_record(SAC, sctp_assoc_change), AssocId2 == undefined ->
            io:format("Association 2 connect result: ~p. AssocId: ~p~n",
                      [SAC#sctp_assoc_change.state, SAC#sctp_assoc_change.assoc_id]),
            client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2,
                       SAC#sctp_assoc_change.assoc_id);

        {sctp, S, Peer1, Port1, Data} ->
            io:format("Association 1: received ~p~n", [Data]),
            client_loop(S, Peer1, Port1, AssocId1,
                        Peer2, Port2, AssocId2);

        {sctp, S, Peer2, Port2, Data} ->
            io:format("Association 2: received ~p~n", [Data]),
            client_loop(S, Peer1, Port1, AssocId1,
                        Peer2, Port2, AssocId2);

        {sctp_error, S, _Peer, _Port, {_Anc, Error}} ->
            io:format("SCTP error: ~p~n", [Error]),
            client_loop(S, Peer1, Port1, AssocId1,
                        Peer2, Port2, AssocId2);

        Other ->
            io:format("Other ~p~n", [Other]),
            client_loop(S, Peer1, Port1, AssocId1,
                        Peer2, Port2, AssocId2)

    after 5000 ->
            ok
    end.

See Also

gen_tcp, gen_udp, inet, RFC 2960 (Stream Control Transmission Protocol), Sockets API Extensions for SCTP

Summary

Types

assoc_id()

Association ID.

elementary_option()

elementary_option_name()

option()

SCTP Socket Option name and value, to set.

option_name()

SCTP Socket Option name, to get.

option_value()

SCTP Socket Option name and value, what you get.

record_option()

ro_option()

sctp_socket()

Socket identifier returned from open/*.

Functions

abort(Socket, Assoc)

Abort an association.

close(Socket)

Close an SCTP socket.

connect(Socket, SockAddr, Opts)

Equivalent to connect(Socket, SockAddr, Opts, infinity).

connect/4

Establish an association with a peer.

connect(Socket, Addr, Port, Opts, Timeout)

Establish an association with a peer.

connect_init(Socket, SockAddr, Opts)

Equivalent to connect_init(Socket, SockAddr, Opts, infinity).

connect_init/4

Start establishing an association with a peer.

connect_init(Socket, Addr, Port, Opts, Timeout)

Start establishing an association with a peer.

connectx_init(Socket, SockAddrs, Opts)

Start establishing an association with a peer (multiple addresses).

connectx_init(Socket, Addrs, Port, Opts)

Equivalent to connectx_init(Socket, Addrs, Port, Opts, infinity).

connectx_init(Socket, Addrs, Port, Opts, Timeout)

Start establishing an association with a peer (multiple addresses).

controlling_process(Socket, Pid)

Change the controlling process (owner) of a socket.

eof(Socket, Assoc)

Terminate an association gracefully.

error_string(ErrorNumber)

Translate an error number into a string or atom.

listen/2

Make an SCTP socket listen to incoming associations.

open()

Equivalent to open([]).

open/1

Create an SCTP socket.

open(Port, Opts)

Equivalent to open([{port, Port} | Opts]).

peeloff(Socket, Assoc)

Branch off an association into a new socket of type stream.

recv(Socket)

Equivalent to recv(Socket, infinity).

recv(Socket, Timeout)

Receive a Data message.

send(Socket, SndRcvInfo, Data)

Send a Data message, full-featured.

send(Socket, Assoc, Stream, Data)

Send a data message.

Types

assoc_id()

-type assoc_id() :: term().

Association ID.

An opaque term returned in, for example, #sctp_paddr_change{}, which identifies an association for an SCTP socket. The term is opaque except for the special value 0, which has a meaning such as "the whole endpoint" or "all future associations".

elementary_option()

(not exported)

-type elementary_option() ::
          {active, true | false | once | -32768..32767} |
          {buffer, non_neg_integer()} |
          {non_block_send, boolean()} |
          {debug, boolean()} |
          {dontroute, boolean()} |
          {exclusiveaddruse, boolean()} |
          {high_msgq_watermark, pos_integer()} |
          {linger, {boolean(), non_neg_integer()}} |
          {low_msgq_watermark, pos_integer()} |
          {mode, list | binary} |
          list | binary |
          {priority, non_neg_integer()} |
          {recbuf, non_neg_integer()} |
          {reuseaddr, boolean()} |
          {reuseport, boolean()} |
          {reuseport_lb, boolean()} |
          {ipv6_v6only, boolean()} |
          {sndbuf, non_neg_integer()} |
          {sctp_autoclose, non_neg_integer()} |
          {sctp_disable_fragments, boolean()} |
          {sctp_i_want_mapped_v4_addr, boolean()} |
          {sctp_maxseg, non_neg_integer()} |
          {sctp_nodelay, boolean()} |
          {tos, non_neg_integer()} |
          {tclass, non_neg_integer()} |
          {ttl, non_neg_integer()} |
          {recvtos, boolean()} |
          {recvtclass, boolean()} |
          {recvttl, boolean()}.

elementary_option_name()

(not exported)

-type elementary_option_name() ::
          active | buffer | non_block_send | debug | dontroute | exclusiveaddruse |
          high_msgq_watermark | linger | low_msgq_watermark | mode | priority | recbuf | reuseaddr |
          reuseport | reuseport_lb | ipv6_v6only | sctp_autoclose | sctp_disable_fragments |
          sctp_i_want_mapped_v4_addr | sctp_maxseg | sctp_nodelay | sndbuf | tos | tclass | ttl |
          recvtos | recvtclass | recvttl.

option()

-type option() :: elementary_option() | record_option().

SCTP Socket Option name and value, to set.

option_name()

-type option_name() :: elementary_option_name() | record_option() | ro_option().

SCTP Socket Option name, to get.

option_value()

-type option_value() :: elementary_option() | record_option() | ro_option().

SCTP Socket Option name and value, what you get.

record_option()

(not exported)

-type record_option() ::
          {sctp_adaptation_layer, #sctp_setadaptation{adaptation_ind :: term()}} |
          {sctp_associnfo,
           #sctp_assocparams{assoc_id :: term(),
                             asocmaxrxt :: term(),
                             number_peer_destinations :: term(),
                             peer_rwnd :: term(),
                             local_rwnd :: term(),
                             cookie_life :: term()}} |
          {sctp_default_send_param,
           #sctp_sndrcvinfo{stream :: term(),
                            ssn :: term(),
                            flags :: term(),
                            ppid :: term(),
                            context :: term(),
                            timetolive :: term(),
                            tsn :: term(),
                            cumtsn :: term(),
                            assoc_id :: term()}} |
          {sctp_delayed_ack_time, #sctp_assoc_value{assoc_id :: term(), assoc_value :: term()}} |
          {sctp_events,
           #sctp_event_subscribe{data_io_event :: term(),
                                 association_event :: term(),
                                 address_event :: term(),
                                 send_failure_event :: term(),
                                 peer_error_event :: term(),
                                 shutdown_event :: term(),
                                 partial_delivery_event :: term(),
                                 adaptation_layer_event :: term(),
                                 authentication_event :: term()}} |
          {sctp_initmsg,
           #sctp_initmsg{num_ostreams :: term(),
                         max_instreams :: term(),
                         max_attempts :: term(),
                         max_init_timeo :: term()}} |
          {sctp_peer_addr_params,
           #sctp_paddrparams{assoc_id :: term(),
                             address :: term(),
                             hbinterval :: term(),
                             pathmaxrxt :: term(),
                             pathmtu :: term(),
                             sackdelay :: term(),
                             flags :: term()}} |
          {sctp_primary_addr, #sctp_prim{assoc_id :: term(), addr :: term()}} |
          {sctp_rtoinfo,
           #sctp_rtoinfo{assoc_id :: term(), initial :: term(), max :: term(), min :: term()}} |
          {sctp_set_peer_primary_addr, #sctp_setpeerprim{assoc_id :: term(), addr :: term()}}.

ro_option()

(not exported)

-type ro_option() ::
          {sctp_get_peer_addr_info,
           #sctp_paddrinfo{assoc_id :: term(),
                           address :: term(),
                           state :: term(),
                           cwnd :: term(),
                           srtt :: term(),
                           rto :: term(),
                           mtu :: term()}} |
          {sctp_status,
           #sctp_status{assoc_id :: term(),
                        state :: term(),
                        rwnd :: term(),
                        unackdata :: term(),
                        penddata :: term(),
                        instrms :: term(),
                        outstrms :: term(),
                        fragmentation_point :: term(),
                        primary :: term()}}.

sctp_socket()

-type sctp_socket() :: port().

Socket identifier returned from open/*.

Functions

abort(Socket, Assoc)

-spec abort(Socket, Assoc) -> ok | {error, inet:posix()}
               when
                   Socket :: sctp_socket(),
                   Assoc ::
                       #sctp_assoc_change{state :: term(),
                                          error :: term(),
                                          outbound_streams :: term(),
                                          inbound_streams :: term(),
                                          assoc_id :: term()}.

Abort an association.

Abnormally terminates the association specified by Assoc, without flushing unsent data. The socket itself remains open. Other associations opened on this socket are still valid, and the socket can be used in new associations.

close(Socket)

-spec close(Socket) -> ok | {error, inet:posix()} when Socket :: sctp_socket().

Close an SCTP socket.

Closes the socket and all associations on it. The unsent data is flushed as for eof/2. The close/1 call is blocking depending of the value of the linger socket [option]. If it is false or the linger time-out expires, the call returns and unsent data is flushed in the background.

connect(Socket, SockAddr, Opts)

(since OTP 24.3)

-spec connect(Socket, SockAddr, Opts) ->
                 {ok,
                  #sctp_assoc_change{state :: comm_up,
                                     error :: term(),
                                     outbound_streams :: term(),
                                     inbound_streams :: term(),
                                     assoc_id :: term()}} |
                 {error,
                  #sctp_assoc_change{state :: cant_assoc,
                                     error :: term(),
                                     outbound_streams :: term(),
                                     inbound_streams :: term(),
                                     assoc_id :: term()}} |
                 {error, inet:posix()}
                 when
                     Socket :: sctp_socket(),
                     SockAddr :: socket:sockaddr_in() | socket:sockaddr_in6(),
                     Opts :: [Opt :: option()].

Equivalent to connect(Socket, SockAddr, Opts, infinity).

connect/4

-spec connect(Socket, SockAddr, Opts, Timeout) ->
                 {ok,
                  #sctp_assoc_change{state :: comm_up,
                                     error :: term(),
                                     outbound_streams :: term(),
                                     inbound_streams :: term(),
                                     assoc_id :: term()}} |
                 {error,
                  #sctp_assoc_change{state :: cant_assoc,
                                     error :: term(),
                                     outbound_streams :: term(),
                                     inbound_streams :: term(),
                                     assoc_id :: term()}} |
                 {error, inet:posix()}
                 when
                     Socket :: sctp_socket(),
                     SockAddr :: socket:sockaddr_in() | socket:sockaddr_in6(),
                     Opts :: [Opt :: option()],
                     Timeout :: timeout();
             (Socket, Addr, Port, Opts) ->
                 {ok,
                  #sctp_assoc_change{state :: comm_up,
                                     error :: term(),
                                     outbound_streams :: term(),
                                     inbound_streams :: term(),
                                     assoc_id :: term()}} |
                 {error,
                  #sctp_assoc_change{state :: cant_assoc,
                                     error :: term(),
                                     outbound_streams :: term(),
                                     inbound_streams :: term(),
                                     assoc_id :: term()}} |
                 {error, inet:posix()}
                 when
                     Socket :: sctp_socket(),
                     Addr :: inet:ip_address() | inet:hostname(),
                     Port :: inet:port_number(),
                     Opts :: [Opt :: option()].

Establish an association with a peer.

With arguments Addr and Port, equivalent to connect(Socket, Addr, Port, Opts, infinity).

With arguments SockAddr and Opts (since OTP 24.3), equivalent to connect(Socket, Addr, Port, Opts, Timeout) where Addr and Port are extracted from SockAddr.

connect(Socket, Addr, Port, Opts, Timeout)

-spec connect(Socket, Addr, Port, Opts, Timeout) ->
                 {ok,
                  #sctp_assoc_change{state :: comm_up,
                                     error :: term(),
                                     outbound_streams :: term(),
                                     inbound_streams :: term(),
                                     assoc_id :: term()}} |
                 {error,
                  #sctp_assoc_change{state :: cant_assoc,
                                     error :: term(),
                                     outbound_streams :: term(),
                                     inbound_streams :: term(),
                                     assoc_id :: term()}} |
                 {error, inet:posix()}
                 when
                     Socket :: sctp_socket(),
                     Addr :: inet:ip_address() | inet:hostname(),
                     Port :: inet:port_number(),
                     Opts :: [Opt :: option()],
                     Timeout :: timeout().

Establish an association with a peer.

Establishes a new association for socket Socket, with the peer (SCTP server socket) specified by Addr and Port. Timeout, is expressed in milliseconds. A socket can be associated with multiple peers. The socket has to be of type seqpacket.

Warning

Using a value of Timeout less than the maximum time taken by the OS to establish an association (around 4.5 minutes if the default values from RFC 4960 are used), can result in inconsistent or incorrect return values. This is especially relevant for associations sharing the same Socket (that is, source address and port), as the controlling process blocks until connect/* returns. connect_init/* provides an alternative without this limitation.

#sctp_assoc_change{}

The result of connect/* is an #sctp_assoc_change{} event that contains, in particular, the new Association ID: l

#sctp_assoc_change{
      state             = atom(),
      error             = integer(),
      outbound_streams  = integer(),
      inbound_streams   = integer(),
      assoc_id          = assoc_id()
}

The number of outbound and inbound streams for the association can be set by giving an sctp_initmsg option to connect as in:

connect(Socket, Ip, Port>,
      [{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams,
                                   max_instreams=MaxInStreams}}])

All options Opt are set on the socket before the association is attempted. If an option record has undefined field values, the options record is first read from the socket for those values. In effect, Opt option records only need to define field values to change before connecting.

The returned outbound_streams and inbound_streams are the number of stream on the socket. These can be different from the requested values (OutStreams and MaxInStreams, respectively), if the peer requires lower values.

state can have the following values:

comm_up - Association is successfully established. This indicates a successful completion of connect.

cant_assoc - The association cannot be established (connect/* failure).

Other states do not normally occur in the output from connect/*. Rather, they can occur in #sctp_assoc_change{} events received instead of data from recv/* calls or socket messages. All of them indicate losing the association because of various error conditions, and are listed here for the sake of completeness:

comm_lost

restart

shutdown_comp

The field error can provide more detailed diagnostics. Its value can be converted into a string using error_string/1.

connect_init(Socket, SockAddr, Opts)

(since OTP 24.3)

-spec connect_init(Socket, SockAddr, Opts) -> ok | {error, inet:posix()}
                      when
                          Socket :: sctp_socket(),
                          SockAddr :: socket:sockaddr_in() | socket:sockaddr_in6(),
                          Opts :: [option()].

Equivalent to connect_init(Socket, SockAddr, Opts, infinity).

connect_init/4

(since OTP R13B04)

-spec connect_init(Socket, SockAddr, Opts, Timeout) -> ok | {error, inet:posix()}
                      when
                          Socket :: sctp_socket(),
                          SockAddr :: socket:sockaddr_in() | socket:sockaddr_in6(),
                          Opts :: [option()],
                          Timeout :: timeout();
                  (Socket, Addr, Port, Opts) -> ok | {error, inet:posix()}
                      when
                          Socket :: sctp_socket(),
                          Addr :: inet:ip_address() | inet:hostname(),
                          Port :: inet:port_number(),
                          Opts :: [option()].

Start establishing an association with a peer.

With arguments Addr and Port, equivalent to connect_init(Socket, Addr, Port, Opts, infinity).

With arguments SockAddr and Opts (since OTP 24.3), equivalent to connect_init(Socket, Addr, Port, Opts, Timeout) where Addr and Port are extracted from SockAddr.

connect_init(Socket, Addr, Port, Opts, Timeout)

(since OTP R13B04)

-spec connect_init(Socket, Addr, Port, Opts, Timeout) -> ok | {error, inet:posix()}
                      when
                          Socket :: sctp_socket(),
                          Addr :: inet:ip_address() | inet:hostname(),
                          Port :: inet:port_number(),
                          Opts :: [option()],
                          Timeout :: timeout().

Start establishing an association with a peer.

Initiates a new association for socket Socket, with the peer (SCTP server socket) specified by Addr and Port.

The fundamental difference between this API and connect/* is that the return value is that of the underlying OS connect(2) system call. If ok is returned, the operation has been succesfully initiated, and the final result result of the association establishment is sent to the socket owner (controlling process) as an #sctp_assoc_change{} event. The socket owner must be prepared to receive this, the recv/* call has to be polled, depending on the value of the active option.

The parameters are as described for connect/*, except the Timeout value since for this function, the time-out only applies to the name resolving of Addr when it is a inet:hostname/0.

connectx_init(Socket, SockAddrs, Opts)

(since OTP 25.0)

-spec connectx_init(Socket, SockAddrs, Opts) -> {ok, assoc_id()} | {error, inet:posix()}
                       when
                           Socket :: sctp_socket(),
                           SockAddrs ::
                               [{inet:ip_address(), inet:port_number()} |
                                inet:family_address() |
                                socket:sockaddr_in() |
                                socket:sockaddr_in6()],
                           Opts :: [option()].

Start establishing an association with a peer (multiple addresses).

Similar to connectx_init/5 except using socket addresses, and not having a Timeout. Since the addresses do not need lookup and the connect is non-blocking this call returns immediately.

The value of each socket address port must be the same or zero. At least one socket address must have a non-zero port

connectx_init(Socket, Addrs, Port, Opts)

(since OTP 25.0)

-spec connectx_init(Socket, Addrs, Port, Opts) -> {ok, assoc_id()} | {error, inet:posix()}
                       when
                           Socket :: sctp_socket(),
                           Addrs :: [inet:ip_address() | inet:hostname()],
                           Port :: inet:port_number() | atom(),
                           Opts :: [option()].

Equivalent to connectx_init(Socket, Addrs, Port, Opts, infinity).

connectx_init(Socket, Addrs, Port, Opts, Timeout)

(since OTP 25.0)

-spec connectx_init(Socket, Addrs, Port, Opts, Timeout) -> {ok, assoc_id()} | {error, inet:posix()}
                       when
                           Socket :: sctp_socket(),
                           Addrs :: [inet:ip_address() | inet:hostname()],
                           Port :: inet:port_number() | atom(),
                           Opts :: [option()],
                           Timeout :: timeout().

Start establishing an association with a peer (multiple addresses).

Initiates a new association for socket Socket, with the peer (SCTP server socket) specified by Addrs and Port.

This API is similar to connect_init/* except the underlying OS sctp_connectx(3) system call is used, that accepts multiple destination addresses.

If successful, the association ID is returned which will be received in a subsequent #sctp_assoc_change{} event.

The parameters are as described in connect_init/5

Note

This API allows the OS to use all Addrs when establishing an association, but does not guarantee it will. Therefore, if the connection fails, the user may want to rotate the order of addresses for a subsequent call.

controlling_process(Socket, Pid)

-spec controlling_process(Socket, Pid) -> ok | {error, Reason}
                             when
                                 Socket :: sctp_socket(),
                                 Pid :: pid(),
                                 Reason :: closed | not_owner | badarg | inet:posix().

Change the controlling process (owner) of a socket.

Assigns a new controlling process Pid to Socket. See gen_udp:controlling_process/2.

eof(Socket, Assoc)

-spec eof(Socket, Assoc) -> ok | {error, Reason}
             when
                 Socket :: sctp_socket(),
                 Assoc ::
                     #sctp_assoc_change{state :: term(),
                                        error :: term(),
                                        outbound_streams :: term(),
                                        inbound_streams :: term(),
                                        assoc_id :: term()},
                 Reason :: term().

Terminate an association gracefully.

Gracefully terminates the association specified by Assoc, flushing all unsent data. The socket itself remains open. Other associations opened on this socket are still valid. The socket can be used in new associations.

error_string(ErrorNumber)

-spec error_string(ErrorNumber) -> ok | string() | unknown_error when ErrorNumber :: integer().

Translate an error number into a string or atom.

Translates an SCTP error number from, for example, #sctp_remote_error{} or #sctp_send_failed{} into an explanatory string, or into one of the atoms ok for no error, or unknown_error for an unrecognized integer.

listen/2

-spec listen(Socket, IsServer) -> ok | {error, Reason}
                when Socket :: sctp_socket(), IsServer :: boolean(), Reason :: term();
            (Socket, Backlog) -> ok | {error, Reason}
                when Socket :: sctp_socket(), Backlog :: integer(), Reason :: term().

Make an SCTP socket listen to incoming associations.

The socket will listen on the IP address(es) and port number it is bound to.

For type seqpacket, sockets (the default), the argumentIsServer must be a boolean/0. In contrast to stream sockets, there is no listening queue length. If IsServer is true, the socket accepts new associations, that is, it becomes an SCTP server socket.

For type stream sockets, the argument Backlog sets the backlog queue length just like for TCP.

open()

-spec open() -> {ok, Socket} | {error, inet:posix()} when Socket :: sctp_socket().

Equivalent to open([]).

open/1

-spec open(Port) -> {ok, Socket} | {error, inet:posix()}
              when Port :: inet:port_number(), Socket :: sctp_socket();
          (Opts) -> {ok, Socket} | {error, inet:posix()}
              when
                  Opts :: [Opt],
                  Opt ::
                      {ifaddr, IP | SockAddr} |
                      {ip, IP} |
                      {port, Port} |
                      inet:address_family() |
                      {type, SockType} |
                      {netns, file:filename_all()} |
                      {bind_to_device, binary()} |
                      option(),
                  IP :: inet:ip_address() | any | loopback,
                  SockAddr :: socket:sockaddr_in() | socket:sockaddr_in6(),
                  Port :: inet:port_number(),
                  SockType :: seqpacket | stream,
                  Socket :: sctp_socket().

Create an SCTP socket.

With argument Port, equivalent toopen([{port, Port}].

Creates an SCTP socket and binds it to the local addresses specified by all {ip,IP} (or synonymously {ifaddr,IP}) options (this feature is called SCTP multi-homing). The default IP and Port are any and 0, meaning bind to all local addresses on any free port.

It is also possible to use {ifaddr, SockAddr}, in which case it takes precedence over the ip and port options. These options can however be used to update the address and port of ifaddr (if they occur after ifaddr in the options list), although this is not recommended.

Other options:

inet6 - Sets up the socket for IPv6.

inet - Sets up the socket for IPv4. This is the default.

A default set of socket options is used. In particular, the socket is opened in binary and passive mode, with SockType seqpacket, and with reasonably large kernel and driver buffers.

When the socket is in passive mode, data can be received through the recv/1,2 calls.

When the socket is in active mode, received data is delivered to the controlling process as messages:

{sctp, Socket, FromIP, FromPort, {AncData, Data}}

Error-related events - such as #sctp_send_failed{}, #sctp_pdapi_event{}, and #sctp_remote_error{} - are also delivered to the controlling process as messages, but use a different tuple tag:

{sctp_error, Socket, FromIP, FromPort, {AncData, Data}}

See recv/1,2 for a description of the message fields.

Note

This message format unfortunately differs slightly from the gen_udp message format with ancillary data, and from the recv/1,2 return tuple format.

open(Port, Opts)

-spec open(Port :: integer(), Opts :: [term()]) -> _.

Equivalent to open([{port, Port} | Opts]).

peeloff(Socket, Assoc)

(since OTP R15B)

-spec peeloff(Socket, Assoc) -> {ok, NewSocket} | {error, Reason}
                 when
                     Socket :: sctp_socket(),
                     Assoc ::
                         #sctp_assoc_change{state :: term(),
                                            error :: term(),
                                            outbound_streams :: term(),
                                            inbound_streams :: term(),
                                            assoc_id :: term()} |
                         assoc_id(),
                     NewSocket :: sctp_socket(),
                     Reason :: term().

Branch off an association into a new socket of type stream.

The existing association Assoc in the socket Socket (that has to be of type seqpacket; one-to-many style) is branched off into a new socket NewSocket of type stream (one-to-one style).

The existing association argument Assoc can be a #sctp_assoc_change{} record as returned from, for example, recv/*, connect/*, or from a listening socket in active mode. It can also be just the field assoc_id integer/0 from such a record.

recv(Socket)

-spec recv(Socket) -> {ok, {FromIP, FromPort, AncData, Data}} | {error, Reason}
              when
                  Socket :: sctp_socket(),
                  FromIP :: inet:ip_address(),
                  FromPort :: inet:port_number(),
                  AncData ::
                      [#sctp_sndrcvinfo{stream :: term(),
                                        ssn :: term(),
                                        flags :: term(),
                                        ppid :: term(),
                                        context :: term(),
                                        timetolive :: term(),
                                        tsn :: term(),
                                        cumtsn :: term(),
                                        assoc_id :: term()} |
                       inet:ancillary_data()],
                  Data ::
                      binary() |
                      string() |
                      #sctp_sndrcvinfo{stream :: term(),
                                       ssn :: term(),
                                       flags :: term(),
                                       ppid :: term(),
                                       context :: term(),
                                       timetolive :: term(),
                                       tsn :: term(),
                                       cumtsn :: term(),
                                       assoc_id :: term()} |
                      #sctp_assoc_change{state :: term(),
                                         error :: term(),
                                         outbound_streams :: term(),
                                         inbound_streams :: term(),
                                         assoc_id :: term()} |
                      #sctp_paddr_change{addr :: term(),
                                         state :: term(),
                                         error :: term(),
                                         assoc_id :: term()} |
                      #sctp_adaptation_event{adaptation_ind :: term(), assoc_id :: term()},
                  Reason ::
                      inet:posix() |
                      #sctp_send_failed{flags :: term(),
                                        error :: term(),
                                        info :: term(),
                                        assoc_id :: term(),
                                        data :: term()} |
                      #sctp_paddr_change{addr :: term(),
                                         state :: term(),
                                         error :: term(),
                                         assoc_id :: term()} |
                      #sctp_pdapi_event{indication :: term(), assoc_id :: term()} |
                      #sctp_remote_error{error :: term(), assoc_id :: term(), data :: term()} |
                      #sctp_shutdown_event{assoc_id :: term()}.

Equivalent to recv(Socket, infinity).

recv(Socket, Timeout)

-spec recv(Socket, Timeout) -> {ok, {FromIP, FromPort, AncData, Data}} | {error, Reason}
              when
                  Socket :: sctp_socket(),
                  Timeout :: timeout(),
                  FromIP :: inet:ip_address(),
                  FromPort :: inet:port_number(),
                  AncData ::
                      [#sctp_sndrcvinfo{stream :: term(),
                                        ssn :: term(),
                                        flags :: term(),
                                        ppid :: term(),
                                        context :: term(),
                                        timetolive :: term(),
                                        tsn :: term(),
                                        cumtsn :: term(),
                                        assoc_id :: term()} |
                       inet:ancillary_data()],
                  Data ::
                      binary() |
                      string() |
                      #sctp_sndrcvinfo{stream :: term(),
                                       ssn :: term(),
                                       flags :: term(),
                                       ppid :: term(),
                                       context :: term(),
                                       timetolive :: term(),
                                       tsn :: term(),
                                       cumtsn :: term(),
                                       assoc_id :: term()} |
                      #sctp_assoc_change{state :: term(),
                                         error :: term(),
                                         outbound_streams :: term(),
                                         inbound_streams :: term(),
                                         assoc_id :: term()} |
                      #sctp_paddr_change{addr :: term(),
                                         state :: term(),
                                         error :: term(),
                                         assoc_id :: term()} |
                      #sctp_adaptation_event{adaptation_ind :: term(), assoc_id :: term()},
                  Reason ::
                      inet:posix() |
                      #sctp_send_failed{flags :: term(),
                                        error :: term(),
                                        info :: term(),
                                        assoc_id :: term(),
                                        data :: term()} |
                      #sctp_paddr_change{addr :: term(),
                                         state :: term(),
                                         error :: term(),
                                         assoc_id :: term()} |
                      #sctp_pdapi_event{indication :: term(), assoc_id :: term()} |
                      #sctp_remote_error{error :: term(), assoc_id :: term(), data :: term()} |
                      #sctp_shutdown_event{assoc_id :: term()}.

Receive a Data message.

Receives the Data message from any association of the socket. If the receive times out, {error,timeout} is returned. The default time-out is infinity. FromIP and FromPort indicate the address of the sender.

AncData is a list of ancillary data items received with the main Data. This list can be empty, or contain a single #sctp_sndrcvinfo{} record, if receiving ancillary data is enabled (see option sctp_events). Per default, it is enabled, as such ancillary data provides an easy way to determine the association and stream over which the message was received. (An alternative way is to get the association ID from FromIP and FromPort using socket option sctp_get_peer_addr_info, but this does still not give the stream number).

AncData may also contain ancillary data from the socket options recvtos, recvtclass or recvttl, if that is supported for the socket by the platform.

The Data received can, depending on the socket mode be a binary/0 or a list/0 of bytes (integers in the range 0 through 255), or it can be an SCTP event.

Possible SCTP events

#sctp_sndrcvinfo{}

#sctp_assoc_change{}

#sctp_paddr_change{
      addr      = {ip_address(),port()},
      state     = atom(),
      error     = integer(),
      assoc_id  = assoc_id()
}

Indicates change of the status of the IP address of the peer specified by addr within association assoc_id. Possible values of state (mostly self-explanatory) include:

addr_unreachable

addr_available

addr_removed

addr_added

addr_made_prim

addr_confirmed

In case of an error (for example, addr_unreachable), the field error provides more diagnostics. In such cases, event #sctp_paddr_change{} is automatically converted into an error term returned by recv. The error field value can be converted into a string using error_string/1.

#sctp_send_failed{
      flags     = true | false,
      error     = integer(),
      info      = #sctp_sndrcvinfo{},
      assoc_id  = assoc_id()
      data      = binary()
}

The sender can receive this event if a send operation fails.

flags - A Boolean specifying if the data has been transmitted over the wire.

error - Provides extended diagnostics, use error_string/1.

info - The original #sctp_sndrcvinfo{} record used in the failed send/*.

data - The whole original data chunk attempted to be sent.

In the current implementation of the Erlang/SCTP binding, this event is internally converted into an error term returned by recv/*.

#sctp_adaptation_event{
      adaptation_ind = integer(),
      assoc_id       = assoc_id()
}

Delivered when a peer sends an adaptation layer indication parameter (configured through option sctp_adaptation_layer). Notie that with the current implementation of the Erlang/SCTP binding, this event is disabled by default.

#sctp_pdapi_event{
      indication = sctp_partial_delivery_aborted,
      assoc_id   = assoc_id()
}

A partial delivery failure. In the current implementation of the Erlang/SCTP binding, this event is internally converted into an error term returned by recv/*.

send(Socket, SndRcvInfo, Data)

-spec send(Socket, SndRcvInfo, Data) -> ok | {error, Reason}
              when
                  Socket :: sctp_socket(),
                  SndRcvInfo ::
                      #sctp_sndrcvinfo{stream :: term(),
                                       ssn :: term(),
                                       flags :: term(),
                                       ppid :: term(),
                                       context :: term(),
                                       timetolive :: term(),
                                       tsn :: term(),
                                       cumtsn :: term(),
                                       assoc_id :: term()},
                  Data :: binary() | iolist(),
                  Reason :: term().

Send a Data message, full-featured.

Sends the Data message with all sending parameters from a #sctp_sndrcvinfo{} record. This way, the user can specify the PPID (passed to the remote end) and context (passed to the local SCTP layer), which can be used, for example, for error identification. However, such a fine grained user control is rarely required. The function send/4 is sufficient for most applications.

Note

Send is normally blocking, but if the socket option non_block_send is set to true, the function will return with e.g. {error, eagain} in the case when the function would otherwise block. It is then up to the user to try again later.

send(Socket, Assoc, Stream, Data)

-spec send(Socket, Assoc, Stream, Data) -> ok | {error, Reason}
              when
                  Socket :: sctp_socket(),
                  Assoc ::
                      #sctp_assoc_change{state :: term(),
                                         error :: term(),
                                         outbound_streams :: term(),
                                         inbound_streams :: term(),
                                         assoc_id :: term()} |
                      assoc_id(),
                  Stream :: integer(),
                  Data :: binary() | iolist(),
                  Reason :: term().

Send a data message.

Sends a Data message on the association Assoc and Stream.

Assoc can be specified with a #sctp_assoc_change{} record from an association establishment, or as the assoc_id/0 integer/0 field value.

Note

Send is normally blocking, but if the socket option non_block_send is set to true, the function will return with e.g. {error, eagain} in the case when the function would otherwise block. It is then up to the user to try again later.

gen_tcp

Interface to TCP/IP sockets.

This module provides functions for communicating over TCP/IP protocol sockets.

The following code fragment is a simple example of a client connecting to a server at port 5678, transferring a binary, and closing the connection:

client() ->
    SomeHostInNet = "localhost", % to make it runnable on one machine
    {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,
                                 [binary, {packet, 0}]),
    ok = gen_tcp:send(Sock, "Some Data"),
    ok = gen_tcp:close(Sock).

At the other end, a server is listening on port 5678, accepts the connection, and receives the binary:

server() ->
    {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},
                                        {active, false}]),
    {ok, Sock} = gen_tcp:accept(LSock),
    {ok, Bin} = do_recv(Sock, []),
    ok = gen_tcp:close(Sock),
    ok = gen_tcp:close(LSock),
    Bin.

do_recv(Sock, Bs) ->
    case gen_tcp:recv(Sock, 0) of
        {ok, B} ->
            do_recv(Sock, [Bs, B]);
        {error, closed} ->
            {ok, list_to_binary(Bs)}
    end.

For more examples, see section Examples.

Note

Functions that create sockets can take an optional option; {inet_backend, Backend} that, if specified, has to be the first option. This selects the implementation backend towards the platform's socket API.

This is a temporary option that will be ignored in a future release.

The default is Backend = inet that selects the traditional inet_drv.c driver. The other choice is Backend = socket that selects the new socket module and its NIF implementation.

The system default can be changed when the node is started with the application kernel's configuration variable inet_backend.

For gen_tcp with inet_backend = socket we have tried to be as "compatible" as possible which has sometimes been impossible. Here is a list of cases when the behaviour of inet-backend inet (default) and socket are different:

Non-blocking send

If a user calling gen_tcp:send/2 with inet_backend = inet, tries to send more data than there is room for in the OS buffers, the "rest data" is buffered by the inet driver (and later sent in the background). The effect for the user is that the call is non-blocking.

This is not the effect when inet_backend = socket, since there is no buffering. Instead the user hangs either until all data has been sent or the send_timeout timeout has been reached.

shutdown/2 may hide errors

The call does not involve the receive process state, and is done right on the underlying socket. On for example Linux, it is a known misbehaviour that it skips some checks so doing shutdown on a listen socket returns ok while the logical result should have been {error, enotconn}. The inet_drv.c driver did an extra check and simulated the correct error, but with Backend = socket it would introduce overhead to involve the receive process.

The option nodelay is a TCP specific option that is not compatible with domain = local.

When using inet_backend = socket, trying to create a socket (via listen or connect) with domain = local (for example with option {ifaddr, {local,"/tmp/test"}}) will fail with {error, enotsup}.

This does not actually work for inet_backend = inet either, but in that case the error is simply ignored, which is a bad idea. We have chosen to not ignore this error for inet_backend = socket.

Async shutdown write

Calling gen_tcp:shutdown(Socket, write | read_write) on a socket created with inet_backend = socket will take immediate effect, unlike for a socket created with inet_backend = inet.

See async shutdown write for more info.

Windows require sockets (domain = inet | inet6) to be bound.

Currently all sockets created on Windows with inet_backend = socket will be bound. If the user does not provide an address, gen_tcp will try to 'figure out' an address itself.

Examples

The following example illustrates use of option {active,once} and multiple accepts by implementing a server as a number of worker processes doing accept on a single listening socket. Function start/2 takes the number of worker processes and the port number on which to listen for incoming connections. If LPort is specified as 0, an ephemeral port number is used, which is why the start function returns the actual port number allocated:

start(Num,LPort) ->
    case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
        {ok, ListenSock} ->
            start_servers(Num,ListenSock),
            {ok, Port} = inet:port(ListenSock),
            Port;
        {error,Reason} ->
            {error,Reason}
    end.

start_servers(0,_) ->
    ok;
start_servers(Num,LS) ->
    spawn(?MODULE,server,[LS]),
    start_servers(Num-1,LS).

server(LS) ->
    case gen_tcp:accept(LS) of
        {ok,S} ->
            loop(S),
            server(LS);
        Other ->
            io:format("accept returned ~w - goodbye!~n",[Other]),
            ok
    end.

loop(S) ->
    inet:setopts(S,[{active,once}]),
    receive
        {tcp,S,Data} ->
            Answer = process(Data), % Not implemented in this example
            gen_tcp:send(S,Answer),
            loop(S);
        {tcp_closed,S} ->
            io:format("Socket ~w closed [~w]~n",[S,self()]),
            ok
    end.

Example of a simple client:

client(PortNo,Message) ->
    {ok,Sock} = gen_tcp:connect("localhost",PortNo,[{active,false},
                                                    {packet,2}]),
    gen_tcp:send(Sock,Message),
    A = gen_tcp:recv(Sock,0),
    gen_tcp:close(Sock),
    A.

The send call does not accept a time-out option because time-outs on send is handled through socket option send_timeout. The behavior of a send operation with no receiver is mainly defined by the underlying TCP stack and the network infrastructure. To write code that handles a hanging receiver that can eventually cause the sender to hang on a send do like the following.

Consider a process that receives data from a client process to be forwarded to a server on the network. The process is connected to the server through TCP/IP and does not get any acknowledge for each message it sends, but has to rely on the send time-out option to detect that the other end is unresponsive. Option send_timeout can be used when connecting:

...
{ok,Sock} = gen_tcp:connect(HostAddress, Port,
                            [{active,false},
                             {send_timeout, 5000},
                             {packet,2}]),
                loop(Sock), % See below
...

In the loop where requests are handled, send time-outs can now be detected:

loop(Sock) ->
    receive
        {Client, send_data, Binary} ->
            case gen_tcp:send(Sock,[Binary]) of
                {error, timeout} ->
                    io:format("Send timeout, closing!~n",
                              []),
                    handle_send_timeout(), % Not implemented here
                    Client ! {self(),{error_sending, timeout}},
                    %% Usually, it's a good idea to give up in case of a
                    %% send timeout, as you never know how much actually
                    %% reached the server, maybe only a packet header?!
                    gen_tcp:close(Sock);
                {error, OtherSendError} ->
                    io:format("Some other error on socket (~p), closing",
                              [OtherSendError]),
                    Client ! {self(),{error_sending, OtherSendError}},
                    gen_tcp:close(Sock);
                ok ->
                    Client ! {self(), data_sent},
                    loop(Sock)
            end
    end.

Usually it suffices to detect time-outs on receive, as most protocols include some sort of acknowledgment from the server, but if the protocol is strictly one way, option send_timeout comes in handy.

Summary

Types

connect_option()

listen_option()

option()

option_name()

pktoptions_value()

Value from socket option pktoptions.

socket()

As returned by accept/1,2 and connect/3,4.

Functions

accept(ListenSocket)

Equivalent to accept(ListenSocket, infinity).

accept(ListenSocket, Timeout)

Accept an incoming connection request on a listen socket.

close(Socket)

Close a TCP socket.

connect(SockAddr, Opts)

Equivalent to connect(SockAddr, Opts, infinity).

connect/3

Create a socket connected to the specified address.

connect(Address, Port, Opts, Timeout)

Create a socket connected to the specified address.

controlling_process(Socket, Pid)

Change the controlling process (owner) of a socket.

listen(Port, Options)

Create a listen socket.

recv(Socket, Length)

Equivalent to recv(Socket, Length, infinity).

recv(Socket, Length, Timeout)

Receive a packet, from a socket in passive mode.

send(Socket, Packet)

Send a packet on a socket.

shutdown(Socket, How)

Close the socket in one or both directions.

Types

connect_option()

-type connect_option() ::
          {fd, Fd :: non_neg_integer()} |
          inet:address_family() |
          {ifaddr, socket:sockaddr_in() | socket:sockaddr_in6() | inet:socket_address()} |
          {ip, inet:socket_address()} |
          {port, inet:port_number()} |
          {tcp_module, module()} |
          {netns, file:filename_all()} |
          {bind_to_device, binary()} |
          option().

listen_option()

-type listen_option() ::
          {fd, Fd :: non_neg_integer()} |
          inet:address_family() |
          {ifaddr, socket:sockaddr_in() | socket:sockaddr_in6() | inet:socket_address()} |
          {ip, inet:socket_address()} |
          {port, inet:port_number()} |
          {backlog, B :: non_neg_integer()} |
          {tcp_module, module()} |
          {netns, file:filename_all()} |
          {bind_to_device, binary()} |
          option().

option()

-type option() ::
          {active, true | false | once | -32768..32767} |
          {buffer, non_neg_integer()} |
          {debug, boolean()} |
          {delay_send, boolean()} |
          {deliver, port | term} |
          {dontroute, boolean()} |
          {exit_on_close, boolean()} |
          {exclusiveaddruse, boolean()} |
          {header, non_neg_integer()} |
          {high_msgq_watermark, pos_integer()} |
          {high_watermark, non_neg_integer()} |
          {keepalive, boolean()} |
          {keepcnt, integer()} |
          {keepidle, integer()} |
          {keepintvl, integer()} |
          {linger, {boolean(), non_neg_integer()}} |
          {low_msgq_watermark, pos_integer()} |
          {low_watermark, non_neg_integer()} |
          {mode, list | binary} |
          list | binary |
          {nodelay, boolean()} |
          {packet,
           0 | 1 | 2 | 4 | raw | sunrm | asn1 | cdr | fcgi | line | tpkt | http | httph | http_bin |
           httph_bin} |
          {packet_size, non_neg_integer()} |
          {priority, non_neg_integer()} |
          {raw, Protocol :: non_neg_integer(), OptionNum :: non_neg_integer(), ValueBin :: binary()} |
          {recbuf, non_neg_integer()} |
          {reuseaddr, boolean()} |
          {reuseport, boolean()} |
          {reuseport_lb, boolean()} |
          {send_timeout, timeout()} |
          {send_timeout_close, boolean()} |
          {show_econnreset, boolean()} |
          {sndbuf, non_neg_integer()} |
          {tos, non_neg_integer()} |
          {tclass, non_neg_integer()} |
          {ttl, non_neg_integer()} |
          {recvtos, boolean()} |
          {recvtclass, boolean()} |
          {recvttl, boolean()} |
          {user_timeout, non_neg_integer()} |
          {ipv6_v6only, boolean()}.

option_name()

-type option_name() ::
          active | buffer | debug | delay_send | deliver | dontroute | exit_on_close |
          exclusiveaddruse | header | high_msgq_watermark | high_watermark | keepalive | keepcnt |
          keepidle | keepintvl | linger | low_msgq_watermark | low_watermark | mode | nodelay | packet |
          packet_size | priority |
          {raw,
           Protocol :: non_neg_integer(),
           OptionNum :: non_neg_integer(),
           ValueSpec :: (ValueSize :: non_neg_integer()) | (ValueBin :: binary())} |
          recbuf | reuseaddr | reuseport | reuseport_lb | send_timeout | send_timeout_close |
          show_econnreset | sndbuf | tos | tclass | ttl | recvtos | recvtclass | recvttl | pktoptions |
          user_timeout | ipv6_v6only.

pktoptions_value()

-type pktoptions_value() :: {pktoptions, inet:ancillary_data()}.

Value from socket option pktoptions.

If the platform implements the IPv4 option IP_PKTOPTIONS, or the IPv6 option IPV6_PKTOPTIONS or IPV6_2292PKTOPTIONS for the socket; this value is returned from inet:getopts/2 when called with the option name pktoptions.

Note

This option appears to be VERY Linux specific, and its existence in future Linux kernel versions is also worrying since the option is part of RFC 2292 which is since long (2003) obsoleted by RFC 3542 that explicitly removes this possibility to get packet information from a stream socket. For comparison: it has existed in FreeBSD but is now removed, at least since FreeBSD 10.

socket()

-type socket() :: inet:socket().

As returned by accept/1,2 and connect/3,4.

Functions

accept(ListenSocket)

-spec accept(ListenSocket) -> {ok, Socket} | {error, Reason}
                when
                    ListenSocket :: socket(),
                    Socket :: socket(),
                    Reason :: closed | system_limit | inet:posix().

Equivalent to accept(ListenSocket, infinity).

accept(ListenSocket, Timeout)

-spec accept(ListenSocket, Timeout) -> {ok, Socket} | {error, Reason}
                when
                    ListenSocket :: socket(),
                    Timeout :: timeout(),
                    Socket :: socket(),
                    Reason :: closed | timeout | system_limit | inet:posix().

Accept an incoming connection request on a listen socket.

ListenSocket must be a socket returned from listen/2. Timeout specifies a time-out value in milliseconds. Defaults to infinity.

Returns:

{ok, Socket} if a connection is established

{error, closed} if ListenSocket is closed

{error, timeout} if no connection is established within Timeout

{error, system_limit} if all available ports in the Erlang emulator are in use

A POSIX error value if something else goes wrong, see inet about possible values

To send packets (outbound) on the returned Socket, use send/2. Packets sent from the peer (inbound) are delivered as messages to the socket owner; the process that created the socket. Unless {active, false} is specified in the option list when creating the listening socket.

See connect/4 about active mode socket messages and passive mode.

Note

The accept call doesn't have to be issued from the socket owner process. Using version 5.5.3 and higher of the emulator, multiple simultaneous accept calls can be issued from different processes, which allows for a pool of acceptor processes handling incoming connections.

close(Socket)

-spec close(Socket) -> ok when Socket :: socket().

Close a TCP socket.

Note that in most implementations of TCP, doing a close does not guarantee that the data sent is delivered to the recipient. It is guaranteed that the recepient will see all sent data before getting the close, but the sender gets no indication of that.

If the sender needs to know that the recepient has received all data there are two common ways to achieve this:

Use gen_tcp:shutdown(Sock, write) to signal that no more data is to be sent and wait for the other side to acknowledge seeing its read side being closed, by closing its write side, which shows as a socket close on this side.

Implement an acknowledgement in the protocol on top of TCP that both connection ends adhere to, indicating that all data has been seen. The socket option {packet, N} may be useful.

connect(SockAddr, Opts)

(since OTP 24.3)

-spec connect(SockAddr, Opts) -> {ok, Socket} | {error, Reason}
                 when
                     SockAddr :: socket:sockaddr_in() | socket:sockaddr_in6(),
                     Opts :: [inet:inet_backend() | connect_option()],
                     Socket :: socket(),
                     Reason :: inet:posix().

Equivalent to connect(SockAddr, Opts, infinity).

connect/3

-spec connect(Address, Port, Opts) -> {ok, Socket} | {error, Reason}
                 when
                     Address :: inet:socket_address() | inet:hostname(),
                     Port :: inet:port_number(),
                     Opts :: [inet:inet_backend() | connect_option()],
                     Socket :: socket(),
                     Reason :: inet:posix();
             (SockAddr, Opts, Timeout) -> {ok, Socket} | {error, Reason}
                 when
                     SockAddr :: socket:sockaddr_in() | socket:sockaddr_in6(),
                     Opts :: [inet:inet_backend() | connect_option()],
                     Timeout :: timeout(),
                     Socket :: socket(),
                     Reason :: timeout | inet:posix().

Create a socket connected to the specified address.

With arguments Address and Port

Equivalent to connect(Address, Port, Opts, infinity).

With argument SockAddr (since OTP 24.3)

Connects to a remote listen socket specified by SockAddr where socket:sockaddr_in6/0 for example allows specifying the scope_id for link local IPv6 addresses.

IPv4 addresses on the same map/0 format is also allowed.

Equivalent to connect/4, besides the format of the destination address.

connect(Address, Port, Opts, Timeout)

-spec connect(Address, Port, Opts, Timeout) -> {ok, Socket} | {error, Reason}
                 when
                     Address :: inet:socket_address() | inet:hostname(),
                     Port :: inet:port_number(),
                     Opts :: [inet:inet_backend() | connect_option()],
                     Timeout :: timeout(),
                     Socket :: socket(),
                     Reason :: timeout | inet:posix().

Create a socket connected to the specified address.

Creates a socket and connects it to a server on TCP port Port on the host with IP address Address, that may also be a hostname.

Opts (connect options)

{ip, Address} - If the local host has many IP addresses, this option specifies which one to use.

{ifaddr, Address} - Same as {ip, Address}.

However, if Address instead is a socket:sockaddr_in/0 or socket:sockaddr_in6/0 this takes precedence over any value previously set with the ip and port options. If these options (ip or/and port) however comes after this option, they may be used to update the corresponding fields of this option (for ip, the addr field, and for port, the port field).

{fd, integer() >= 0} - If a socket has somehow been connected without using gen_tcp, use this option to pass the file descriptor for it. If {ip, Address} and/or {port, port_number()} is combined with this option, the fd is bound to the specified interface and port before connecting. If these options are not specified, it is assumed that the fd is already bound appropriately.

inet - Sets up the socket for IPv4.

inet6 - Sets up the socket for IPv6.

local - Sets up a Unix Domain Socket. See inet:local_address/0

{port, Port} - Specifies which local port number to use.

{tcp_module, module()} - Overrides which callback module is used. Defaults to inet_tcp for IPv4 and inet6_tcp for IPv6.

{protocol, tcp|mptcp} - With mptcp creates the socket with protocol IPPROTO_MPTCP, if that is defined on the system. Other than that the socket is regarded as a tcp socket. If IPPROTO_MPTCP is not defined, {error, eprotonosupport} is returned. tcp is the default value.

option/0 - See inet:setopts/2.

Socket Data

Packets can be sent to the peer (outbound) with send(Socket, Packet). Packets sent from the peer (inbound) are delivered as messages to the socket owner; the process that created the socket, unless {active, false} is specified in the Options list.

Active mode socket messages

{tcp, Socket, Data} - Inbound data from the socket.

{tcp_passive, Socket} - The socket was in {active, N} mode (see inet:setopts/2 for details) and its message counter reached 0, indicating that the socket has transitioned to passive ({active, false}) mode.

{tcp_closed, Socket} - The socket was closed.

{tcp_error, Socket, Reason} A socket error occurred.

Passive mode

If {active, false} is specified in the option list for the socket, packets and errors are retrieved by calling recv/2,3 (send/2 may also return errors).

Timeout

The optional Timeout parameter specifies a connect time-out in milliseconds. Defaults to infinity.

Note

Keep in mind that if the underlying OS connect() call returns a timeout, gen_tcp:connect will also return a timeout (i.e. {error, etimedout}), even if a larger Timeout was specified (for example infinity).

Note

The default values for options specified to connect can be affected by the Kernel configuration parameter inet_default_connect_options. For details, see inet.

controlling_process(Socket, Pid)

-spec controlling_process(Socket, Pid) -> ok | {error, Reason}
                             when
                                 Socket :: socket(),
                                 Pid :: pid(),
                                 Reason :: closed | not_owner | badarg | inet:posix().

Change the controlling process (owner) of a socket.

Assigns a new controlling process Pid to Socket. The controlling process is the process that the socket sends messages to. If this function is called from any other process than the current controlling process, {error, not_owner} is returned.

If the process identified by Pid is not an existing local pid/0, {error, badarg} is returned. {error, badarg} may also be returned in some cases when Socket is closed during the execution of this function.

If the socket is in active mode, this function will transfer any messages from the socket in the mailbox of the caller to the new controlling process.

If any other process is interacting with the socket during the transfer, it may not work correctly and messages may remain in the caller's mailbox. For instance, changing the sockets active mode during the transfer could cause this.

listen(Port, Options)

-spec listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}
                when
                    Port :: inet:port_number(),
                    Options :: [inet:inet_backend() | listen_option()],
                    ListenSocket :: socket(),
                    Reason :: system_limit | inet:posix().

Create a listen socket.

Creates a socket and sets it to listen on port Port on the local host.

If Port == 0, the underlying OS assigns an available (ephemeral) port number, use inet:port/1 to retrieve it.

The following options are available:

list - Received Packets are delivered as lists of bytes, [byte/0].

binary - Received Packets are delivered as binary/0s.

{backlog, B} - B :: non_neg_integer/0. The backlog value defines the maximum length that the queue of pending connections can grow to. Defaults to 5.

inet6 - Sets up the socket for IPv6.

inet - Sets up the socket for IPv4.

{fd, Fd} - If a socket has somehow been created without using gen_tcp, use this option to pass the file descriptor for it.

{ip, Address} - If the host has many IP addresses, this option specifies which one to listen on.

{port, Port} - Specifies which local port number to use.

{ifaddr, Address} - Same as {ip, Address}.

However, if this instead is an socket:sockaddr_in/0 or socket:sockaddr_in6/0 this takes precedence over any value previously set with the ip and port options. If these options (ip or/and port) however comes after this option, they may be used to update their corresponding fields of this option (for ip, the addr field, and for port, the port field).

{tcp_module, module()} - Overrides which callback module is used. Defaults to inet_tcp for IPv4 and inet6_tcp for IPv6.

{protocol, tcp|mptcp} - With mptcp creates the socket with protocol IPPROTO_MPTCP, if that is defined on the system. Other than that the socket is regarded as a tcp socket. If IPPROTO_MPTCP is not defined, {error, eprotonosupport} is returned. tcp is the default value.

option/0 - See inet:setopts/2.

The returned socket ListenSocket should be used when calling accept/1,2 to accept an incoming connection request.

Note

The default values for options specified to listen can be affected by the Kernel configuration parameter inet_default_listen_options. For details, see inet.

recv(Socket, Length)

-spec recv(Socket, Length) -> {ok, Packet} | {error, Reason}
              when
                  Socket :: socket(),
                  Length :: non_neg_integer(),
                  Packet :: string() | binary() | HttpPacket,
                  Reason :: closed | inet:posix(),
                  HttpPacket :: term().

Equivalent to recv(Socket, Length, infinity).

recv(Socket, Length, Timeout)

-spec recv(Socket, Length, Timeout) -> {ok, Packet} | {error, Reason}
              when
                  Socket :: socket(),
                  Length :: non_neg_integer(),
                  Timeout :: timeout(),
                  Packet :: string() | binary() | HttpPacket,
                  Reason :: closed | timeout | inet:posix(),
                  HttpPacket :: term().

Receive a packet, from a socket in passive mode.

A closed socket is indicated by the return value {error, closed}. If the socket is not in passive mode, the return value is {error, einval}.

Argument Length is only meaningful when the socket is in raw mode and denotes the number of bytes to read. If Length is 0, all available bytes are returned. If Length > 0, exactly Length bytes are returned, or an error; except if the socket is closed from the other side, then the last read before the one returning {error, closed} may return less than Length bytes of data.

The optional Timeout parameter specifies a time-out in milliseconds. Defaults to infinity.

Any process can receive data from a passive socket, even if that process is not the controlling process of the socket. However, only one process can call this function on a socket at any given time. Using simultaneous calls to recv is not recommended as the behavior depends on the socket implementation, and could return errors such as {error, ealready}.

send(Socket, Packet)

-spec send(Socket, Packet) -> ok | {error, Reason}
              when
                  Socket :: socket(),
                  Packet :: iodata(),
                  Reason :: closed | {timeout, RestData} | inet:posix(),
                  RestData :: binary() | erlang:iovec().

Send a packet on a socket.

There is no send/2 call with a time-out option; use socket option send_timeout if time-outs are desired. See section Examples.

The return value {error, {timeout, RestData}} can only be returned when inet_backend = socket.

Note

Non-blocking send.

If the user tries to send more data than there is room for in the OS send buffers, the 'rest data' is stored in (inet driver) internal buffers and later sent in the background. The function immediately returns ok (not informing the caller that some date isn'nt sent yet). Any issue while sending the 'rest data' may be returned later.

When using inet_backend = socket, the behaviour is different. There is no buffering, instead the caller will "hang" until all of the data has been sent or the send timeout (as specified by the send_timeout option) expires (the function can "hang" even when using the inet backend if the internal buffers are full).

If this happens when using packet =/= raw, a partial packet has been written. A new packet therefore mustn't be written at this point, as there is no way for the peer to distinguish this from data in the current packet. Instead, set the packet option to raw, send the rest data (as raw data) and then set packet back to the correct type.

shutdown(Socket, How)

-spec shutdown(Socket, How) -> ok | {error, Reason}
                  when Socket :: socket(), How :: read | write | read_write, Reason :: inet:posix().

Close the socket in one or both directions.

How == write means closing the socket for writing, reading from it is still possible.

If How == read or there is no outgoing data buffered in the Socket port, the shutdown is performed immediately and any error encountered is returned in Reason.

If there is data buffered in the socket port, shutdown isn't performed on the socket until that buffered data has been written to the OS protocol stack. If any errors are encountered, the socket is closed and {error, closed} is returned by the next recv/2 or send/2 call.

Option {exit_on_close, false} is useful if the peer performs a shutdown of its write side. Then the socket stays open for writing after receive has indicated that the socket was closed.

Note

Async shutdown write (How :: write | read_write).

If the shutdown attempt is made while the inet driver is sending buffered data in the background, the shutdown is postponed until all buffered data has been sent. This function immediately returns ok, and the caller isn't informed (that the shutdown has been postponed).

When using inet_backend = socket, the behaviour is different. A shutdown with How :: write | read_write will always be performed immediately.

gen_udp

Interface to UDP sockets.

This module provides functions for communicating over UDP protocol sockets.

Note

Functions that create sockets can take an optional option; {inet_backend, Backend} that, if specified, has to be the first option. This selects the implementation backend towards the platform's socket API.

This is a temporary option that will be ignored in a future release.

The default is Backend = inet that selects the traditional inet_drv.c driver. The other choice is Backend = socket that selects the new socket module and its NIF implementation.

The system default can be changed when the node is started with the application kernel's configuration variable inet_backend.

For gen_udp with inet_backend = socket we have tried to be as "compatible" as possible which has sometimes been impossible. Here is a list of cases when the behaviour of inet-backend inet (default) and socket are different:

The option read_packets is currently ignored.

Windows require sockets (domain = inet | inet6) to be bound.

Currently all sockets created on Windows with inet_backend = socket will be bound. If the user does not provide an address, gen_udp will try to 'figure out' an address itself.

Summary

Types

ip6_membership()

ip6_multicast_if()

IPv6 this multicast interface index (an integer).

ip_membership()

IP multicast membership.

ip_multicast_if()

membership()

multicast_if()

open_option()

option()

option_name()

socket()

A socket as returned by open/1,2.

Functions

close(Socket)

Closes a UDP socket.

connect(Socket, SockAddr)

Connect a UDP socket.

connect(Socket, Address, Port)

Connect a UDP socket.

controlling_process(Socket, Pid)

Change the controlling process (owner) of a socket.

open(Port)

Equivalent to open(Port, []).

open(Port, Opts)

Open a UDP socket.

recv(Socket, Length)

Equivalent to recv(Socket, Length, infinity).

recv(Socket, Length, Timeout)

Receive a packet from a socket in passive mode.

send(Socket, Packet)

Send a packet on a connected UDP socket.

send(Socket, Destination, Packet)

Equivalent to send(Socket, Destination, [], Packet).

send/4

Send a UDP packet to the specified destination.

send(Socket, Host, Port, AncData, Packet)

Send a packet to the specified destination, with ancillary data.

Types

ip6_membership()

-type ip6_membership() :: {MultiAddress :: inet:ip6_address(), IfIndex :: integer()}.

ip6_multicast_if()

-type ip6_multicast_if() :: integer().

IPv6 this multicast interface index (an integer).

ip_membership()

-type ip_membership() ::
          {MultiAddress :: inet:ip4_address(), Interface :: inet:ip4_address()} |
          {MultiAddress :: inet:ip4_address(), Address :: inet:ip4_address(), IfIndex :: integer()}.

IP multicast membership.

The 3-tuple form isn't supported on all platforms. 'ifindex' defaults to zero (0) on platforms that supports the 3-tuple variant.

ip_multicast_if()

-type ip_multicast_if() :: inet:ip4_address().

membership()

-type membership() :: ip_membership() | ip6_membership().

multicast_if()

-type multicast_if() :: ip_multicast_if() | ip6_multicast_if().

open_option()

-type open_option() ::
          {ip, inet:socket_address()} |
          {fd, non_neg_integer()} |
          {ifaddr, socket:sockaddr_in() | socket:sockaddr_in6() | inet:socket_address()} |
          inet:address_family() |
          {port, inet:port_number()} |
          {netns, file:filename_all()} |
          {bind_to_device, binary()} |
          option().

option()

-type option() ::
          {active, true | false | once | -32768..32767} |
          {add_membership, membership()} |
          {broadcast, boolean()} |
          {buffer, non_neg_integer()} |
          {debug, boolean()} |
          {deliver, port | term} |
          {dontroute, boolean()} |
          {drop_membership, membership()} |
          {exclusiveaddruse, boolean()} |
          {header, non_neg_integer()} |
          {high_msgq_watermark, pos_integer()} |
          {low_msgq_watermark, pos_integer()} |
          {mode, list | binary} |
          list | binary |
          {multicast_if, multicast_if()} |
          {multicast_loop, boolean()} |
          {multicast_ttl, non_neg_integer()} |
          {priority, non_neg_integer()} |
          {raw, Protocol :: non_neg_integer(), OptionNum :: non_neg_integer(), ValueBin :: binary()} |
          {read_packets, non_neg_integer()} |
          {recbuf, non_neg_integer()} |
          {reuseaddr, boolean()} |
          {reuseport, boolean()} |
          {reuseport_lb, boolean()} |
          {sndbuf, non_neg_integer()} |
          {tos, non_neg_integer()} |
          {tclass, non_neg_integer()} |
          {ttl, non_neg_integer()} |
          {recvtos, boolean()} |
          {recvtclass, boolean()} |
          {recvttl, boolean()} |
          {ipv6_v6only, boolean()}.

option_name()

-type option_name() ::
          active | broadcast | buffer | debug | deliver | dontroute | exclusiveaddruse | header |
          high_msgq_watermark | low_msgq_watermark | mode | multicast_if | multicast_loop |
          multicast_ttl | priority |
          {raw,
           Protocol :: non_neg_integer(),
           OptionNum :: non_neg_integer(),
           ValueSpec :: (ValueSize :: non_neg_integer()) | (ValueBin :: binary())} |
          read_packets | recbuf | reuseaddr | reuseport | reuseport_lb | sndbuf | tos | tclass | ttl |
          recvtos | recvtclass | recvttl | pktoptions | ipv6_v6only.

socket()

-type socket() :: inet:socket().

A socket as returned by open/1,2.

Functions

close(Socket)

-spec close(Socket) -> ok when Socket :: socket().

Closes a UDP socket.

connect(Socket, SockAddr)

(since OTP 24.3)

-spec connect(Socket, SockAddr) -> ok | {error, Reason}
                 when
                     Socket :: socket(),
                     SockAddr :: socket:sockaddr_in() | socket:sockaddr_in6(),
                     Reason :: inet:posix().

Connect a UDP socket.

Connecting a UDP socket only means storing the specified (destination) socket address, as specified by SockAddr, so that the system knows where to send data.

When the socket is "connected" it is not necessary to specify the destination address when sending a datagram. That is; send/2 may be used.

It also means that the socket will only receive data from the connected address. Other messages are discarded on arrival by the OS protocol stack.

connect(Socket, Address, Port)

(since OTP 24.3)

-spec connect(Socket, Address, Port) -> ok | {error, Reason}
                 when
                     Socket :: socket(),
                     Address :: inet:socket_address() | inet:hostname(),
                     Port :: inet:port_number(),
                     Reason :: inet:posix().

Connect a UDP socket.

See connect/2.

With this function the destination is specified with separate Address and Port arguments where Address may be an IP address or a host name.

controlling_process(Socket, Pid)

-spec controlling_process(Socket, Pid) -> ok | {error, Reason}
                             when
                                 Socket :: socket(),
                                 Pid :: pid(),
                                 Reason :: closed | not_owner | badarg | inet:posix().

Change the controlling process (owner) of a socket.

Assigns a new controlling process Pid to Socket. The controlling process is the process that the socket sends messages to. If this function is called from any other process than the current controlling process, {error, not_owner} is returned.

If the process identified by Pid is not an existing local pid/0, {error, badarg} is returned. {error, badarg} may also be returned in some cases when Socket is closed during the execution of this function.

If the socket is in active mode, this function will transfer any messages from the socket in the mailbox of the caller to the new controlling process.

If any other process is interacting with the socket during the transfer, it may not work correctly and messages may remain in the caller's mailbox. For instance, changing the sockets active mode during the transfer could cause this.

open(Port)

-spec open(Port) -> {ok, Socket} | {error, Reason}
              when Port :: inet:port_number(), Socket :: socket(), Reason :: system_limit | inet:posix().

Equivalent to open(Port, []).

open(Port, Opts)

-spec open(Port, Opts) -> {ok, Socket} | {error, Reason}
              when
                  Port :: inet:port_number(),
                  Opts :: [inet:inet_backend() | open_option()],
                  Socket :: socket(),
                  Reason :: system_limit | inet:posix().

Open a UDP socket.

The created socket is bound to the UDP port number Port. If Port == 0, the underlying OS assigns a free (ephemeral) UDP port; use inet:port/1 to retrieve it.

The process that calls this function becomes the Socket's controlling process (socket owner).

UDP socket options

list - Received Packet is delivered as a list.

binary - Received Packet is delivered as a binary.

{ip, Address} - If the local host has many IP addresses, this option specifies which one to use.

{ifaddr, Address} - Same as {ip, Address}.

However, if this instead is a socket:sockaddr_in/0 or socket:sockaddr_in6/0 this takes precedence over any value previously set with the ip options. If the ip option comes after the ifaddr option, it may be used to update its corresponding field of the ifaddr option (the addr field).

{fd, integer() >= 0} - If a socket has somehow been opened without using gen_udp, use this option to pass the file descriptor for it. If Port is not set to 0 and/or {ip, ip_address()} is combined with this option, the fd is bound to the specified interface and port after it is being opened. If these options are not specified, it is assumed that the fd is already bound appropriately.

inet6 - Sets up the socket for IPv6.

inet - Sets up the socket for IPv4.

local - Sets up a Unix Domain Socket. See inet:local_address/0

{udp_module, module()} - Overrides which callback module is used. Defaults to inet_udp for IPv4 and inet6_udp for IPv6.

{multicast_if, Address} - Sets the local device for a multicast socket.

{multicast_loop, true | false} - When true, sent multicast packets are looped back to the local sockets.

{multicast_ttl, Integer} - Option multicast_ttl changes the time-to-live (TTL) for outgoing multicast datagrams to control the scope of the multicasts.

Datagrams with a TTL of 1 are not forwarded beyond the local network. Defaults to 1.

{add_membership, {MultiAddress, InterfaceAddress}} - Joins a multicast group.

{drop_membership, {MultiAddress, InterfaceAddress}} - Leaves a multicast group.

option/0 - See inet:setopts/2.

UDP packets are sent with this socket using send(Socket, ...). When UDP packets arrive to the Socket's UDP port, and the socket is in an active mode, the packets are delivered as messages to the controlling process (socket owner):

{udp, Socket, PeerIP, PeerPort, Packet} % Without ancillary data
{udp, Socket, PeerIP, PeerPort, AncData, Packet} % With ancillary data

PeerIP and PeerPort are the address from which Packet was sent. Packet is a list of bytes ([byte/0] if option list is active and a binary/0 if option binaryis active (they are mutually exclusive).

The message contains an AncData field only if any of the socket options recvtos, recvtclass or recvttl are active.

When a socket in {active, N} mode (see inet:setopts/2 for details), transitions to passive ({active, false}) mode (N counts down to 0), the controlling process is notified by a message on this form:

{udp_passive, Socket}

If the OS protocol stack reports an error for the socket, the following message is sent to the controlling process:

{udp_error, Socket, Reason}

Reason is mostly a POSIX Error Code.

If the socket is in passive mode (not in an active mode), received data can be retrieved with therecv/2,3](recv/2) calls. Note that incoming UDP packets that are longer than the receive buffer option specifies can be truncated without warning.

The default value for the receive buffer option is {recbuf, 9216}.

recv(Socket, Length)

-spec recv(Socket, Length) -> {ok, RecvData} | {error, Reason}
              when
                  Socket :: socket(),
                  Length :: non_neg_integer(),
                  RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
                  Address :: inet:ip_address() | inet:returned_non_ip_address(),
                  Port :: inet:port_number(),
                  AncData :: inet:ancillary_data(),
                  Packet :: string() | binary(),
                  Reason :: not_owner | inet:posix().

Equivalent to recv(Socket, Length, infinity).

recv(Socket, Length, Timeout)

-spec recv(Socket, Length, Timeout) -> {ok, RecvData} | {error, Reason}
              when
                  Socket :: socket(),
                  Length :: non_neg_integer(),
                  Timeout :: timeout(),
                  RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
                  Address :: inet:ip_address() | inet:returned_non_ip_address(),
                  Port :: inet:port_number(),
                  AncData :: inet:ancillary_data(),
                  Packet :: string() | binary(),
                  Reason :: not_owner | timeout | inet:posix().

Receive a packet from a socket in passive mode.

Timeout specifies a time-out in milliseconds.

If any of the socket options recvtos, recvtclass or recvttl are active, the RecvData tuple contains an AncData field, otherwise it doesn't.

send(Socket, Packet)

(since OTP 24.3)

-spec send(Socket, Packet) -> ok | {error, Reason}
              when Socket :: socket(), Packet :: iodata(), Reason :: not_owner | inet:posix().

Send a packet on a connected UDP socket.

To connect a UDP socket, use connect/2 or connect/3.

send(Socket, Destination, Packet)

(since OTP 22.1)

-spec send(Socket, Destination, Packet) -> ok | {error, Reason}
              when
                  Socket :: socket(),
                  Destination ::
                      {inet:ip_address(), inet:port_number()} |
                      inet:family_address() |
                      socket:sockaddr_in() |
                      socket:sockaddr_in6(),
                  Packet :: iodata(),
                  Reason :: not_owner | inet:posix().

Equivalent to send(Socket, Destination, [], Packet).

send/4

-spec send(Socket, Host, Port, Packet) -> ok | {error, Reason}
              when
                  Socket :: socket(),
                  Host :: inet:hostname() | inet:ip_address(),
                  Port :: inet:port_number() | atom(),
                  Packet :: iodata(),
                  Reason :: not_owner | inet:posix();
          (Socket, Destination, AncData, Packet) -> ok | {error, Reason}
              when
                  Socket :: socket(),
                  Destination ::
                      {inet:ip_address(), inet:port_number()} |
                      inet:family_address() |
                      socket:sockaddr_in() |
                      socket:sockaddr_in6(),
                  AncData :: inet:ancillary_data(),
                  Packet :: iodata(),
                  Reason :: not_owner | inet:posix();
          (Socket, Destination, PortZero, Packet) -> ok | {error, Reason}
              when
                  Socket :: socket(),
                  Destination :: {inet:ip_address(), inet:port_number()} | inet:family_address(),
                  PortZero :: inet:port_number(),
                  Packet :: iodata(),
                  Reason :: not_owner | inet:posix().

Send a UDP packet to the specified destination.

With arguments Host and Port

Argument Host can be a hostname or a socket address, and Port can be a port number or a service name atom. These are resolved to a Destination and then this function is equivalent to send(Socket, Destination, [], Packet) just below.

With arguments Destination and AncData (since OTP 22.1)

Sends a packet to the specified Destination with ancillary data AncData.

Note

The ancillary data AncData contains options that for this single message override the default options for the socket, an operation that may not be supported on all platforms, and if so return {error, einval}. Using more than one of an ancillary data item type may also not be supported. AncData =:= [] is always supported.

With arguments Destination and PortZero (since OTP 22.1)

Sends a packet to the specified Destination. Since Destination is a complete address, PortZero is redundant and has to be 0.

This is a legacy clause mostly for Destination = {local, Binary} where PortZero is superfluous. Equivalent to send(Socket, Destination, [], Packet), right above here.

send(Socket, Host, Port, AncData, Packet)

(since OTP 22.1)

-spec send(Socket, Host, Port, AncData, Packet) -> ok | {error, Reason}
              when
                  Socket :: socket(),
                  Host :: inet:hostname() | inet:ip_address() | inet:local_address(),
                  Port :: inet:port_number() | atom(),
                  AncData :: inet:ancillary_data(),
                  Packet :: iodata(),
                  Reason :: not_owner | inet:posix().

Send a packet to the specified destination, with ancillary data.

Equivalent to send(Socket, Host, Port, Packet) regarding Host and Port and also equivalent to send(Socket, Destination, AncData, Packet) regarding the ancillary data: AncData.

inet

Access to Network protocols.

This module, together with gen_tcp, gen_udp and gen_sctp provides access to the Network protocols TCP, SCTP and UDP over IP, as well as stream and datagram protocols over the local (unix) address domain / protocol domain.

See also ERTS User's Guide: Inet Configuration or more information about how to configure an Erlang runtime system for IP communication.

The following four Kernel configuration parameters affect the behavior of all gen_tcp, gen_udp and gen_sctp sockets opened on an Erlang node:

inet_default_connect_options can contain a list of default options used for all sockets created by a gen_tcp:connect/2,3,4](gen_tcp:connect/2) call.

inet_default_listen_options can contain a list of default options used for sockets created by a gen_tcp:listen/2 call.

inet_default_udp_options can contain a list of default options used for all sockets created by a gen_udp:open/1,2](gen_udp:open/2) call.

inet_default_sctp_options can contain a list of default options used for all sockets created by a gen_sctp:open/0,1](gen_sctp:open/1) call.

For the gen_tcp:accept/1,2 call, the values of the listening socket options are inherited. Therefore there is no corresponding application variable for accept.

Using the Kernel configuration parameters above, one can set default options for all TCP sockets on a node, but use this with care. Options such as {delay_send,true} can be specified in this way. The following is an example of starting an Erlang node with all sockets using delayed send:

$ erl -sname test -kernel \
inet_default_connect_options '[{delay_send,true}]' \
inet_default_listen_options '[{delay_send,true}]'

Please note that the default option {active, true} cannot be changed, for internal implementation reasons.

Addresses as inputs to functions can be either a string or a tuple. For example, the IP address 150.236.20.73 can be passed to gethostbyaddr/1, either as a string "150.236.20.73" or as a tuple {150, 236, 20, 73}.

IPv4 address examples:

Address          ip_address()
-------          ------------
127.0.0.1        {127,0,0,1}
192.168.42.2     {192,168,42,2}

IPv6 address examples:

Address          ip_address()
-------          ------------
::1             {0,0,0,0,0,0,0,1}
::192.168.42.2  {0,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2}
::FFFF:192.168.42.2
                {0,0,0,0,0,16#FFFF,(192 bsl 8) bor 168,(42 bsl 8) bor 2}
3ffe:b80:1f8d:2:204:acff:fe17:bf38
                {16#3ffe,16#b80,16#1f8d,16#2,16#204,16#acff,16#fe17,16#bf38}
fe80::204:acff:fe17:bf38
                {16#fe80,0,0,0,16#204,16#acff,16#fe17,16#bf38}

Function parse_address/1 can be useful:

1> inet:parse_address("192.168.42.2").
{ok,{192,168,42,2}}
2> inet:parse_address("::FFFF:192.168.42.2").
{ok,{0,0,0,0,0,65535,49320,10754}}

POSIX Error Codes

e2big - Too long argument list

eacces - Permission denied

eaddrinuse - Address already in use

eaddrnotavail - Cannot assign requested address

eadv - Advertise error

eafnosupport - Address family not supported by protocol family

eagain - Resource temporarily unavailable

ealign - EALIGN

ealready - Operation already in progress

ebade - Bad exchange descriptor

ebadf - Bad file number

ebadfd - File descriptor in bad state

ebadmsg - Not a data message

ebadr - Bad request descriptor

ebadrpc - Bad RPC structure

ebadrqc - Bad request code

ebadslt - Invalid slot

ebfont - Bad font file format

ebusy - File busy

echild - No children

echrng - Channel number out of range

ecomm - Communication error on send

econnaborted - Software caused connection abort

econnrefused - Connection refused

econnreset - Connection reset by peer

edeadlk - Resource deadlock avoided

edeadlock - Resource deadlock avoided

edestaddrreq - Destination address required

edirty - Mounting a dirty fs without force

edom - Math argument out of range

edotdot - Cross mount point

edquot - Disk quota exceeded

eduppkg - Duplicate package name

eexist - File already exists

efault - Bad address in system call argument

efbig - File too large

ehostdown - Host is down

ehostunreach - Host is unreachable

eidrm - Identifier removed

einit - Initialization error

einprogress - Operation now in progress

eintr - Interrupted system call

einval - Invalid argument

eio - I/O error

eisconn - Socket is already connected

eisdir - Illegal operation on a directory

eisnam - Is a named file

el2hlt - Level 2 halted

el2nsync - Level 2 not synchronized

el3hlt - Level 3 halted

el3rst - Level 3 reset

elbin - ELBIN

elibacc - Cannot access a needed shared library

elibbad - Accessing a corrupted shared library

elibexec - Cannot exec a shared library directly

elibmax - Attempting to link in more shared libraries than system limit

elibscn - .lib section in a.out corrupted

elnrng - Link number out of range

eloop - Too many levels of symbolic links

emfile - Too many open files

emlink - Too many links

emsgsize - Message too long

emultihop - Multihop attempted

enametoolong - Filename too long

enavail - Unavailable

enet - ENET

enetdown - Network is down

enetreset - Network dropped connection on reset

enetunreach - Network is unreachable

enfile - File table overflow

enoano - Anode table overflow

enobufs - No buffer space available

enocsi - No CSI structure available

enodata - No data available

enodev - No such device

enoent - No such file or directory

enoexec - Exec format error

enolck - No locks available

enolink - Link has been severed

enomem - Not enough memory

enomsg - No message of desired type

enonet - Machine is not on the network

enopkg - Package not installed

enoprotoopt - Bad protocol option

enospc - No space left on device

enosr - Out of stream resources or not a stream device

enosym - Unresolved symbol name

enosys - Function not implemented

enotblk - Block device required

enotconn - Socket is not connected

enotdir - Not a directory

enotempty - Directory not empty

enotnam - Not a named file

enotsock - Socket operation on non-socket

enotsup - Operation not supported

enotty - Inappropriate device for ioctl

enotuniq - Name not unique on network

enxio - No such device or address

eopnotsupp - Operation not supported on socket

eperm - Not owner

epfnosupport - Protocol family not supported

epipe - Broken pipe

eproclim - Too many processes

eprocunavail - Bad procedure for program

eprogmismatch - Wrong program version

eprogunavail - RPC program unavailable

eproto - Protocol error

eprotonosupport - Protocol not supported

eprototype - Wrong protocol type for socket

erange - Math result unrepresentable

erefused - EREFUSED

eremchg - Remote address changed

eremdev - Remote device

eremote - Pathname hit remote filesystem

eremoteio - Remote I/O error

eremoterelease - EREMOTERELEASE

erofs - Read-only filesystem

erpcmismatch - Wrong RPC version

erremote - Object is remote

eshutdown - Cannot send after socket shutdown

esocktnosupport - Socket type not supported

espipe - Invalid seek

esrch - No such process

esrmnt - Srmount error

estale - Stale remote file handle

esuccess - Error 0

etime - Timer expired

etimedout - Connection timed out

etoomanyrefs - Too many references

etxtbsy - Text file or pseudo-device busy

euclean - Structure needs cleaning

eunatch - Protocol driver not attached

eusers - Too many users

eversion - Version mismatch

ewouldblock - Operation would block

exdev - Cross-device link

exfull - Message tables full

nxdomain - Hostname or domain name cannot be found

Summary

Types

address_family()

ancillary_data()

Ancillary data / control messages.

ether_address()

family_address()

A general network address.

getifaddrs_ifopts()

Interface address description list.

hostent()

A record describing a host; name and address.

hostname()

i_option()

Options for selecting statistics items.

inet6_address()

A network address for the inet6 family (AF_INET6, IPv6)

inet_address()

A network address for the inet family (AF_INET, IPv4)

inet_backend()

Implementation backend selector for socket/0.

ip4_address()

ip6_address()

ip_address()

local_address()

A network address for the local family (AF_LOCAL | AF_UNIX)

module_socket()

port_number()

posix()

POSIX Error Code atom/0.

returned_non_ip_address()

a non-IP network address.

socket()

A socket recognized by this module and its siblings.

socket_address()

socket_getopt()

socket_optval()

socket_protocol()

socket_setopt()

stat_option()

Functions

cancel_monitor(MRef)

Cancel a socket monitor.

close(Socket)

Close a socket of any type.

format_error(Reason)

Format an error code into a string/0.

get_rc()

Get the inet configuration.

getaddr(Host, Family)

Resolve a host to an address, in a specific addresss family.

getaddrs(Host, Family)

Resolve a host to a list of addresses, in a specific address family.

gethostbyaddr(Address)

Resolve (reverse) an address to a #hostent{} record.

gethostbyname(Hostname)

Resolve a hostname to a #hostent{} record.

gethostbyname(Hostname, Family)

Resolve a hostname to a #hostent{} record, in a specific address family.

gethostname()

Get the local hostname.

getifaddrs()

Get interface names and addresses.

getifaddrs/1

Get interface names and addresses, in a specific namespace.

getopts(Socket, Options)

Get one or more options for a socket.

getstat(Socket)

Equivalent to getstat/2.

getstat(Socket, Options)

Get one or more statistics options for a socket.

i()

Equivalent to i/1 for the protocols tcp, udp, and sctp

i/1

List network sockets.

i/2

List network sockets.

info(Socket)

Get information about a socket.

ipv4_mapped_ipv6_address/1

Convert between an IPv4 address and an IPv4-mapped IPv6 address.

is_ip_address(IPAddress)

Test for an IP address.

is_ipv4_address(IPv4Address)

Test for an IPv4 address.

is_ipv6_address(IPv6Address)

Test for an IPv6 address.

monitor(Socket)

Start a socket monitor.

ntoa(IpAddress)

Parse an ip_address/0 to an IPv4 or IPv6 address string.

parse_address(Address)

Parse an IP address string to an ip_address/0.

parse_ipv4_address(Address)

Parse (relaxed) an IPv4 address string to an ip4_address/0.

parse_ipv4strict_address(Address)

Parse an IPv4 address string to an ip4_address/0.

parse_ipv6_address(Address)

Parse (relaxed) an IPv6 address string to an ip6_address/0.

parse_ipv6strict_address(Address)

Parse an IPv6 address string to an ip6_address/0.

parse_strict_address(Address)

Parse an IP address string to an ip_address/0.

peername(Socket)

Return the address of the socket's remote end.

peernames(Socket)

Equivalent to peernames(Socket, 0).

peernames(Socket, Assoc)

Return the addresses of all remote ends of a socket.

port(Socket)

Return the local port number for a socket.

setopts(Socket, Options)

Set one or more options for a socket.

sockname(Socket)

Return the local address and port number for a socket.

socknames(Socket)

Equivalent to socknames(Socket, 0).

socknames(Socket, Assoc)

Return all localaddresses for a socket.

Types

address_family()

-type address_family() :: inet | inet6 | local.

ancillary_data()

-type ancillary_data() :: [{tos, byte()} | {tclass, byte()} | {ttl, byte()}].

Ancillary data / control messages.

Ancillary data received with a data packet, read with the socket option pktoptions from a TCP socket, or to set in a call to gen_udp:send/4 or gen_udp:send/5.

The value(s) correspond to the currently active socket options recvtos, recvtclass and recvttl, or for a single send operation the option(s) to override the currently active socket option(s).

ether_address()

(not exported)

-type ether_address() :: [0..255].

family_address()

-type family_address() :: inet_address() | inet6_address() | local_address().

A general network address.

A general network address format of the form {Family, Destination} where Family is an atom such as local and the format of Destination depends on Family. Destination is a complete address (for example an IP address with port number).

getifaddrs_ifopts()

(not exported)

-type getifaddrs_ifopts() ::
          [Ifopt ::
               {flags, Flags :: [up | broadcast | loopback | pointtopoint | running | multicast]} |
               {addr, Addr :: ip_address()} |
               {netmask, Netmask :: ip_address()} |
               {broadaddr, Broadaddr :: ip_address()} |
               {dstaddr, Dstaddr :: ip_address()} |
               {hwaddr, Hwaddr :: [byte()]}].

Interface address description list.

A list returned from getifaddrs/0,1 for a named interface, translated from the returned data of the POSIX API function getaddrinfo().

Hwaddr is hardware dependent, for example, on Ethernet interfaces it is the 6-byte Ethernet address (MAC address (EUI-48 address)).

The tuples {addr,Addr}, {netmask,Netmask}, and possibly {broadaddr,Broadaddr} or {dstaddr,Dstaddr} are repeated in the list if the interface has got multiple addresses. An interface may have multiple {flag,_} tuples for example if it has different flags for different address families.

Multiple {hwaddr,Hwaddr} tuples is hard to say anything definite about, though. The tuple {flag,Flags} is mandatory, all others are optional.

Do not rely too much on the order of Flags atoms or the Ifopt tuples. There are however some rules:

A {flag,_} tuple applies to all other tuples that follow.

Immediately after {addr,_} follows {netmask,_}.

Immediately thereafter may {broadaddr,_} follow if broadcast is member of Flags, or {dstaddr,_} if pointtopoint is member of Flags. Both {dstaddr,_} and {broadaddr,_} doesn't occur for the same {addr,_}.

Any {netmask,_}, {broadaddr,_}, or {dstaddr,_} tuples that follow an {addr,Addr} tuple concerns the address Addr.

The tuple {hwaddr,_} is not returned on Solaris, as the hardware address historically belongs to the link layer and it is not returned by the Solaris API function getaddrinfo().

Warning

On Windows, the data is fetched from different OS API functions, so the Netmask and Broadaddr values may be calculated, just as some Flags values.

hostent()

-type hostent() ::
          #hostent{h_name :: inet:hostname(),
                   h_aliases :: [inet:hostname()],
                   h_addrtype :: inet | inet6,
                   h_length :: non_neg_integer(),
                   h_addr_list :: [inet:ip_address()]}.

A record describing a host; name and address.

Corresponds to the C: struct hostent as returned by for example gethostbyname(3).

The record is defined in the Kernel include file "inet.hrl".

Add the following directive to the module:

-include_lib("kernel/include/inet.hrl").

hostname()

-type hostname() :: atom() | string().

i_option()

(not exported)

-type i_option() ::
          port | module | recv | sent | owner | local_address |
          {local_address, ShowPorts :: boolean()} |
          foreign_address |
          {foreign_address, ShowPorts :: boolean()} |
          state | type.

Options for selecting statistics items.

Regarding ShowPorts, see show_ports as described in the i/2 function, defaults to false.

inet6_address()

(not exported)

-type inet6_address() :: {inet6, {ip6_address() | any | loopback, port_number()}}.

A network address for the inet6 family (AF_INET6, IPv6)

Warning

This address format is currently experimental and for completeness to make all address families have a {Family, Destination} representation.

inet_address()

(not exported)

-type inet_address() :: {inet, {ip4_address() | any | loopback, port_number()}}.

A network address for the inet family (AF_INET, IPv4)

Warning

This address format is currently experimental and for completeness to make all address families have a {Family, Destination} representation.

inet_backend()

-type inet_backend() :: {inet_backend, inet | socket}.

Implementation backend selector for socket/0.

Selects the implementation backend for sockets. The current default is inet which uses inet_drv.c to call the platform's socket API. The value socket instead uses the socket module and its NIF implementation.

This is a temporary option that will be ignored in a future release.

ip4_address()

-type ip4_address() :: {0..255, 0..255, 0..255, 0..255}.

ip6_address()

-type ip6_address() :: {0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535}.

ip_address()

-type ip_address() :: ip4_address() | ip6_address().

local_address()

-type local_address() :: {local, File :: binary() | string()}.

A network address for the local family (AF_LOCAL | AF_UNIX)

This address family, also known as "Unix domain sockets" only works on Unix-like systems.

File is normally a file pathname in a local filesystem. It is limited in length by the operating system, traditionally to 108 bytes.

A binary/0 is passed as is to the operating system, but a string/0 is encoded according to the system filename encoding mode.

Other addresses are possible, for example Linux implements "Abstract Addresses". See the documentation for Unix Domain Sockets on your system, normally unix in manual section 7.

In most API functions where you can use this address family the port number must be 0.

module_socket()

(not exported)

-type module_socket() :: {'$inet', Handler :: module(), Handle :: term()}.

port_number()

-type port_number() :: 0..65535.

posix()

-type posix() ::
          eaddrinuse | eaddrnotavail | eafnosupport | ealready | econnaborted | econnrefused |
          econnreset | edestaddrreq | ehostdown | ehostunreach | einprogress | eisconn | emsgsize |
          enetdown | enetunreach | enopkg | enoprotoopt | enotconn | enotty | enotsock | eproto |
          eprotonosupport | eprototype | esocktnosupport | etimedout | ewouldblock | exbadport |
          exbadseq |
          file:posix().

POSIX Error Code atom/0.

An atom that is named from the POSIX error codes used in Unix, and in the runtime libraries of most C compilers. See section POSIX Error Codes.

returned_non_ip_address()

-type returned_non_ip_address() :: {local, binary()} | {unspec, <<>>} | {undefined, any()}.

a non-IP network address.

Addresses besides ip_address/0 ones that are returned from socket API functions. See in particular local_address/0. The unspec family corresponds to AF_UNSPEC and can occur if the other side has no socket address. The undefined family can only occur in the unlikely event of an address family that the VM doesn't recognize.

socket()

-type socket() :: port() | module_socket().

A socket recognized by this module and its siblings.

See gen_tcp:socket/0 and gen_udp:socket/0.

socket_address()

-type socket_address() :: ip_address() | any | loopback | local_address().

socket_getopt()

-type socket_getopt() :: gen_sctp:option_name() | gen_tcp:option_name() | gen_udp:option_name().

socket_optval()

-type socket_optval() ::
          gen_sctp:option_value() | gen_tcp:option() | gen_udp:option() | gen_tcp:pktoptions_value().

socket_protocol()

-type socket_protocol() :: tcp | udp | sctp.

socket_setopt()

-type socket_setopt() :: gen_sctp:option() | gen_tcp:option() | gen_udp:option().

stat_option()

-type stat_option() ::
          recv_cnt | recv_max | recv_avg | recv_oct | recv_dvi | send_cnt | send_max | send_avg |
          send_oct | send_pend.

Functions

cancel_monitor(MRef)

(since OTP 24.0)

-spec cancel_monitor(MRef) -> boolean() when MRef :: reference().

Cancel a socket monitor.

If MRef is a reference that the calling process obtained by calling monitor/1, this monitor is removed. If the monitoring is already removed, nothing happens.

The returned value is one of the following:

true - The monitor was found and removed. In this case, no 'DOWN' message corresponding to this monitor has been delivered and will not be delivered.

false - The monitor was not found and couldn't be removed. Probably because the monitor has already triggered and there is a corresponding 'DOWN' message in the caller message queue.

close(Socket)

-spec close(Socket) -> ok when Socket :: socket().

Close a socket of any type.

format_error(Reason)

-spec format_error(Reason) -> string() when Reason :: posix() | system_limit.

Format an error code into a string/0.

Returns a diagnostic error string. For possible POSIX values and corresponding strings, see section POSIX Error Codes.

get_rc()

-spec get_rc() -> [{Par :: atom(), Val :: any()} | {Par :: atom(), Val1 :: any(), Val2 :: any()}].

Get the inet configuration.

Returns the state of the inet configuration database in form of a list of recorded configuration parameters. For more information, see ERTS User's Guide: Inet Configuration.

Only actual parameters with other than default values are returned, for example not directives that specify other sources for configuration parameters nor directives that clear parameters.

getaddr(Host, Family)

-spec getaddr(Host, Family) -> {ok, Address} | {error, posix()}
                 when
                     Host :: ip_address() | hostname(),
                     Family :: address_family(),
                     Address :: ip_address().

Resolve a host to an address, in a specific addresss family.

Returns the IP address for Host as a tuple of integers. Host can be an IP address, a single hostname/0, or a fully qualified hostname/0.

getaddrs(Host, Family)

-spec getaddrs(Host, Family) -> {ok, Addresses} | {error, posix()}
                  when
                      Host :: ip_address() | hostname(),
                      Family :: address_family(),
                      Addresses :: [ip_address()].

Resolve a host to a list of addresses, in a specific address family.

Returns a list of all IP addresses for Host. Host can be an IP address, a single hostname/0, or a fully qualified hostname/0.

gethostbyaddr(Address)

-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()}
                       when Address :: string() | ip_address(), Hostent :: hostent().

Resolve (reverse) an address to a #hostent{} record.

Returns a #hostent{} record for the host with the specified address.

gethostbyname(Hostname)

-spec gethostbyname(Hostname) -> {ok, Hostent} | {error, posix()}
                       when Hostname :: hostname(), Hostent :: hostent().

Resolve a hostname to a #hostent{} record.

Returns a #hostent{} record for the host with the specified Hostname.

This function uses the resolver, which is often the native (OS) resolver.

If resolver option inet6 is true, an IPv6 address is looked up.

See ERTS User's Guide: Inet Configuration for information about the resolver configuration.

A quirk of many resolvers is that an integer string is interpreted as an IP address. For instance, the integer string "3232235521" and the string "192.168.0.1" are both translated to the IP address {192,168,0,1}.

gethostbyname(Hostname, Family)

-spec gethostbyname(Hostname, Family) -> {ok, Hostent} | {error, posix()}
                       when Hostname :: hostname(), Family :: address_family(), Hostent :: hostent().

Resolve a hostname to a #hostent{} record, in a specific address family.

Returns a #hostent{} record for the host with the specified Hostname, restricted to the specified address Family.

See also gethostbyname/1.

gethostname()

-spec gethostname() -> {ok, Hostname} when Hostname :: string().

Get the local hostname.

Returns the local hostname. Never fails.

getifaddrs()

(since OTP R14B01)

-spec getifaddrs() -> {ok, [{Ifname :: string(), Ifopts :: getifaddrs_ifopts()}]} | {error, posix()}.

Get interface names and addresses.

Returns a list of 2-tuples containing interface names and the interfaces' addresses. Ifname is a Unicode string and Ifopts is a list of interface address description tuples.

The interface address description tuples are documented under the type of the Ifopts value.

getifaddrs/1

(since OTP 21.2)

-spec getifaddrs([Option :: inet_backend() | {netns, Namespace :: file:filename_all()}] | socket()) ->
                    {ok, [{Ifname :: string(), Ifopts :: getifaddrs_ifopts()}]} | {error, posix()}.

Get interface names and addresses, in a specific namespace.

Equivalent to getifaddrs/0, but accepts an Option {netns, Namespace} that, on platforms that support the feature (Linux), sets a network namespace for the OS call. Also, If the option 'inet_backend' is first in the options list, the specified backend will be used (for 'inet', inet and for 'socket' the equivalent net functions will be used).

See the socket option {netns, Namespace} under setopts/2.

getopts(Socket, Options)

-spec getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()}
                 when
                     Socket :: socket(), Options :: [socket_getopt()], OptionValues :: [socket_optval()].

Get one or more options for a socket.

Gets all options in the list Options from Socket. See setopts/2 for a list of available options. See also the descriptions of protocol specific types referenced by socket_optval() .

The number of elements in the returned OptionValues list does not necessarily correspond to the number of options asked for. If the operating system fails to support an option, it is left out in the returned list. An error tuple is returned only when getting options for the socket is impossible (that is, the socket is closed or the buffer size in a raw request is too large). This behavior is kept for backward compatibility reasons.

A raw option request RawOptReq = {raw, Protocol, OptionNum, ValueSpec} can be used to get information about socket options not (explicitly) supported by the emulator. The use of raw socket options makes the code non-portable, but allows the Erlang programmer to take advantage of unusual features present on a particular platform.

RawOptReq consists of tag raw followed by the protocol level, the option number, and either a binary or the size, in bytes, of the buffer in which the option value is to be stored. A binary is to be used when the underlying getsockopt requires input in the argument field. In this case, the binary size shall correspond to the required buffer size of the return value. The supplied values in a RawOptReq correspond to the second, third, and fourth/fifth parameters to the getsockopt call in the C socket API. The value stored in the buffer is returned as a binary ValueBin, where all values are coded in native endianness.

Asking for and inspecting raw socket options require low-level information about the current operating system and TCP stack.

Example:

Consider a Linux machine where option TCP_INFO can be used to collect TCP statistics for a socket. Assume you are interested in field tcpi_sacked of struct tcp_info filled in when asking for TCP_INFO. To be able to access this information, you need to know the following:

The numeric value of protocol level IPPROTO_TCP

The numeric value of option TCP_INFO

The size of struct tcp_info

The size and offset of the specific field

By inspecting the headers or writing a small C program, it is found that IPPROTO_TCP is 6, TCP_INFO is 11, the structure size is 92 (bytes), the offset of tcpi_sacked is 28 bytes, and the value is a 32-bit integer. The following code can be used to retrieve the value:

get_tcpi_sacked(Sock) ->
    {ok,[{raw,_,_,Info}]} = inet:getopts(Sock,[{raw,6,11,92}]),
    <<_:28/binary,TcpiSacked:32/native,_/binary>> = Info,
    TcpiSacked.

Preferably, you would check the machine type, the operating system, and the Kernel version before executing anything similar to this code.

getstat(Socket)

-spec getstat(Socket) -> {ok, OptionValues} | {error, posix()}
                 when Socket :: socket(), OptionValues :: [{stat_option(), integer()}].

Equivalent to getstat/2.

getstat(Socket, Options)

-spec getstat(Socket, Options) -> {ok, OptionValues} | {error, posix()}
                 when
                     Socket :: socket(),
                     Options :: [stat_option()],
                     OptionValues :: [{stat_option(), integer()}].

Get one or more statistics options for a socket.

getstat(Socket) is equivalent to getstat(Socket, [recv_avg, recv_cnt, recv_dvi, recv_max, recv_oct, send_avg, send_cnt, send_pend, send_max, send_oct]).

The following options are available:

recv_avg - Average size of packets, in bytes, received by the socket.

recv_cnt - Number of packets received by the socket.

recv_dvi - Average packet size deviation, in bytes, received by the socket.

recv_max - Size of the largest packet, in bytes, received by the socket.

recv_oct - Number of bytes received by the socket.

send_avg - Average size of packets, in bytes, sent from the socket.

send_cnt - Number of packets sent from the socket.

send_pend - Number of bytes waiting to be sent by the socket.

send_max - Size of the largest packet, in bytes, sent from the socket.

send_oct - Number of bytes sent from the socket.

i()

(since OTP 21.0)

-spec i() -> ok.

Equivalent to i/1 for the protocols tcp, udp, and sctp

i/1

(since OTP 21.0)

-spec i(show_ports | socket_protocol() | [i_option()]) -> ok.

List network sockets.

With argument Proto equivalent to i(Proto, Options) where Options is a list of all atom/0s in i_option/0.

With argument Options, equivalent to `i(Proto, Options) for Proto: tcp, udp, and sctp.

With argument show_ports (since OTP 27.0) equivalent to `i(Proto, Options) where Option is a list of all options in i_option/0 with ShowPorts = true.

i/2

(since OTP 21.0)

-spec i(socket_protocol(), show_ports | (Options :: [i_option()])) -> ok.

List network sockets.

Lists all TCP, UDP and SCTP sockets on the terminal, those created by the Erlang runtime system as well as by the application.

The following options are available:

port - An internal index of the port.

module - The callback module of the socket.

recv - Number of bytes received by the socket.

sent - Number of bytes sent from the socket.

owner - The socket owner process.

local_address - The local address of the socket.

foreign_address - The address and port of the other end of the connection.

state - The connection state.

type - STREAM or DGRAM or SEQPACKET.

The Options argument may also be (since OTP 27.0):

show_ports - Do not translate the port numbers (of 'local_address' and 'foreign_address') to service name(s).

info(Socket)

(since OTP 24.0)

-spec info(Socket) -> Info when Socket :: socket(), Info :: term().

Get information about a socket.

Returns a term containing miscellaneous information about a socket.

ipv4_mapped_ipv6_address/1

(since OTP 21.0)

-spec ipv4_mapped_ipv6_address(ip_address()) -> ip_address().

Convert between an IPv4 address and an IPv4-mapped IPv6 address.

Convert an IPv4 address to an IPv4-mapped IPv6 address or the reverse. When converting from an IPv6 address all but the 2 low words are ignored so this function also works on some other types of IPv6 addresses than IPv4-mapped.

is_ip_address(IPAddress)

(since OTP 25.0)

-spec is_ip_address(IPAddress) -> boolean() when IPAddress :: ip_address() | term().

Test for an IP address.

Tests if the argument IPAddress is an ip_address/0 and if so returns true, otherwise false.

is_ipv4_address(IPv4Address)

(since OTP 25.0)

-spec is_ipv4_address(IPv4Address) -> boolean() when IPv4Address :: ip4_address() | term().

Test for an IPv4 address.

Tests if the argument IPv4Address is an ip4_address/0 and if so returns true, otherwise false.

is_ipv6_address(IPv6Address)

(since OTP 25.0)

-spec is_ipv6_address(IPv6Address) -> boolean() when IPv6Address :: ip6_address() | term().

Test for an IPv6 address.

Tests if the argument IPv6Address is an ip6_address/0 and if so returns true, otherwise false.

monitor(Socket)

(since OTP 24.0)

-spec monitor(Socket) -> reference() when Socket :: socket().

Start a socket monitor.

If the Socket to monitor doesn't exist or when the monitor is triggered, a 'DOWN' message is sent that has the following pattern:

	    {'DOWN', MonitorRef, Type, Object, Info}

MonitorRef - The return value from this function.

Type - The type of socket, can be one of the following atom/0s: port or socket.

Object - The monitored entity, the socket, which triggered the event.

Info - Either the termination reason of the socket or nosock (the Socket did not exist when this function was called).

Making several calls to inet:monitor/1 for the same Socket is not an error; one monitor is created per call.

The monitor is triggered when the socket is closed in any way such as an API call, remote end close, closed by signal when owner exits, ...

ntoa(IpAddress)

(since OTP R16B02)

-spec ntoa(IpAddress) -> Address | {error, einval} when Address :: string(), IpAddress :: ip_address().

Parse an ip_address/0 to an IPv4 or IPv6 address string.

parse_address(Address)

(since OTP R16B)

-spec parse_address(Address) -> {ok, IPAddress} | {error, einval}
                       when Address :: string(), IPAddress :: ip_address().

Parse an IP address string to an ip_address/0.

Returns an ip4_address/0 or an ip6_address/0 depending on which parsing that succeeds.

Accepts a short form IPv4 address string like parse_ipv4_address/1.

parse_ipv4_address(Address)

(since OTP R16B)

-spec parse_ipv4_address(Address) -> {ok, IPv4Address} | {error, einval}
                            when Address :: string(), IPv4Address :: ip4_address().

Parse (relaxed) an IPv4 address string to an ip4_address/0.

Accepts a short form IPv4 address string (less than 4 fields) such as "127.1" or "0x7f000001".

parse_ipv4strict_address(Address)

(since OTP R16B)

-spec parse_ipv4strict_address(Address) -> {ok, IPv4Address} | {error, einval}
                                  when Address :: string(), IPv4Address :: ip4_address().

Parse an IPv4 address string to an ip4_address/0.

Requires an IPv4 address string containing four fields, that is; not a short form address string.

parse_ipv6_address(Address)

(since OTP R16B)

-spec parse_ipv6_address(Address) -> {ok, IPv6Address} | {error, einval}
                            when Address :: string(), IPv6Address :: ip6_address().

Parse (relaxed) an IPv6 address string to an ip6_address/0.

Also accepts a (relaxed) IPv4 address string like parse_ipv4_address/1 and returns an IPv4-mapped IPv6 address.

parse_ipv6strict_address(Address)

(since OTP R16B)

-spec parse_ipv6strict_address(Address) -> {ok, IPv6Address} | {error, einval}
                                  when Address :: string(), IPv6Address :: ip6_address().

Parse an IPv6 address string to an ip6_address/0.

Doesn't accept an IPv4 address string. An IPv6 address string, though, allows an IPv4 tail like this: "::127.0.0.1" (which is the same as "::7f00:0001").

parse_strict_address(Address)

(since OTP R16B)

-spec parse_strict_address(Address) -> {ok, IPAddress} | {error, einval}
                              when Address :: string(), IPAddress :: ip_address().

Parse an IP address string to an ip_address/0.

Like parse_address/1 but doesn't accept a short form IPv4 address string.

peername(Socket)

-spec peername(Socket :: socket()) ->
                  {ok, {ip_address(), port_number()} | returned_non_ip_address()} | {error, posix()}.

Return the address of the socket's remote end.

Returns the address and port for the other end of a connection.

Notice that for SCTP sockets, this function returns only one of the peer addresses of the socket. Function peernames/1,2 returns all.

peernames(Socket)

(since OTP R16B03)

-spec peernames(Socket :: socket()) ->
                   {ok, [{ip_address(), port_number()} | returned_non_ip_address()]} | {error, posix()}.

Equivalent to peernames(Socket, 0).

Notice that the behavior of this function for an SCTP one-to-many style socket is not defined by the SCTP Sockets API Extensions.

peernames(Socket, Assoc)

(since OTP R16B03)

-spec peernames(Socket, Assoc) -> {ok, [{Address, Port}]} | {error, posix()}
                   when
                       Socket :: socket(),
                       Assoc ::
                           #sctp_assoc_change{state :: term(),
                                              error :: term(),
                                              outbound_streams :: term(),
                                              inbound_streams :: term(),
                                              assoc_id :: term()} |
                           gen_sctp:assoc_id(),
                       Address :: ip_address(),
                       Port :: non_neg_integer().

Return the addresses of all remote ends of a socket.

Returns a list of all address/port number pairs for the remote end of an association Assoc of a socket.

This function can return multiple addresses for multihomed sockets, such as SCTP sockets. For other sockets it returns a one-element list.

Notice that parameter Assoc is by the SCTP Sockets API Extensions defined to be ignored for one-to-one style sockets. What the special value 0 means, is unfortunately undefined, and hence the behavior for one-to-many style sockets.

port(Socket)

-spec port(Socket) -> {ok, Port} | {error, any()} when Socket :: socket(), Port :: port_number().

Return the local port number for a socket.

setopts(Socket, Options)

-spec setopts(Socket, Options) -> ok | {error, posix()}
                 when Socket :: socket(), Options :: [socket_setopt()].

Set one or more options for a socket.

Sets the list of Options on Socket.

The following options are available:

{active, true | false | once | N} - If the value is true, which is the default, everything received from the socket is sent as messages to the receiving process.

If the value is false (passive mode), the process must explicitly receive incoming data by calling gen_tcp:recv/2,3, gen_udp:recv/2,3, or gen_sctp:recv/1,2 (depending on the type of socket).

If the value is once ({active, once}), one data message from the socket is sent to the process. To receive one more message, setopts/2 must be called again with option {active, once}.

If the value is an integer N in the range -32768 to 32767 (inclusive), the value is added to the socket's count of data messages sent to the controlling process. A socket's default message count is 0. If a negative value is specified, and its magnitude is equal to or greater than the socket's current message count, the socket's message count is set to 0. Once the socket's message count reaches 0, either because of sending received data messages to the process or by being explicitly set, the process is then notified by a special message, specific to the type of socket, that the socket has entered passive mode. Once the socket enters passive mode, to receive more messages setopts/2 must be called again to set the socket back into an active mode.

When using {active, once} or {active, N}, the socket changes behavior automatically when data is received. This can be confusing in combination with connection-oriented sockets (that is, gen_tcp), as a socket with {active, false} behavior reports closing differently than a socket with {active, true} behavior. To simplify programming, a socket where the peer closed, and this is detected while in {active, false} mode, still generates message {tcp_closed, Socket} when set to {active, once}, {active, true}, or {active, N} mode. It is therefore safe to assume that message {tcp_closed, Socket}, possibly followed by socket port termination (depending on option exit_on_close) eventually appears when a socket changes back and forth between {active, true} and {active, false} mode. However, when peer closing is detected it is all up to the underlying TCP/IP stack and protocol.

Notice that {active, true} mode provides no flow control; a fast sender can easily overflow the receiver with incoming messages. The same is true for {active, N} mode, while the message count is greater than zero.

Use active mode only if your high-level protocol provides its own flow control (for example, acknowledging received messages) or the amount of data exchanged is small. Using {active, false} mode, {active, once} mode, or {active, N} mode with values of N appropriate for the application to provide flow control, ensures the other side cannot send faster than the receiver can read.

{broadcast, Boolean} (UDP sockets) - Enables/disables permission to send broadcasts.

{buffer, Size} - The size of the user-level buffer used by the driver. Not to be confused with options sndbuf and recbuf, which correspond to the Kernel socket buffers. For TCP it is recommended to have val(buffer) >= val(recbuf) to avoid performance issues because of unnecessary copying. For UDP the same recommendation applies, but the max should not be larger than the MTU of the network path. val(buffer) is automatically set to the above maximum when recbuf is set. However, as the size set for recbuf usually become larger, you are encouraged to use getopts/2 to analyze the behavior of your operating system.

Note that this is also the maximum amount of data that can be received from a single recv call. If you are using higher than normal MTU consider setting buffer higher.

{delay_send, Boolean} - Normally, when an Erlang process sends to a socket, the driver tries to send the data immediately. If that fails, the driver uses any means available to queue up the message to be sent whenever the operating system says it can handle it. Setting {delay_send, true} makes all messages queue up. The messages sent to the network are then larger but fewer. The option affects the scheduling of send requests versus Erlang processes instead of changing any real property of the socket. The option is implementation-specific. Defaults to false.

{deliver, port | term} - When {active, true}, data is delivered on the form port : {S, {data, [H1,..Hsz | Data]}} or term : {tcp, S, [H1..Hsz | Data]}.

{dontroute, Boolean} - Enables/disables routing bypass for outgoing messages.

{exit_on_close, Boolean} - This option is set to true by default.

The only reason to set it to false is if you want to continue sending data to the socket after a close is detected, for example, if the peer uses gen_tcp:shutdown/2 to shut down the write side.

{exclusiveaddruse, Boolean} - Enables/disables exclusive address/port usage on Windows. That is, by enabling this option you can prevent other sockets from binding to the same address/port. By default this option is disabled. That is, other sockets may use the same address/port by setting {reuseaddr, true} in combination with {reuseport, true} unless {exclusiveaddruse, true} has been set on Socket. On non-Windows systems this option is silently ignored.

Note

This option is currently not supported for socket created with inet_backend = socket

{header, Size} - This option is only meaningful if option binary was specified when the socket was created. If option header is specified, the first Size number bytes of data received from the socket are elements of a list, and the remaining data is a binary specified as the tail of the same list. For example, if Size == 2, the data received matches [Byte1, Byte2 | Binary].

{high_msgq_watermark, Size} - The socket message queue is set to a busy state when the amount of data on the message queue reaches this limit. Notice that this limit only concerns data that has not yet reached the ERTS internal socket implementation. Defaults to 8 kB.

Senders of data to the socket are suspended if either the socket message queue is busy or the socket itself is busy.

For more information, see options low_msgq_watermark, high_watermark, and low_watermark.

Notice that distribution sockets disable the use of high_msgq_watermark and low_msgq_watermark. Instead use the distribution buffer busy limit, which is a similar feature.

{high_watermark, Size} (TCP/IP sockets) - The socket is set to a busy state when the amount of data queued internally by the ERTS socket implementation reaches this limit. Defaults to 8 kB.

Senders of data to the socket are suspended if either the socket message queue is busy or the socket itself is busy.

For more information, see options low_watermark, high_msgq_watermark, and low_msqg_watermark.

{ipv6_v6only, Boolean} - Restricts the socket to use only IPv6, prohibiting any IPv4 connections. This is only applicable for IPv6 sockets (option inet6).

On most platforms this option must be set on the socket before associating it to an address. It is therefore only reasonable to specify it when creating the socket and not to use it when calling function (setopts/2) containing this description.

The behavior of a socket with this option set to true is the only portable one. The original idea when IPv6 was new of using IPv6 for all traffic is now not recommended by FreeBSD (you can use {ipv6_v6only,false} to override the recommended system default value), forbidden by OpenBSD (the supported GENERIC kernel), and impossible on Windows (which has separate IPv4 and IPv6 protocol stacks). Most Linux distros still have a system default value of false. This policy shift among operating systems to separate IPv6 from IPv4 traffic has evolved, as it gradually proved hard and complicated to get a dual stack implementation correct and secure.

On some platforms, the only allowed value for this option is true, for example, OpenBSD and Windows. Trying to set this option to false, when creating the socket, fails in this case.

Setting this option on platforms where it does not exist is ignored. Getting this option with getopts/2 returns no value, that is, the returned list does not contain an {ipv6_v6only,_} tuple. On Windows, the option does not exist, but it is emulated as a read-only option with value true.

Therefore, setting this option to true when creating a socket never fails, except possibly on a platform where you have customized the kernel to only allow false, which can be doable (but awkward) on, for example, OpenBSD.

If you read back the option value using getopts/2 and get no value, the option does not exist in the host operating system. The behavior of both an IPv6 and an IPv4 socket listening on the same port, and for an IPv6 socket getting IPv4 traffic is then no longer predictable.

{keepalive, Boolean} (TCP/IP sockets) - Enables/disables periodic transmission on a connected socket when no other data is exchanged. If the other end does not respond, the connection is considered broken and an error message is sent to the controlling process. Defaults to false.

{keepcnt, Integer} (TCP/IP sockets) - Linux specific TCP_KEEPCNT.

{keepidle, Integer} (TCP/IP sockets) - Linux specific TCP_KEEPIDLE.

{keepintvl, Integer} (TCP/IP sockets) - Linux specific TCP_KEEPINTVL.

{linger, {true|false, Seconds}} - Determines the time-out, in seconds, for flushing unsent data in the close/1 socket call.

The first component is if linger is enabled, the second component is the flushing time-out, in seconds. There are 3 alternatives:

{false, _} - close/1 or shutdown/2 returns immediately, not waiting for data to be flushed, with closing happening in the background.

{true, 0} - Aborts the connection when it is closed. Discards any data still remaining in the send buffers and sends RST to the peer.

This avoids TCP's TIME_WAIT state, but leaves open the possibility that another "incarnation" of this connection being created.

{true, Time} when Time > 0 - close/1 or shutdown/2 will not return until all queued messages for the socket have been successfully sent or the linger timeout (Time) has been reached.

{low_msgq_watermark, Size} - If the socket message queue is in a busy state, the socket message queue is set in a not busy state when the amount of data queued in the message queue falls below this limit. Notice that this limit only concerns data that has not yet reached the ERTS internal socket implementation. Defaults to 4 kB.

Senders that are suspended because of either a busy message queue or a busy socket are resumed when the socket message queue and the socket are not busy.

For more information, see options high_msgq_watermark, high_watermark, and low_watermark.

Notice that distribution sockets disable the use of high_msgq_watermark and low_msgq_watermark. Instead they use the distribution buffer busy limit, which is a similar feature.

{low_watermark, Size} (TCP/IP sockets) - If the socket is in a busy state, the socket is set in a not busy state when the amount of data queued internally by the ERTS socket implementation falls below this limit. Defaults to 4 kB.

Senders that are suspended because of a busy message queue or a busy socket are resumed when the socket message queue and the socket are not busy.

For more information, see options high_watermark, high_msgq_watermark, and low_msgq_watermark.

{mode, Mode :: binary | list} - Received Packet is delivered as defined by Mode.

{netns, Namespace :: file:filename_all()} - Sets a network namespace for the socket. Parameter Namespace is a filename defining the namespace, for example, "/var/run/netns/example", typically created by command ip netns add example. This option must be used in a function call that creates a socket, that is, gen_tcp:connect/3,4, gen_tcp:listen/2, gen_udp:open/1,2 or gen_sctp:open/0,1,2, and also getifaddrs/1.

This option uses the Linux-specific syscall setns(), such as in Linux kernel 3.0 or later, and therefore only exists when the runtime system is compiled for such an operating system.

The virtual machine also needs elevated privileges, either running as superuser or (for Linux) having capability CAP_SYS_ADMIN according to the documentation for setns(2). However, during testing also CAP_SYS_PTRACE and CAP_DAC_READ_SEARCH have proven to be necessary.

Example:

setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp

Notice that the filesystem containing the virtual machine executable (beam.smp in the example) must be local, mounted without flag nosetuid, support extended attributes, and the kernel must support file capabilities. All this runs out of the box on at least Ubuntu 12.04 LTS, except that SCTP sockets appear to not support network namespaces.

Namespace is a filename and is encoded and decoded as discussed in module file, with the following exceptions:

Emulator flag +fnu is ignored.

getopts/2 for this option returns a binary for the filename if the stored filename cannot be decoded. This is only to occur if you set the option using a binary that cannot be decoded with the emulator's filename encoding: file:native_name_encoding/0.

{bind_to_device, Ifname :: binary()} - Binds a socket to a specific network interface. This option must be used in a function call that creates a socket, that is, gen_tcp:connect/3,4, gen_tcp:listen/2, gen_udp:open/1,2, or gen_sctp:open/0,1,2.

Unlike getifaddrs/0, Ifname is encoded a binary. In the unlikely case that a system is using non-7-bit-ASCII characters in network device names, special care has to be taken when encoding this argument.

This option uses the Linux-specific socket option SO_BINDTODEVICE, such as in Linux kernel 2.0.30 or later, and therefore only exists when the runtime system is compiled for such an operating system.

Before Linux 3.8, this socket option could be set, but could not retrieved with getopts/2. Since Linux 3.8, it is readable.

The virtual machine also needs elevated privileges, either running as superuser or (for Linux) having capability CAP_NET_RAW.

The primary use case for this option is to bind sockets into Linux VRF instances.

list - Received Packet is delivered as a list.

binary - Received Packet is delivered as a binary.

{nodelay, Boolean} (TCP/IP sockets) - If Boolean == true, option TCP_NODELAY is turned on for the socket, which means that also small amounts of data are sent immediately.

This option is not supported for domain = local, but if inet_backend =/= socket this error will be ignored.

{nopush, Boolean} (TCP/IP sockets) - This translates to TCP_NOPUSH on BSD and to TCP_CORK on Linux.

If Boolean == true, the corresponding option is turned on for the socket, which means that small amounts of data are accumulated until a full MSS-worth of data is available or this option is turned off.

Note that while TCP_NOPUSH socket option is available on OSX, its semantics is very different (e.g., unsetting it does not cause immediate send of accumulated data). Hence, nopush option is intentionally ignored on OSX.

{packet, PacketType} (TCP/IP sockets) - Defines the type of packets to use for a socket. Possible values:

raw | 0 - No packaging is done.

1 | 2 | 4 - Packets consist of a header specifying the number of bytes in the packet, followed by that number of bytes. The header length can be one, two, or four bytes, and containing an unsigned integer in big-endian byte order. Each send operation generates the header, and the header is stripped off on each receive operation.

The 4-byte header is limited to 2Gb.

asn1 | cdr | sunrm | fcgi | tpkt | line - These packet types only have effect on receiving. When sending a packet, it is the responsibility of the application to supply a correct header. On receiving, however, one message is sent to the controlling process for each complete packet received, and, similarly, each call to gen_tcp:recv/2,3 returns one complete packet. The header is not stripped off.

The meanings of the packet types are as follows:

asn1 - ASN.1 BER

sunrm - Sun's RPC encoding

cdr - CORBA (GIOP 1.1)

fcgi - Fast CGI

tpkt - TPKT format [RFC1006]

line - Line mode, a packet is a line-terminated with newline, lines longer than the receive buffer are truncated

http | http_bin - The Hypertext Transfer Protocol. The packets are returned with the format according to HttpPacket described in erlang:decode_packet/3 in ERTS. A socket in passive mode returns {ok, HttpPacket} from gen_tcp:recv while an active socket sends messages like {http, Socket, HttpPacket}.

httph | httph_bin - These two types are often not needed, as the socket automatically switches from http/http_bin to httph/httph_bin internally after the first line is read. However, there can be occasions when they are useful, such as parsing trailers from chunked encoding.

{packet_size, Integer}(TCP/IP sockets) - Sets the maximum allowed length of the packet body. If the packet header indicates that the length of the packet is longer than the maximum allowed length, the packet is considered invalid. The same occurs if the packet header is too large for the socket receive buffer.

For line-oriented protocols (line, http*), option packet_size also guarantees that lines up to the indicated length are accepted and not considered invalid because of internal buffer limitations.

{line_delimiter, Char} (TCP/IP sockets) - Sets the line delimiting character for line-oriented protocols (line). Defaults to $\n.

{raw, Protocol, OptionNum, ValueBin} - See below.

{read_ahead, Boolean} - If set to false avoids reading ahead from the OS socket layer. The default for this option is true which speeds up packet header parsing. Setting false has a performance penalty because the packet header has to be read first, to know exactly how many bytes to read for the body, which roughly doubles the number of read operations.

The use of this option is essential for example before switching to kTLS which activates OS socket layer encryption and decryption by setting special (raw) socket options. So if the Erlang socket layer has read ahead, it has read bytes that was for the OS socket layer to decrypt, which makes packet decryption derail for the connection.

Warning

For packet modes that doesn't have the packet length at a fixed location in a packet header, such as line or asn1, not reading ahead can become very inefficient since sometimes the only way to accomplish this is to read one byte at the time until the length or packet end is found.

{read_packets, Integer} (UDP sockets) - Sets the maximum number of UDP packets to read without intervention from the socket when data is available. When this many packets have been read and delivered to the destination process, new packets are not read until a new notification of available data has arrived. Defaults to 5. If this parameter is set too high, the system can become unresponsive because of UDP packet flooding.

{recbuf, Size} - The minimum size of the receive buffer to use for the socket. You are encouraged to use getopts/2 to retrieve the size set by your operating system.

{recvtclass, Boolean} - If set to true activates returning the received TCLASS value on platforms that implements the protocol IPPROTO_IPV6 option IPV6_RECVTCLASS or IPV6_2292RECVTCLASS for the socket. The value is returned as a {tclass,TCLASS} tuple regardless of if the platform returns an IPV6_TCLASS or an IPV6_RECVTCLASS CMSG value.

For packet oriented sockets that supports receiving ancillary data with the payload data (gen_udp and gen_sctp), the TCLASS value is returned in an extended return tuple contained in an ancillary data list. For stream oriented sockets (gen_tcp) the only way to get the TCLASS value is if the platform supports the pktoptions option.

{recvtos, Boolean} - If set to true activates returning the received TOS value on platforms that implements the protocol IPPROTO_IP option IP_RECVTOS for the socket. The value is returned as a {tos,TOS} tuple regardless of if the platform returns an IP_TOS or an IP_RECVTOS CMSG value.

For packet oriented sockets that supports receiving ancillary data with the payload data (gen_udp and gen_sctp), the TOS value is returned in an extended return tuple contained in an ancillary data list. For stream oriented sockets (gen_tcp) the only way to get the TOS value is if the platform supports the pktoptions option.

{recvttl, Boolean} - If set to true activates returning the received TTL value on platforms that implements the protocol IPPROTO_IP option IP_RECVTTL for the socket. The value is returned as a {ttl,TTL} tuple regardless of if the platform returns an IP_TTL or an IP_RECVTTL CMSG value.

For packet oriented sockets that supports receiving ancillary data with the payload data (gen_udp and gen_sctp), the TTL value is returned in an extended return tuple contained in an ancillary data list. For stream oriented sockets (gen_tcp) the only way to get the TTL value is if the platform supports the pktoptions option.

{reuseaddr, Boolean} - Allows or disallows reuse of local address. By default, reuse is disallowed.

Note

On windows {reuseaddr, true} will have no effect unless also {reuseport, true} is set. If both are set, the SO_REUSEADDR Windows socket option will be enabled. This since setting SO_REUSEADDR on Windows more or less has the same behavior as setting both SO_REUSEADDR and SO_REUSEPORT on BSD. This behavior was introduced as of OTP 26.0.

Change

Previous behavior on Windows:

Prior to OTP 25.0, the {reuseaddr, true} option was silently ignored.

Between OTP 25.0 and up to the predecessor of OTP 25.2, the underlying SO_REUSEADDR socket option was set if {reuseaddr, true} was set.

Between OTP 25.2 and up to the predecessor of OTP 26.0, the underlying SO_REUSEADDR socket option was only set on UDP sockets if {reuseaddr, true} was set, and silently ignored on other sockets.

See also the exclusiveaddruse option.

{reuseport, Boolean} - Allows or disallows reuse of local port which may or may not have load balancing depending on the underlying OS. By default, reuse is disallowed. See also reuseport_lb.

Note

On windows {reuseport, true} will have no effect unless also {reuseaddr, true} is set. If both are set, the SO_REUSEADDR Windows socket option will be enabled. This since setting SO_REUSEADDR on Windows more or less has the same behavior as setting both SO_REUSEADDR and SO_REUSEPORT on BSD. The reuseport option was introduced as of OTP 26.0.

See also the exclusiveaddruse option.

Note

reuseport may or may not be the same underlying option as reuseport_lb depending on the underlying OS. They, for example, are on Linux. When they are the same underlying option, operating on both may cause them to interact in surprising ways. For example, by enabling reuseport and then disabling reuseport_lb both will end up being disabled.

{reuseport_lb, Boolean} - Allows or disallows reuse of local port with load balancing. By default, reuse is disallowed. See also reuseport.

Note

reuseport_lb may or may not be the same underlying option as reuseport depending on the underlying OS. On Linux, for example, they are. And when they are the same underlying option, operating on both may cause them to interact in surprising ways. For example, by enabling reuseport_lb, and then disabling reuseport, both will end up being disabled.

{send_timeout, Integer} - Only allowed for connection-oriented sockets.

Specifies a longest time to wait for a send operation to be accepted by the underlying TCP stack. When the limit is exceeded, the send operation returns {error, timeout}. How much of a packet that got sent is unknown; the socket is therefore to be closed whenever a time-out has occurred (see send_timeout_close below). Defaults to infinity.

{send_timeout_close, Boolean} - Only allowed for connection-oriented sockets.

Used together with send_timeout to specify whether the socket is to be automatically closed when the send operation returns {error, timeout}. The recommended setting is true, which automatically closes the socket. Defaults to false because of backward compatibility.

{show_econnreset, Boolean} (TCP/IP sockets) - When this option is set to false, which is default, an RST received from the TCP peer is treated as a normal close (as though an FIN was sent). A caller to gen_tcp:recv/2 gets {error, closed}. In active mode, the controlling process receives a {tcp_closed, Socket} message, indicating that the peer has closed the connection.

Setting this option to true allows you to distinguish between a connection that was closed normally, and one that was aborted (intentionally or unintentionally) by the TCP peer. A call to gen_tcp:recv/2 returns {error, econnreset}. In active mode, the controlling process receives a {tcp_error, Socket, econnreset} message before the usual {tcp_closed, Socket}, as is the case for any other socket error. Calls to gen_tcp:send/2 also returns {error, econnreset} when it is detected that a TCP peer has sent an RST.

A connected socket returned from gen_tcp:accept/1 inherits the show_econnreset setting from the listening socket.

{sndbuf, Size} - The minimum size of the send buffer to use for the socket. You are encouraged to use getopts/2, to retrieve the size set by your operating system.

{priority, Integer} - Sets the SO_PRIORITY socket level option on platforms where this is implemented. The behavior and allowed range varies between different systems. The option is ignored on platforms where it is not implemented. Use with caution.

{tos, Integer} - Sets IP_TOS IP level options on platforms where this is implemented. The behavior and allowed range varies between different systems. The option is ignored on platforms where it is not implemented. Use with caution.

{tclass, Integer} - Sets IPV6_TCLASS IP level options on platforms where this is implemented. The behavior and allowed range varies between different systems. The option is ignored on platforms where it is not implemented. Use with caution.

{user_timeout, Integer} (TCP/IP sockets) - Linux specific TCP_USER_TIMEOUT.

In addition to these options, raw option specifications can be used. The raw options are specified as a tuple of arity four, beginning with tag raw, followed by the protocol level, the option number, and the option value specified as a binary. This corresponds to the second, third, and fourth arguments to the setsockopt call in the C socket API. The option value must be coded in the native endianness of the platform and, if a structure is required, must follow the structure alignment conventions on the specific platform.

Using raw socket options requires detailed knowledge about the current operating system and TCP stack.

Example:

This example concerns the use of raw options. Consider a Linux system where you want to set option TCP_LINGER2 on protocol level IPPROTO_TCP in the stack. You know that on this particular system it defaults to 60 (seconds), but you want to lower it to 30 for a particular socket. Option TCP_LINGER2 is not explicitly supported by inet, but you know that the protocol level translates to number 6, the option number to number 8, and the value is to be specified as a 32-bit integer. You can use this code line to set the option for the socket named Sock:

inet:setopts(Sock, [{raw,6,8,<<30:32/native>>}]),

As many options are silently discarded by the stack if they are specified out of range; it can be a good idea to check that a raw option is accepted. The following code places the value in variable TcpLinger2:

{ok,[{raw,6,8,<<TcpLinger2:32/native>>}]}=inet:getopts(Sock,[{raw,6,8,4}]),

Code such as these examples is inherently non-portable, even different versions of the same OS on the same platform can respond differently to this kind of option manipulation. Use with care.

Notice that the default options for TCP/IP sockets can be changed with the Kernel configuration parameters mentioned in the beginning of this manual page.

sockname(Socket)

-spec sockname(Socket :: socket()) ->
                  {ok, {ip_address(), port_number()} | returned_non_ip_address()} | {error, posix()}.

Return the local address and port number for a socket.

Notice that for SCTP sockets this function returns only one of the socket addresses. Function socknames/1,2 returns all.

socknames(Socket)

(since OTP R16B03)

-spec socknames(Socket :: socket()) ->
                   {ok, [{ip_address(), port_number()} | returned_non_ip_address()]} | {error, posix()}.

Equivalent to socknames(Socket, 0).

socknames(Socket, Assoc)

(since OTP R16B03)

-spec socknames(Socket, Assoc) -> {ok, [{Address, Port}]} | {error, posix()}
                   when
                       Socket :: socket(),
                       Assoc ::
                           #sctp_assoc_change{state :: term(),
                                              error :: term(),
                                              outbound_streams :: term(),
                                              inbound_streams :: term(),
                                              assoc_id :: term()} |
                           gen_sctp:assoc_id(),
                       Address :: ip_address(),
                       Port :: non_neg_integer().

Return all localaddresses for a socket.

Returns a list of all local address/port number pairs for a socket, for the specified association Assoc.

This function can return multiple addresses for multihomed sockets, such as SCTP sockets. For other sockets it returns a one-element list.

Notice that parameter Assoc is by the SCTP Sockets API Extensions defined to be ignored for one-to-one style sockets. For one-to-many style sockets, the special value 0 is defined to mean that the returned addresses must be without any particular association. How different SCTP implementations interpret this varies somewhat.

inet_res

A rudimentary DNS client.

This module performs DNS name resolving towards recursive name servers.

See also ERTS User's Guide: Inet Configuration or more information about how to configure an Erlang runtime system for IP communication, and how to enable this DNS client by defining 'dns' as a lookup method. The DNS client then acts as a backend for the resolving functions in inet.

This DNS client can resolve DNS records even if it is not used for normal name resolving in the node.

Warning

This is not a full-fledged resolver, only a DNS client that relies on being in trusted network shielded from DNS reply spoofing by firewalls, and on asking only trusted recursive name servers.

If the Crypto application is loaded, this implementation does its best to not be fooled by spoofed DNS replies. This is nevertheless a meager remedy compared to using encrypted and signed DNS methods like TSIG or DNSSEC, as full fledged resolvers do.

Note

If the Crypto application is loaded, this resolver client uses cryptographically random transaction IDs and port numbers, which should render the probability for a sucessfully brute force spoofed reply to be too low to be a usable exploit. An Erlang node that is installed in an exposed network environment should already have the Crypto application loaded for example to run the SSL application. If this is not the case, the Crypto application can be explicitly loaded with application:load(crypto).

Name Resolving

UDP queries are used unless resolver option usevc is true, which forces TCP queries. If the query is too large for UDP, TCP is used instead. For regular DNS queries, 512 bytes is the size limit.

When EDNS is enabled (resolver option edns is set to the EDNS version (that is; 0 instead of false), resolver option udp_payload_size sets the payload size limit. If a name server replies with the TC bit set (truncation), indicating that the answer is incomplete, the query is retried towards the same name server using TCP. Resolver option udp_payload_size also sets the advertised size for the maximum allowed reply size, if EDNS is enabled, otherwise the name server uses the limit 512 bytes. If the reply is larger, it gets truncated, forcing a TCP requery.

For UDP queries, resolver options timeout and retry control retransmission. Each name server in the nameservers list is tried with a time-out of timeout/retry. Then all name servers are tried again, doubling the time-out, for a total of retry times.

But before all name servers are tried again, there is a (user configurable) time-out, servfail_retry_timeout. The point of this is to prevent the new query to be handled by a server's servfail cache (a client that is too eager will actually only get what is in the servfail cache). If there is too little time left of the resolver call's time-out to do a retry, the resolver call may return before the call's time-out has expired.

For queries not using the search list, if the query to all nameservers results in {error,nxdomain} or an empty answer, the same query is tried for alt_nameservers.

If randomization of transaction ID:s and port numbers is too costly for an Erlang node in a trusted network shielded from DNS reply spoofing, the legacy behaviour to reuse the UDP socket on retries and use sequential transaction ID:s can be configured by setting the resolver option random to false.

Resolver Types

The following data types concern the resolver:

DNS Types

The following data types concern the DNS client:

Example

This access functions example shows how lookup/3 can be implemented using resolve/3 from outside the module:

example_lookup(Name, Class, Type) ->
    case inet_res:resolve(Name, Class, Type) of
        {ok,Msg} ->
            [inet_dns:rr(RR, data)
             || RR <- inet_dns:msg(Msg, anlist),
                 inet_dns:rr(RR, type) =:= Type,
                 inet_dns:rr(RR, class) =:= Class];
        {error,_} ->
            []
     end.

Summary

Types

dns_class()

dns_data()

DNS record data (content)

dns_msg()

A DNS message.

dns_name()

A string with no adjacent dots.

dns_rr_type()

hostent()

Extended variant of inet:hostent/0.

nameserver()

res_error()

res_option()

Legacy Functions

nnslookup(Name, Class, Type, Nameservers)

Equivalent to nnslookup(Name, Class, Type, NSs, infinity).

nnslookup(Name, Class, Type, Nameservers, Timeout)

Resolve a DNS query.

nslookup(Name, Class, Type)

Equivalent to nslookup(Name, Class, Type, infinity).

nslookup/4

Resolve a DNS query.

Functions

getbyname(Name, Type)

Equivalent to getbyname(Name, Type, [], infinity).

getbyname(Name, Type, Timeout)

Equivalent to getbyname(Name, Type, [], Timeout).

getbyname(Name, Type, Opts, Timeout)

Resolve a DNS query.

gethostbyaddr(Address)

Equivalent to gethostbyaddr(Address, infinity).

gethostbyaddr(Address, Timeout)

Backend function used by inet:gethostbyaddr/1.

gethostbyaddr(Address, Opts, Timeout)

Backend function used by inet:gethostbyaddr/1.

gethostbyname(Name)

Backend functions used by inet:gethostbyname/1,2.

gethostbyname(Name, Family)

Equivalent to gethostbyname(Name, Family, infinity).

gethostbyname(Name, Family, Timeout)

Equivalent to gethostbyname(Name, Family, [], Timeout).

gethostbyname(Name, Family, Opts, Timeout)

Backend functions used by inet:gethostbyname/1,2.

lookup(Name, Class, Type)

Equivalent to lookup(Name, Class, Type, [], infinity).

lookup(Name, Class, Type, Opts)

Equivalent to lookup(Name, Class, Type, Opts, infinity).

lookup(Name, Class, Type, Opts, Timeout)

Look up DNS data.

resolve(Name, Class, Type)

Equivalent to resolve(Name, Class, Type, [], infinity).

resolve(Name, Class, Type, Opts)

Equivalent to resolve(Name, Class, Type, Opts, infinity).

resolve(Name, Class, Type, Opts, Timeout)

Resolve a DNS query.

Types

dns_class()

(not exported)

-type dns_class() :: in | chaos | hs | any.

dns_data()

(not exported)

-type dns_data() ::
          dns_name() |
          inet:ip4_address() |
          inet:ip6_address() |
          {MName :: dns_name(),
           RName :: dns_name(),
           Serial :: integer(),
           Refresh :: integer(),
           Retry :: integer(),
           Expiry :: integer(),
           Minimum :: integer()} |
          {inet:ip4_address(), Proto :: integer(), BitMap :: binary()} |
          {CpuString :: string(), OsString :: string()} |
          {RM :: dns_name(), EM :: dns_name()} |
          {Prio :: integer(), dns_name()} |
          {Prio :: integer(), Weight :: integer(), Port :: integer(), dns_name()} |
          {Order :: integer(),
           Preference :: integer(),
           Flags :: string(),
           Services :: string(),
           Regexp :: string(),
           dns_name()} |
          [string()] |
          binary().

DNS record data (content)

The basic type of each data element is specified in this type.

Regexp is a UTF-8 string/0. The other string/0s are actually Latin-1 strings.

dns_msg()

(not exported)

-type dns_msg() :: term().

A DNS message.

This is the start of a hierarchy of opaque data structures that can be examined with access functions in inet_dns, which return lists of {Field,Value} tuples. The arity 2 functions return the value for a specified field.

dns_msg() = DnsMsg
    inet_dns:msg(DnsMsg) ->
        [ {header, dns_header()}
        | {qdlist, dns_query()}
        | {anlist, dns_rr()}
        | {nslist, dns_rr()}
        | {arlist, dns_rr()} ]
    inet_dns:msg(DnsMsg, header) -> dns_header() % for example
    inet_dns:msg(DnsMsg, Field) -> Value

dns_header() = DnsHeader
    inet_dns:header(DnsHeader) ->
        [ {id, integer()}
        | {qr, boolean()}
        | {opcode, query | iquery | status | integer()}
        | {aa, boolean()}
        | {tc, boolean()}
        | {rd, boolean()}
        | {ra, boolean()}
        | {pr, boolean()}
        | {rcode, integer(0..16)} ]
    inet_dns:header(DnsHeader, Field) -> Value

query_type() = axfr | mailb | maila | any | dns_rr_type()

dns_query() = DnsQuery
    inet_dns:dns_query(DnsQuery) ->
        [ {domain, dns_name()}
        | {type, query_type()}
        | {class, dns_class()} ]
    inet_dns:dns_query(DnsQuery, Field) -> Value

dns_rr() = DnsRr
    inet_dns:rr(DnsRr) -> DnsRrFields | DnsRrOptFields
    DnsRrFields = [ {domain, dns_name()}
                  | {type, dns_rr_type()}
                  | {class, dns_class()}
                  | {ttl, integer()}
                  | {data, dns_data()} ]
    DnsRrOptFields = [ {domain, dns_name()}
                     | {type, opt}
                     | {udp_payload_size, integer()}
                     | {ext_rcode, integer()}
                     | {version, integer()}
                     | {z, integer()}
                     | {data, dns_data()} ]
    inet_dns:rr(DnsRr, Field) -> Value

There is an information function for the types above:

inet_dns:record_type(dns_msg()) -> msg;
inet_dns:record_type(dns_header()) -> header;
inet_dns:record_type(dns_query()) -> dns_query;
inet_dns:record_type(dns_rr()) -> rr;
inet_dns:record_type(_) -> undefined.

So, inet_dns:(inet_dns:record_type(X))(X) converts any of these data structures into a {Field,Value} list.

dns_name()

(not exported)

-type dns_name() :: string().

A string with no adjacent dots.

dns_rr_type()

(not exported)

-type dns_rr_type() ::
          a | aaaa | caa | cname | gid | hinfo | ns | mb | md | mg | mf | minfo | mx | naptr | null |
          ptr | soa | spf | srv | txt | uid | uinfo | unspec | uri | wks.

hostent()

-type hostent() ::
          inet:hostent() |
          {hostent,
           H_name :: inet:hostname(),
           H_aliases :: [inet:hostname()],
           H_addrtype :: dns_rr_type(),
           H_length :: non_neg_integer(),
           H_addr_list :: [dns_data()]}.

Extended variant of inet:hostent/0.

Allows dns_rr_type/0 for the #hostent{}.h_addrtype field, and [dns_data/0] for the #hostent{}.h_addr_list field.

nameserver()

-type nameserver() :: {inet:ip_address(), Port :: 1..65535}.

res_error()

-type res_error() :: formerr | qfmterror | servfail | nxdomain | notimp | refused | badvers | timeout.

res_option()

-type res_option() ::
          {alt_nameservers, [nameserver()]} |
          {edns, 0 | false} |
          {inet6, boolean()} |
          {nameservers, [nameserver()]} |
          {recurse, boolean()} |
          {retry, integer()} |
          {timeout, integer()} |
          {udp_payload_size, integer()} |
          {dnssec_ok, boolean()} |
          {usevc, boolean()} |
          {random, boolean()} |
          {nxdomain_reply, boolean()}.

Legacy Functions

nnslookup(Name, Class, Type, Nameservers)

-spec nnslookup(Name, Class, Type, Nameservers) -> {ok, dns_msg()} | {error, Reason}
                   when
                       Name :: dns_name() | inet:ip_address(),
                       Class :: dns_class(),
                       Type :: dns_rr_type(),
                       Nameservers :: [nameserver()],
                       Reason :: inet:posix().

Equivalent to nnslookup(Name, Class, Type, NSs, infinity).

nnslookup(Name, Class, Type, Nameservers, Timeout)

-spec nnslookup(Name, Class, Type, Nameservers, Timeout) -> {ok, dns_msg()} | {error, Reason}
                   when
                       Name :: dns_name() | inet:ip_address(),
                       Class :: dns_class(),
                       Type :: dns_rr_type(),
                       Timeout :: timeout(),
                       Nameservers :: [nameserver()],
                       Reason :: inet:posix().

Resolve a DNS query.

Like nslookup/4 but calls resolve/5 with both the arguments Opts = [{nameservers, Nameservers}] and Timeout.

nslookup(Name, Class, Type)

-spec nslookup(Name, Class, Type) -> {ok, dns_msg()} | {error, Reason}
                  when
                      Name :: dns_name() | inet:ip_address(),
                      Class :: dns_class(),
                      Type :: dns_rr_type(),
                      Reason :: inet:posix() | res_error().

Equivalent to nslookup(Name, Class, Type, infinity).

nslookup/4

-spec nslookup(Name, Class, Type, Timeout) -> {ok, dns_msg()} | {error, Reason}
                  when
                      Name :: dns_name() | inet:ip_address(),
                      Class :: dns_class(),
                      Type :: dns_rr_type(),
                      Timeout :: timeout(),
                      Reason :: inet:posix() | res_error();
              (Name, Class, Type, Nameservers) -> {ok, dns_msg()} | {error, Reason}
                  when
                      Name :: dns_name() | inet:ip_address(),
                      Class :: dns_class(),
                      Type :: dns_rr_type(),
                      Nameservers :: [nameserver()],
                      Reason :: inet:posix() | res_error().

Resolve a DNS query.

This function is a legacy wrapper to resolve/5 that simplifies errors matching {error, {Reason, _}} into {error, Reason} or {error, einval}.

With argument Timeout calls resolve/5 with Opts = [].

With argument Nameservers calls resolve/5 with Opts = [{nameservers, Nameservers}] and Timeout = infinity.

Functions

getbyname(Name, Type)

-spec getbyname(Name, Type) -> {ok, Hostent} | {error, Reason}
                   when
                       Name :: dns_name(),
                       Type :: dns_rr_type(),
                       Hostent :: inet:hostent() | hostent(),
                       Reason :: inet:posix() | res_error().

Equivalent to getbyname(Name, Type, [], infinity).

getbyname(Name, Type, Timeout)

-spec getbyname(Name, Type, Timeout) -> {ok, Hostent} | {error, Reason}
                   when
                       Name :: dns_name(),
                       Type :: dns_rr_type(),
                       Timeout :: timeout(),
                       Hostent :: inet:hostent() | hostent(),
                       Reason :: inet:posix() | res_error().

Equivalent to getbyname(Name, Type, [], Timeout).

getbyname(Name, Type, Opts, Timeout)

(since OTP 28.1)

-spec getbyname(Name, Type, Opts, Timeout) -> {ok, Hostent} | {error, Reason}
                   when
                       Name :: dns_name(),
                       Type :: dns_rr_type(),
                       Opts :: [Opt],
                       Opt :: res_option() | verbose | atom(),
                       Timeout :: timeout(),
                       Hostent :: inet:hostent() | hostent(),
                       Reason :: inet:posix() | res_error().

Resolve a DNS query.

Resolves a DNS query of the specified Type for the specified host, of classin. Returns, on success, when resolving a Type = a|aaaa DNS record, a #hostent{} record with #hostent.h_addrtype = inet|inet6, respectively; see inet:hostent/0.

When resolving other Type = dns_rr_type():s (of class in), also returns a #hostent{} record but with dns_rr_type/0 in #hostent.h_addrtype, and the resolved dns_data/0 in #hostent.h_addr_list; see hostent/0.

This function uses resolver option search that is a list of domain names. If the name to resolve contains no dots, it is prepended to each domain name in the search list, and they are tried in order. If the name contains dots, it is first tried as an absolute name and if that fails, the search list is used. If the name has a trailing dot, it is supposed to be an absolute name and the search list is not used.

See resolve/5 about Opts.

gethostbyaddr(Address)

-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, Reason}
                       when
                           Address :: inet:ip_address(),
                           Hostent :: inet:hostent(),
                           Reason :: inet:posix() | res_error().

Equivalent to gethostbyaddr(Address, infinity).

gethostbyaddr(Address, Timeout)

-spec gethostbyaddr(Address, Timeout) -> {ok, Hostent} | {error, Reason}
                       when
                           Address :: inet:ip_address(),
                           Timeout :: timeout(),
                           Hostent :: inet:hostent(),
                           Reason :: inet:posix() | res_error().

Backend function used by inet:gethostbyaddr/1.

gethostbyaddr(Address, Opts, Timeout)

(since OTP 28.1)

-spec gethostbyaddr(Address, Opts, Timeout) -> {ok, Hostent} | {error, Reason}
                       when
                           Address :: inet:ip_address(),
                           Opts :: [Opt],
                           Opt :: res_option() | verbose | atom(),
                           Timeout :: timeout(),
                           Hostent :: inet:hostent(),
                           Reason :: inet:posix() | res_error().

Backend function used by inet:gethostbyaddr/1.

gethostbyname(Name)

-spec gethostbyname(Name) -> {ok, Hostent} | {error, Reason}
                       when
                           Name :: dns_name(),
                           Hostent :: inet:hostent(),
                           Reason :: inet:posix() | res_error().

Backend functions used by inet:gethostbyname/1,2.

If resolver option inet6 is true, equivalent to gethostbyname(Name, inet6, infinity), otherwise gethostbyname(Name, inet, infinity).

gethostbyname(Name, Family)

-spec gethostbyname(Name, Family) -> {ok, Hostent} | {error, Reason}
                       when
                           Name :: dns_name(),
                           Family :: inet:address_family(),
                           Hostent :: inet:hostent(),
                           Reason :: inet:posix() | res_error().

Equivalent to gethostbyname(Name, Family, infinity).

gethostbyname(Name, Family, Timeout)

-spec gethostbyname(Name, Family, Timeout) -> {ok, Hostent} | {error, Reason}
                       when
                           Name :: dns_name(),
                           Family :: inet:address_family(),
                           Timeout :: timeout(),
                           Hostent :: inet:hostent(),
                           Reason :: inet:posix() | res_error().

Equivalent to gethostbyname(Name, Family, [], Timeout).

gethostbyname(Name, Family, Opts, Timeout)

(since OTP 28.1)

-spec gethostbyname(Name, Family, Opts, Timeout) -> {ok, Hostent} | {error, Reason}
                       when
                           Name :: dns_name(),
                           Family :: inet:address_family(),
                           Opts :: [Opt],
                           Opt :: res_option() | verbose | atom(),
                           Timeout :: timeout(),
                           Hostent :: inet:hostent(),
                           Reason :: inet:posix() | res_error().

Backend functions used by inet:gethostbyname/1,2.

This function uses resolver option search just like getbyname/2,3.

lookup(Name, Class, Type)

-spec lookup(Name, Class, Type) -> [dns_data()]
                when Name :: dns_name() | inet:ip_address(), Class :: dns_class(), Type :: dns_rr_type().

Equivalent to lookup(Name, Class, Type, [], infinity).

lookup(Name, Class, Type, Opts)

-spec lookup(Name, Class, Type, Opts) -> [dns_data()]
                when
                    Name :: dns_name() | inet:ip_address(),
                    Class :: dns_class(),
                    Type :: dns_rr_type(),
                    Opts :: [res_option() | verbose].

Equivalent to lookup(Name, Class, Type, Opts, infinity).

lookup(Name, Class, Type, Opts, Timeout)

-spec lookup(Name, Class, Type, Opts, Timeout) -> [dns_data()]
                when
                    Name :: dns_name() | inet:ip_address(),
                    Class :: dns_class(),
                    Type :: dns_rr_type(),
                    Opts :: [res_option() | verbose],
                    Timeout :: timeout().

Look up DNS data.

Resolves the DNS data for the record Name of the specified Type and Class. On success, filters out the answer records with the correct Class and Type, and returns a list of their data fields. So, a lookup for type any gives an empty answer, as the answer records have specific types that are not any. An empty answer or a failed lookup returns an empty list.

Calls resolve/* with the same arguments and filters the result, so Opts is described for those functions.

resolve(Name, Class, Type)

-spec resolve(Name, Class, Type) -> {ok, dns_msg()} | Error
                 when
                     Name :: dns_name() | inet:ip_address(),
                     Class :: dns_class(),
                     Type :: dns_rr_type(),
                     Error :: {error, Reason} | {error, {Reason, dns_msg()}},
                     Reason :: inet:posix() | res_error().

Equivalent to resolve(Name, Class, Type, [], infinity).

resolve(Name, Class, Type, Opts)

-spec resolve(Name, Class, Type, Opts) -> {ok, dns_msg()} | Error
                 when
                     Name :: dns_name() | inet:ip_address(),
                     Class :: dns_class(),
                     Type :: dns_rr_type(),
                     Opts :: [Opt],
                     Opt :: res_option() | verbose | atom(),
                     Error :: {error, Reason} | {error, {Reason, dns_msg()}},
                     Reason :: inet:posix() | res_error().

Equivalent to resolve(Name, Class, Type, Opts, infinity).

resolve(Name, Class, Type, Opts, Timeout)

-spec resolve(Name, Class, Type, Opts, Timeout) -> {ok, dns_msg()} | Error
                 when
                     Name :: dns_name() | inet:ip_address(),
                     Class :: dns_class(),
                     Type :: dns_rr_type(),
                     Opts :: [Opt],
                     Opt :: res_option() | verbose | atom(),
                     Timeout :: timeout(),
                     Error :: {error, Reason} | {error, {Reason, dns_msg()}},
                     Reason :: inet:posix() | res_error().

Resolve a DNS query.

Resolves a DNS query for the specified Type, Class, and Name, into a DNS message possibly containing Resource Records. The returned dns_msg/0 can be examined using access functions in inet_db, as described in section in DNS Types.

If Name is an ip_address(), the domain name to query about is generated as the standard reverse ".IN-ADDR.ARPA." name for an IPv4 address, or the ".IP6.ARPA." name for an IPv6 address. In this case, you most probably want to use Class = in and Type = ptr, but it is not done automatically.

Opts overrides the corresponding resolver options. If option nameservers is specified, it is assumed that it is the complete list of name serves, so resolver option alt_nameserves is ignored. However, if option alt_nameserves is also specified to this function, it is used.

Option verbose (or rather {verbose,true}) causes diagnostics printout through io:format/2 of queries, replies, retransmissions, and so on, similar to utilities such as dig and nslookup.

Option nxdomain_reply (or rather {nxdomain_reply, true}) causes NXDOMAIN errors from DNS servers to be returned as {error, {nxdomain, dns_msg()}}. dns_msg/0 contains the additional sections that where included by the answering server. This is mainly useful to inspect the SOA record to get the TTL for negative caching.

If Opt is any atom, it is interpreted as {Opt,true} unless the atom string starts with "no", making the interpretation {Opt,false}. For example, usevc is an alias for {usevc, true} and nousevc is an alias for {usevc, false}.

Option inet6 has no effect on this function. You probably want to use Type = a | aaaa instead.

net

Network interface.

This module provides an API for the network interface.

Summary

Types

address_info()

ifaddrs()

Interface addresses and flags.

ifaddrs_filter()

Interface address filtering selector.

ifaddrs_filter_fun()

Interface address filtering selector function/0.

ifaddrs_filter_map()

Interface address filtering selector map.

ifaddrs_flag()

ifaddrs_flags()

name_info()

name_info_flag()

name_info_flag_ext()

name_info_flags()

network_interface_index()

network_interface_name()

Functions

getaddrinfo(Host)

Equivalent to getaddrinfo(Host, undefined).

getaddrinfo(Host, Service)

Network address and service translation.

gethostname()

Return the name of the current host.

getifaddrs()

Equivalent to getifaddrs(default).

getifaddrs/1

Get interface addresses.

getifaddrs(Filter, Namespace)

Get interface addresses in a namespace.

getnameinfo(SockAddr)

Equivalent to getnameinfo(SockAddr, undefined).

getnameinfo(SockAddr, Flags)

Address-to-name translation in a protocol-independant manner.

getservbyname(Name)

Equivalent to getservbyname(Name, any).

getservbyname(Name, Protocol)

Get service by name.

getservbyport(PortNumber)

Equivalent to getservbyport(PortNumber, any).

getservbyport(PortNumber, Protocol)

Get service by name.

if_index2name(Idx)

Mappings between network interface index and names.

if_name2index(Name)

Mappings between network interface names and indexes.

if_names()

Get network interface names and indexes.

Types

address_info()

(since OTP 22.0)

-type address_info() ::
          #{family := socket:domain(),
            socktype := any | socket:type() | integer(),
            protocol := socket:protocol(),
            address := socket:sockaddr()}.

ifaddrs()

(since OTP 22.0)

-type ifaddrs() ::
          #{name := string(),
            flags := ifaddrs_flags(),
            addr => socket:sockaddr(),
            netmask => socket:sockaddr(),
            broadaddr => socket:sockaddr(),
            dstaddr => socket:sockaddr()}.

Interface addresses and flags.

This type defines addresses and flags for an interface.

Note

Not all fields of this map has to be present. The flags field can be used to test for some of the fields. For example broadaddr will only be present if the broadcast flag is present in flags.

ifaddrs_filter()

(not exported) (since OTP 22.0)

-type ifaddrs_filter() ::
          all | default | inet | inet6 | packet | link | hwaddr |
          ifaddrs_filter_map() |
          ifaddrs_filter_fun().

Interface address filtering selector.

all - All interfaces

default - Interfaces with address family inet or inet6

inet | inet6 | packet | link - Interfaces with only the specified address family

hwaddr - Interfaces with address family packet or link

ifaddrs_filter_fun()

(not exported) (since OTP 22.0)

-type ifaddrs_filter_fun() :: fun((ifaddrs()) -> boolean()).

Interface address filtering selector function/0.

For each ifaddrs entry, return either true to keep the entry or false to discard the entry.

For example, to get an interface list which only contains non-loopback inet interfaces:

net:getifaddrs(
    fun (#{ addr  := #{family := inet},
            flags := Flags}) ->
          not lists:member(loopback, Flags);
        (_) ->
          false
    end).

ifaddrs_filter_map()

(not exported) (since OTP 22.0)

-type ifaddrs_filter_map() ::
          #{family :=
                all | default | local | inet | inet6 | packet | link |
                [local | inet | inet6 | packet | link],
            flags := any | [ifaddrs_flag()]}.

Interface address filtering selector map.

The family field can only have the (above) specified values (and not all the values of socket:domain()). It can also be a list of values, to cover the situation when any of the specified families are accepted. For example, family can be set to [inet,inet6] if either inet or inet6 is accepted.

The use of the flags field is that any flag provided must exist for the interface.

For example, if family is set to inet and flags to [broadcast, multicast] only interfaces with address family inet and the flags broadcast and multicast will be listed.

ifaddrs_flag()

(since OTP 22.0)

-type ifaddrs_flag() ::
          up | broadcast | debug | loopback | pointopoint | notrailers | running | noarp | promisc |
          master | slave | multicast | portsel | automedia | dynamic.

ifaddrs_flags()

(since OTP 22.0)

-type ifaddrs_flags() :: [ifaddrs_flag()].

name_info()

(since OTP 22.0)

-type name_info() :: #{host := string(), service := string()}.

name_info_flag()

(since OTP 22.0)

-type name_info_flag() :: namereqd | dgram | nofqdn | numerichost | numericserv.

name_info_flag_ext()

(since OTP 22.0)

-type name_info_flag_ext() :: idn.

name_info_flags()

(since OTP 22.0)

-type name_info_flags() :: [name_info_flag() | name_info_flag_ext()].

network_interface_index()

(since OTP 22.0)

-type network_interface_index() :: non_neg_integer().

network_interface_name()

(since OTP 22.0)

-type network_interface_name() :: string().

Functions

getaddrinfo(Host)

(since OTP 22.0)

-spec getaddrinfo(Host) -> {ok, Info} | {error, Reason}
                     when Host :: string(), Info :: [address_info()], Reason :: term().

Equivalent to getaddrinfo(Host, undefined).

getaddrinfo(Host, Service)

(since OTP 22.0)

-spec getaddrinfo(Host, undefined) -> {ok, Info} | {error, Reason}
                     when Host :: string(), Info :: [address_info()], Reason :: term();
                 (undefined, Service) -> {ok, Info} | {error, Reason}
                     when Service :: string(), Info :: [address_info()], Reason :: term();
                 (Host, Service) -> {ok, Info} | {error, Reason}
                     when
                         Host :: string(),
                         Service :: string(),
                         Info :: [address_info()],
                         Reason :: term().

Network address and service translation.

This function is the inverse of getnameinfo. It converts host and service to a corresponding socket address.

One of the Host and Service may be undefined but not both.

gethostname()

(since OTP 22.0)

-spec gethostname() -> {ok, HostName} | {error, Reason} when HostName :: string(), Reason :: term().

Return the name of the current host.

getifaddrs()

(since OTP 22.3)

-spec getifaddrs() -> {ok, IfAddrs} | {error, Reason} when IfAddrs :: [ifaddrs()], Reason :: term().

Equivalent to getifaddrs(default).

getifaddrs/1

(since OTP 22.3)

-spec getifaddrs(Filter) -> {ok, IfAddrs} | {error, Reason}
                    when Filter :: ifaddrs_filter(), IfAddrs :: [ifaddrs()], Reason :: term();
                (Namespace) -> {ok, IfAddrs} | {error, Reason}
                    when Namespace :: file:filename_all(), IfAddrs :: [ifaddrs()], Reason :: term().

Get interface addresses.

With argument 'Filter: get the machines interface addresses, filtered according to Filter.

With argument Namespace: equivalent to getifaddrs(default, Namespace).

getifaddrs(Filter, Namespace)

(since OTP 22.3)

-spec getifaddrs(Filter, Namespace) -> {ok, IfAddrs} | {error, Reason}
                    when
                        Filter :: ifaddrs_filter(),
                        Namespace :: file:filename_all(),
                        IfAddrs :: [ifaddrs()],
                        Reason :: term().

Get interface addresses in a namespace.

The same as getifaddrs(Filter) but in the specified Namespace.

getnameinfo(SockAddr)

(since OTP 22.0)

-spec getnameinfo(SockAddr) -> {ok, Info} | {error, Reason}
                     when SockAddr :: socket:sockaddr(), Info :: name_info(), Reason :: term().

Equivalent to getnameinfo(SockAddr, undefined).

getnameinfo(SockAddr, Flags)

(since OTP 22.0)

-spec getnameinfo(SockAddr, Flags) -> {ok, Info} | {error, Reason}
                     when
                         SockAddr :: socket:sockaddr(),
                         Flags :: name_info_flags() | undefined,
                         Info :: name_info(),
                         Reason :: term().

Address-to-name translation in a protocol-independant manner.

This function is the inverse of getaddrinfo. It converts a socket address to a corresponding host and service.

getservbyname(Name)

(since OTP 27.1)

-spec getservbyname(Name) -> {ok, PortNumber} | {error, Reason}
                       when
                           Name :: atom() | string(),
                           PortNumber :: socket:port_number(),
                           Reason :: term().

Equivalent to getservbyname(Name, any).

getservbyname(Name, Protocol)

(since OTP 27.1)

-spec getservbyname(Name, Protocol) -> {ok, PortNumber} | {error, Reason}
                       when
                           Name :: atom() | string(),
                           PortNumber :: socket:port_number(),
                           Protocol :: any | socket:protocol(),
                           Reason :: term().

Get service by name.

This function is used to get the port number of the specified protocol for the named service.

getservbyport(PortNumber)

(since OTP 27.1)

-spec getservbyport(PortNumber) -> {ok, Name} | {error, Reason}
                       when
                           PortNumber :: socket:port_number(),
                           Name :: atom() | string(),
                           Reason :: term().

Equivalent to getservbyport(PortNumber, any).

getservbyport(PortNumber, Protocol)

(since OTP 27.1)

-spec getservbyport(PortNumber, Protocol) -> {ok, Name} | {error, Reason}
                       when
                           PortNumber :: socket:port_number(),
                           Protocol :: any | socket:protocol(),
                           Name :: atom() | string(),
                           Reason :: term().

Get service by name.

This function is used to get the service name of the specified protocol for the given port number.

if_index2name(Idx)

(since OTP 22.0)

-spec if_index2name(Idx) -> {ok, Name} | {error, Reason}
                       when
                           Idx :: network_interface_index(),
                           Name :: network_interface_name(),
                           Reason :: term().

Mappings between network interface index and names.

if_name2index(Name)

(since OTP 22.0)

-spec if_name2index(Name) -> {ok, Idx} | {error, Reason}
                       when
                           Name :: network_interface_name(),
                           Idx :: network_interface_index(),
                           Reason :: term().

Mappings between network interface names and indexes.

if_names()

(since OTP 22.0)

-spec if_names() -> {ok, Names} | {error, Reason}
                  when
                      Names :: [{Idx, If}],
                      Idx :: network_interface_index(),
                      If :: network_interface_name(),
                      Reason :: term().

Get network interface names and indexes.

socket

Socket interface.

This module provides an API for network sockets. Functions are provided to create, delete and manipulate the sockets as well as sending and receiving data on them.

The intent is that it shall be as "close as possible" to the OS level socket interface. The only significant additions are that some of the functions, e.g. recv/3, have a time-out argument, and that recv/* for a stream socket iterates until the requested amount of data has been received.

Note

Asynchronous Calls

Some functions feature asynchronous calls. This is achieved by setting the Timeout argument to nowait or to a Handle :: reference/0. See the respective function's type specification.

This module has two different implementations of asynchronous calls. One on the Unix family of operating systems: select - based on the standard socket interface's select(3)/poll(3) calls, and one on Windows: completion - based on asynchronous I/O Completion Ports. The difference shows in the return values and message formats because they have slightly different semantics.

The completion and select Return Values

For instance, the call recv(Socket, 0, nowait), when there is no data available for reading, will, depending on the operating system, return one of:

{completion,CompletionInfo}

{select,SelectInfo}

Where CompletionInfo is {completion_info, _,CompletionHandle} and SelectInfo is {select_info, _,SelectHandle}. Both the CompletionHandle and the SelectHandle are of type reference/0.

When the operation can continue, a completion message containing the CompletionHandle or a select message containing the SelectHandle is sent to the calling process.

On select systems, recv/2,3,4 may also return:

{select, {SelectInfo, Data}

This may happen for sockets of type stream when Length > 1 since the OS may split a data stream at any point and deliver just the first part of the requested data. For the next recv/2,3,4 call; the Length to receive will probably have to be adjusted due to the already delivered data in this return value.

On select systems, when the {otp, select_read} option is true, the asynchronous recv/3,4, recvfrom/3,4, and recvmsg/3,4,5 functions may also return:

{select_read, {SelectInfo, Data}

This indicates that the receive operation was completed; all requested data has been delivered, and that the calling process will get a select message when there is data available for the next receive operation.

The completion and select Messages

The completion message has the format:

{'$socket',Socket, completion, {CompletionHandle, CompletionStatus}}

The select message has the format:

{'$socket',Socket, select,SelectHandle}

When a completion message is received (which contains the result of the operation), it means that the operation has been completed and CompletionStatus is the return value for the operation, which is what the function that initiated the operation could have returned, with the nowait argument, except for the completion and select return values.

When a select message is received, it only means that the operation may now continue, by retrying the operation (which may return a new {select, _} value). Some operations are retried by repeating the same function call, and some have a dedicated function variant to be used for the retry. See the respective function's documentation.

Operation Queuing on select Systems

On select systems, all other processes are locked out until the current process has completed the operation as in a continuation call has returned a value indicating success or failure (not a select or select_read return). Other processes are queued and get a select return which makes them wait for their turn.

Note that receiving data from parallel processes is only suitable for some protocols. For a stream socket it is in general a recipe for disaster.

Cancelling an operation

An operation that is in progress (not completed) may be canceled using cancel/2 both on completion and select systems.

Cancelling an operation ensures that there is no completion, select, nor abort message in the inbox after the cancel/2 call.

Using a Handle

If creating a reference/0 with make_ref() and using that as the Timeout | Handle argument, the same Handle will then be the SelectHandle in the returned select_info/0 and the received select message, or be the CompletionHandle in the returned completion_info/0 and the received completion message.

The compiler may then optimize a following receive statement to only scan the messages that arrive after the reference/0 is created. If the message queue is large this is a big optimization.

It is not possible to have more than one operation in progress with the same reference/0.

Repeating an Operation on a select Systems

Onselect systems, if a call would be repeated before the select message has been received it replaces the operation in progress:

    {select, {select_info, Handle}} = socket:accept(LSock, nowait),
    {ok, Socket} = socket:accept(LSock, 1000),
    :

Above, Handle is no longer valid once the second accept/2, call has been made (the first call is automatically canceled). After the second accept/2 call returns, the accept operation has completed.

Note that there is a race here; there is no way to know if the call is repeated before the select message is sent since it may have been sent just before the repeated call. So now there might be a select message containing Handle in the inbox.

The abort Message

Another message the user must be prepared for (when using nowait | Handle) is the abort message:

{'$socket',Socket, abort, Info}

This message indicates that the operation in progress has been aborted. For instance, if the socket has been closed by another process; Info will be {Handle, closed}.

Note

Support for IPv6 has been implemented but not fully tested.

This module was introduced in OTP 22.0, as experimental code.

In OTP 22.1, the nowait argument was added for many functions, and the cancel/2 and info/1 functions were also added.

In OTP 22.3, the number_of/0 function was added.

In OTP 23.0, the functions is_supported/1,2 and the open/1,2 functions with an FD argument were added.

In OTP 23.1, the use_registry/1 function was added.

In OTP 24.0, the select_handle/0 argument was added for many functions, the cancel/1, cancel_monitor/1, getopt/3 with tuple options, getopt_native/3, info/0, monitor/1, open/3 with an option list, many variants of the recv/*, recvfrom/*, recvmsg/*, send/*, sendmsg/*, the sendto/* functions, the sendfile/* functions, and the setopt/3, setopt_native/3 functions, were added.

In OTP 24.1, the i/* functions were added.

In OTP 24.2, the ioctl/* functions were added.

In OTP 26.0, the completion_handle/0 argument was added for many functions, and the cancel/2 function with completion_info/0 argument was added. That is: support for Windows asynchronous I/O Completion Ports was added. The Unix-ish flavored (select handle) API features could be considered no longer experimental.

In OTP 27.0, the Windows flavored (completion handle) API features could be considered no longer experimental.

In OTP 29.0, (experimental) complete support for SCTP was added (functionally feature compatible with inet). Not (yet) supported for FreeBSD.

Examples

client(SAddr, SPort) ->
   {ok, Sock} = socket:open(inet, stream, tcp),
   ok = socket:connect(Sock, #{family => inet,
                               addr   => SAddr,
                               port   => SPort}),
   Msg = <<"hello">>,
   ok = socket:send(Sock, Msg),
   ok = socket:shutdown(Sock, write),
   {ok, Msg} = socket:recv(Sock),
   ok = socket:close(Sock).

server(Addr, Port) ->
   {ok, LSock} = socket:open(inet, stream, tcp),
   ok = socket:bind(LSock, #{family => inet,
                             port   => Port,
                             addr   => Addr}),
   ok = socket:listen(LSock),
   {ok, Sock} = socket:accept(LSock),
   {ok, Msg} = socket:recv(Sock),
   ok = socket:send(Sock, Msg),
   ok = socket:close(Sock),
   ok = socket:close(LSock).

Summary

Types

cmsg()

Control messages (ancillary messages).

cmsg_recv()

Control messages (ancillary messages) returned by recvmsg/1,2,3,5.

cmsg_send()

Control messages (ancillary messages) accepted by sendmsg/2,3,4.

completion_handle()

Completion operation handle.

completion_info()

Completion operation info.

completion_tag()

Completion operation tag.

domain()

Protocol domain a.k.a address family.

ee_origin()

eei()

Extended Error Information.

extended_err()

hatype()

icmp_dest_unreach()

icmpv6_dest_unreach()

in6_addr()

in6_flow_info()

in6_scope_id()

in_addr()

info()

Platform dependent information items.

info_keys()

Information element designators for the i/1 and i/2 functions.

interface_type()

The interface type (of the datalink). We only translate a few values to atoms, the rest are left as (unsigned) integer values.

invalid()

ioctl_device_flag()

ioctl_device_map()

ip_mreq()

C: struct ip_mreq

ip_mreq_source()

C: struct ip_mreq_source

ip_msfilter()

C: struct ip_msfilter

ip_pktinfo()

C: struct ip_pktinfo

ip_pmtudisc()

C: IP_PMTUDISC_* values. => Lowercase atom/0 values corresponding to the C library constants IP_PMTUDISC_*. Some constant(s) may be unsupported by the platform.

ip_tos()

C: IPTOS_* values.

iptos_dscp()

These symbolic DSCP values are according to IANA's [Differentiated Services Field Codepoints registry] (https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml).

iptos_native()

iptos_tos()

Lowercase atom/0 values corresponding to the C library constants IPTOS_*. The atoms are named like The C library names, but to avoid platform depencendy, the set of names and values follow RFC 1349, not the C library header files.

iptos_tos_prec()

iptos_tos_value()

iptos_value()

ipv6_hops()

IPv6 hop limit value.

ipv6_mreq()

C: struct ipv6_mreq

ipv6_pktinfo()

C: struct in6_pktinfo

ipv6_pmtudisc()

C: IPV6_PMTUDISC_* values

level()

Protocol level.

linger()

C: struct linger

msg()

C: struct msghdr

msg_data_recv()

Message returned by recvmsg/1,2,3,5.

msg_flag()

Platform dependent message flags.

msg_notification_recv()

Notifications can be received on a SCTP socket (type = seqpacket and protocol = sctp).

msg_recv()

Message returned by recvmsg/1,2,3,5.

msg_send()

Message sent by sendmsg/2,3,4.

native_value()

otp_socket_option()

Protocol level otp socket option.

packet_type()

port_number()

posix()

Posix error codes.

protocol()

Protocol name.

sctp_adapt_event()

A peer has sent a Adaptation Layer Indication parameter.

sctp_assoc_change()

An SCTP association has either begun or ended.

sctp_assoc_change_state()

sctp_assoc_id()

C: sctp_assoc_t

sctp_assoc_reset_event()

C: struct sctp_assoc_reset_event

sctp_assoc_stats()

C: struct sctp_assoc_stats.

sctp_assocparams()

C: struct sctp_assocparams

sctp_authkey()

When a receiver is using authentication, info about new keys and errors are provided in this notification.

sctp_event_subscribe()

C: struct sctp_event_subscribe.

sctp_initmsg()

C: struct sctp_initmsg.

sctp_notification()

All possible notification types. All of them has at least two fields: 'type' and 'flags' ('flags' are not allways used).

sctp_notification_generic()

C: union sctp_notification

sctp_operation_error()

These error codes are (currently) defined in RFC 4960, and named as Operation Errors.

sctp_paddr_change()

A destination address on a multi-homed peer has encountered a change.

sctp_pap_flag()

C: enum sctp_spp_flags.

sctp_pap_flags()

There are three pairs of flags that cannot be both be set (maybe obviously) at the same time

sctp_pdapi_event()

A receiver is engaged in a partial delivery.

sctp_peer_addr_change_state()

sctp_peer_address_info()

C: struct sctp_paddrinfo.

sctp_peer_address_parameters()

C: struct sctp_paddrparams.

sctp_peer_address_state()

C: enum sctp_spinfo_state.

sctp_remote_error()

A remote peer may send an operational error message to its peer.

sctp_rtoinfo()

C: struct sctp_rtoinfo.

sctp_send_failed()

SCTP cannot deliver a message.

sctp_send_failed_event()

SCTP cannot deliver a message.

sctp_sender_dry()

The SCTP stack has no more user data to send or retransmit.

sctp_set_adaptation_layer_ind()

C: struct sctp_setadaptation.

sctp_set_peer_primary_address()

C: struct sctp_setpeerprim.

sctp_set_primary_address()

C: struct sctp_prim.

sctp_setadaption()

C: struct sctp_setadaption

sctp_shutdown_event()

A peer has sent a SHUTDOWN.

sctp_snd_info()

C: struct sctp_sndinfo

sctp_snd_rcv_info()

SCTP options for sendmsg() and SCTP header information about a received message through recvmsg().

sctp_snd_rcv_info_flags()

sctp_status()

C: struct sctp_status.

sctp_stream_change_event()

C: struct sctp_stream_change_event

sctp_stream_reset_event()

C: struct sctp_stream_reset_event

select_handle()

Select operation handle.

select_info()

Select operation info.

select_tag()

Select operation tag.

sockaddr()

sockaddr_dl()

C: struct sockaddr_dl

sockaddr_in6()

C: struct sockaddr_in6

sockaddr_in()

C: struct sockaddr_in

sockaddr_ll()

C: struct sockaddr_ll

sockaddr_native()

C: struct sockaddr

sockaddr_recv()

sockaddr_un()

C: struct sockaddr_un.

sockaddr_unspec()

C: struct sockaddr of AF_UNSPEC

socket()

A socket, according to this module.

socket_counters()

A map/0 of Name := Counter associations.

socket_handle()

Opaque socket handle unique for the socket.

socket_info()

socket_option()

Socket option.

timespec()

C: struct timespec

timeval()

C: struct timeval

type()

Protocol type.

uint8()

uint16()

uint32()

uint64()

Functions

accept(ListenSocket)

Equivalent to accept(ListenSocket, infinity).

accept/2

Accept a connection on a listening socket.

bind(Socket, Addr)

Bind a name to a socket.

bind(Socket, Addrs, Action)

Bind a list of socket addreses to a socket.

cancel/2

Cancel an asynchronous call in progress.

cancel_monitor(MRef)

Cancel a socket monitor.

close(Socket)

Close a socket.

connect(Socket)

Finalize a connect/3 operation.

connect(Socket, SockAddr)

Equivalent to connect(Socket, SockAddr, infinity) or connect(Socket, SockAddrs, undefined, infinity).

connect/3

Connect the socket to the given address(s).

getopt/2

Get the value of a socket option.

getopt/3

Get a socket option, with a specifier (extra input) OptValue.

getopt_native/3

Get a "native" socket option.

i()

Print information to the erlang shell in table format for all sockets.

i/1

Print information to the erlang shell in table format for all sockets.

i/2

Print information to the erlang shell in table format for a selection of sockets.

info()

Get miscellaneous information about this socket library.

info(Socket)

Get miscellaneous info about a socket.

ioctl/2

Set socket (device) parameters.

ioctl/3

Get or set socket (device) parameters.

ioctl(Socket, SetRequest, Name, Value)

Set socket (device) parameters.

is_supported(Key1)

Check if a socket feature is supported.

is_supported(Key1, Key2)

Check if a socket feature is supported.

listen(Socket)

Make a socket listen for connections.

listen/2

Make a socket listen for connections.

monitor(Socket)

Start a socket monitor.

number_of()

Return the number of active sockets.

open(FD)

Equivalent to open(FD, #{}).

open/2

Create a socket.

open/3

Create a socket.

open(Domain, Type, Protocol, Opts)

Create a socket.

peeloff(Socket, AssocId)

Branch off an association into a separate socket.

peeloff(Socket, AssocId, InheritOpts)

Branch off an association into a separate socket.

peername(Socket)

Return the remote address of a socket.

peernames(Socket, AssocId)

Return the remote (peer) address(s) of an association of a socket.

recv(Socket)

Equivalent to recv(Socket, 0, [], infinity).

recv/2

Receive data on a connected socket.

recv/3

Receive data on a connected socket.

recv/4

Receive data on a connected socket.

recvfrom(Socket)

Equivalent to recvfrom(Socket, 0, [], infinity).

recvfrom/2

Receive a message on a socket.

recvfrom/3

Receive a message on a socket.

recvfrom/4

Receive a message on a socket.

recvmmsg/6

Receive multiple messages on a socket.

recvmsg(Socket)

Equivalent to recvmsg(Socket, 0, 0, [], infinity).

recvmsg/2

Receive a message on a socket.

recvmsg/3

Receive a message on a socket.

recvmsg(Socket, BufSz, CtrlSz, TimeoutOrHandle)

Equivalent to recvmsg(Socket, BufSz, CtrlSz, [], TimeoutOrHandle).

recvmsg/5

Receive a message on a socket.

rest_iov(Written, IOV)

Calculate the rest I/O vector after a partially successful sendv (CompletionStatus was {ok, Written}).

send(Socket, Data)

Equivalent to send(Socket, Data, [], infinity).

send/3

Send data on a connected socket.

send/4

Send data on a connected socket.

sendfile(Socket, FileHandle_Cont)

Send a file on a socket.

sendfile(Socket, FileHandle_Cont, Timeout_Handle)

Send a file on a socket.

sendfile(Socket, FileHandle_Cont, Offset, Count)

Send a file on a socket.

sendfile/5

Send a file on a socket.

sendmmsg/4

Send multiple messages on a socket.

sendmsg(Socket, Msg)

Equivalent to sendmsg(Socket, Msg, [], infinity).

sendmsg/3

Send data and control messages on a socket.

sendmsg/4

Send data and control messages on a socket.

sendto/3

Send data on a socket.

sendto/4

Send data on a socket.

sendto/5

Send data on a socket.

sendv(Socket, IOV)

Equivalent to sendv(Socket, IOV, infinity).

sendv/3

Send erlang:iovec/0 data on a connected socket.

sendv/4

Send data on a connected socket, continuation.

setopt/3

Set a socket option.

setopt/4

Set a socket option (backwards compatibility function).

setopt_native(Socket, Option, Value)

Set a "native" socket option.

shutdown(Socket, How)

Shut down all or part of a full-duplex connection.

sockname(Socket)

Get the socket's address.

socknames(Socket, AssocId)

Get the socket's address.

supports()

Retrieve information about what socket features the module and the platform supports.

supports(Key1)

Retrieve information about what socket features the module and the platform supports.

supports(Key1, Key2)

Retrieve information about what socket features the module and the platform supports.

use_registry(D)

Set the global use_registry option default value.

which_sockets()

Return a list of all known sockets.

which_sockets(FilterRule)

Return a filtered list of known sockets.

Types

cmsg()

(since OTP 22.0)

-type cmsg() :: cmsg_recv() | cmsg_send().

Control messages (ancillary messages).

cmsg_recv()

(since OTP 22.0)

-type cmsg_recv() ::
          #{level := socket, type := timestamp, data := binary(), value => timeval()} |
          #{level := socket, type := timestampns, data := binary(), value => timespec()} |
          #{level := socket, type := rights, data := binary()} |
          #{level := socket, type := credentials, data := binary()} |
          #{level := ip, type := tos, data := binary(), value => ip_tos()} |
          #{level := ip, type := recvtos, data := binary(), value := ip_tos()} |
          #{level := ip, type := ttl, data := binary(), value => integer()} |
          #{level := ip, type := recvttl, data := binary(), value := integer()} |
          #{level := ip, type := pktinfo, data := binary(), value => ip_pktinfo()} |
          #{level := ip, type := origdstaddr, data := binary(), value => sockaddr_recv()} |
          #{level := ip, type := recverr, data := binary(), value => extended_err()} |
          #{level := ipv6, type := hoplimit, data := binary(), value => integer()} |
          #{level := ipv6, type := pktinfo, data := binary(), value => ipv6_pktinfo()} |
          #{level := ipv6, type := recverr, data := binary(), value => extended_err()} |
          #{level := ipv6, type := tclass, data := binary(), value => integer()}.

Control messages (ancillary messages) returned by recvmsg/1,2,3,5.

A control message has got a data field with a native (binary) value for the message data, and may also have a decoded value field if this socket library successfully decoded the data.

cmsg_send()

(since OTP 22.0)

-type cmsg_send() ::
          #{level := sctp, type := sndrcv, value := sctp_snd_rcv_info()} |
          #{level := socket, type := timestamp, data => native_value(), value => timeval()} |
          #{level := socket, type := rights, data := native_value()} |
          #{level := socket, type := credentials, data := native_value()} |
          #{level := ip, type := tos, data => native_value(), value => iptos_value()} |
          #{level := ip, type := ttl, data => native_value(), value => integer()} |
          #{level := ip, type := hoplimit, data => native_value(), value => integer()} |
          #{level := ipv6, type := tclass, data => native_value(), value => integer()}.

Control messages (ancillary messages) accepted by sendmsg/2,3,4.

A control message may for some message types have a value field with a symbolic value, or a data field with a native value, that has to be binary compatible what is defined in the platform's header files.

completion_handle()

(since OTP 26.0)

-type completion_handle() :: reference().

Completion operation handle.

A reference/0 that uniquely identifies the (completion) operation, contained in the returned completion_info/0.

completion_info()

(since OTP 26.0)

-type completion_info() ::
          {completion_info, CompletionTag :: completion_tag(), CompletionHandle :: completion_handle()}.

Completion operation info.

Returned by an operation that requires the caller to wait for a completion message containing the CompletionHandle and the result of the operation; the CompletionStatus.

completion_tag()

(since OTP 26.0)

-type completion_tag() ::
          accept | connect |
          recv | recvfrom | recvmsg | recvmmsg | send | sendv | sendto | sendmsg | sendmmsg | sendfile.

Completion operation tag.

A tag that describes the ongoing (completion) operation (= function name), contained in the returned completion_info/0.

domain()

(since OTP 22.0)

-type domain() :: inet | inet6 | local | unspec.

Protocol domain a.k.a address family.

A lowercase atom/0 representing a protocol domain on the platform named AF_* (or PF_*). For example inet corresponds to AF_INET.

is_supported(ipv6) tells if the IPv6 protocol, protocol domain inet6, is supported.

is_supported(local) tells if the protocol domain local is supported.

supports/0 reports both values, but also many more, with a single call.

ee_origin()

(since OTP 22.0)

-type ee_origin() :: none | local | icmp | icmp6.

eei()

(since OTP 22.0)

-type eei() ::
          #{info := econnreset | econnaborted | netname_deleted | too_many_cmds | atom(),
            raw_info := term()}.

Extended Error Information.

A term containing additional (error) information if the socket NIF has been configured to produce it.

extended_err()

(since OTP 22.0)

-type extended_err() ::
          #{error := posix(),
            origin := icmp,
            type := dest_unreach,
            code := icmp_dest_unreach() | 0..255,
            info := 0..4294967295,
            data := 0..4294967295,
            offender := sockaddr_recv()} |
          #{error := posix(),
            origin := icmp,
            type := time_exceeded | 0..255,
            code := 0..255,
            info := 0..4294967295,
            data := 0..4294967295,
            offender := sockaddr_recv()} |
          #{error := posix(),
            origin := icmp6,
            type := dest_unreach,
            code := icmpv6_dest_unreach() | 0..255,
            info := 0..4294967295,
            data := 0..4294967295,
            offender := sockaddr_recv()} |
          #{error := posix(),
            origin := icmp6,
            type := pkt_toobig | time_exceeded | 0..255,
            code := 0..255,
            info := 0..4294967295,
            data := 0..4294967295,
            offender := sockaddr_recv()} |
          #{error := posix(),
            origin := ee_origin() | 0..255,
            type := 0..255,
            code := 0..255,
            info := 0..4294967295,
            data := 0..4294967295,
            offender := sockaddr_recv()}.

hatype()

(not exported) (since OTP 22.0)

-type hatype() ::
          netrom | eether | ether | ax25 | pronet | chaos | ieee802 | arcnet | appletlk | dlci | atm |
          metricom | ieee1394 | eui64 | infiniband | tunnel | tunnel6 | loopback | localtlk | none |
          void |
          non_neg_integer().

icmp_dest_unreach()

(since OTP 22.0)

-type icmp_dest_unreach() ::
          net_unreach | host_unreach | port_unreach | frag_needed | net_unknown | host_unknown.

icmpv6_dest_unreach()

(since OTP 22.0)

-type icmpv6_dest_unreach() ::
          noroute | adm_prohibited | not_neighbour | addr_unreach | port_unreach | policy_fail |
          reject_route.

in6_addr()

(since OTP 22.0)

-type in6_addr() :: {0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535}.

in6_flow_info()

(not exported) (since OTP 22.0)

-type in6_flow_info() :: 0..1048575.

in6_scope_id()

(not exported) (since OTP 22.0)

-type in6_scope_id() :: 0..4294967295.

in_addr()

(since OTP 22.0)

-type in_addr() :: {0..255, 0..255, 0..255, 0..255}.

info()

(not exported) (since OTP 22.0)

-type info() ::
          #{counters := #{atom() := non_neg_integer()},
            iov_max := non_neg_integer(),
            use_registry := boolean(),
            io_backend := #{name := atom()},
            load_nif_result := undefined | ok | {error, term()}}.

Platform dependent information items.

The value of iov_max is the value of the IOV_MAX constant in the system headers, which is the largest allowed I/O vector. See also sendmsg/4 regarding the iov key of msg_send/0. The smallest allowed IOV_MAX value according to POSIX is 16, but check your platform documentation to be sure.

About the use_registry key, see use_registry/1 and the otp_socket_option/0 with the same name.

info_keys()

(since OTP 22.0)

-type info_keys() ::
          [domain | type | protocol | fd | owner | local_address | remote_address | recv | sent | state].

Information element designators for the i/1 and i/2 functions.

interface_type()

(since OTP 22.0)

-type interface_type() ::
          other | hdh1822 | x25ddh | x25 | ether | ppp | loop | ipv4 | ipv6 | '6to4' | gif | faith |
          stf | bridge | cellular |
          non_neg_integer().

The interface type (of the datalink). We only translate a few values to atoms, the rest are left as (unsigned) integer values.

invalid()

(since OTP 22.0)

-type invalid() :: {invalid, What :: term()}.

ioctl_device_flag()

(since OTP 22.0)

-type ioctl_device_flag() ::
          up | broadcast | debug | loopback | pointopoint | notrailers | knowsepoch | running | noarp |
          promisc | allmulti | master | oactive | slave | simplex | link0 | link1 | link2 | multicast |
          portsel | automedia | cantconfig | ppromisc | dynamic | monitor | staticarp | dying |
          renaming | nogroup | lower_up | dormant | echo.

ioctl_device_map()

(since OTP 22.0)

-type ioctl_device_map() ::
          #{mem_start := non_neg_integer(),
            mem_end := non_neg_integer(),
            base_addr := non_neg_integer(),
            irq := non_neg_integer(),
            dma := non_neg_integer(),
            port := non_neg_integer()}.

ip_mreq()

(since OTP 22.0)

-type ip_mreq() :: #{multiaddr := in_addr(), interface := in_addr()}.

C: struct ip_mreq

Corresponds to the C struct ip_mreq for managing multicast groups.

ip_mreq_source()

(since OTP 22.0)

-type ip_mreq_source() :: #{multiaddr := in_addr(), interface := in_addr(), sourceaddr := in_addr()}.

C: struct ip_mreq_source

Corresponds to the C struct ip_mreq_source for managing multicast groups.

ip_msfilter()

(since OTP 22.0)

-type ip_msfilter() ::
          #{multiaddr := in_addr(),
            interface := in_addr(),
            mode := include | exclude,
            slist := [in_addr()]}.

C: struct ip_msfilter

Corresponds to the C struct ip_msfilter for managing multicast source filtering (RFC 3376).

ip_pktinfo()

(since OTP 22.0)

-type ip_pktinfo() :: #{ifindex := non_neg_integer(), spec_dst := in_addr(), addr := in_addr()}.

C: struct ip_pktinfo

ip_pmtudisc()

(since OTP 22.0)

-type ip_pmtudisc() :: want | dont | do | probe.

C: IP_PMTUDISC_* values. => Lowercase atom/0 values corresponding to the C library constants IP_PMTUDISC_*. Some constant(s) may be unsupported by the platform.

ip_tos()

(since OTP 22.0)

-type ip_tos() ::
          #{native := iptos_native(), tos := iptos_tos(), dscp := iptos_dscp() | non_neg_integer()}.

C: IPTOS_* values.

Note that since there are two different representations of TOS; according to RFC 1349 ("classic TOS") and RFC 2474 (DSCP), we have three different value representations for tos: native (the raw unencoded value of the TOS octet), tos (classic), and dscp.

When sending or setting (the ip tos option), the user can choose between the three different (value) representations. When reading, the value is represented as a map with all three representations, since 'socket' does not know which one is expected. Its then up to the user pick the one they want.

An integer dscp value is a DSCP field value that is not known from the IANA registry (see iptos_dscp/0).

iptos_dscp()

(since OTP 22.0)

-type iptos_dscp() ::
          cs0 | le | cs1 | af11 | af12 | af13 | cs2 | af21 | af22 | af23 | cs3 | af31 | af32 | af33 |
          cs4 | af41 | af42 | af43 | cs5 | voice_admit | nqb | ef | cs6 | cs7.

These symbolic DSCP values are according to IANA's [Differentiated Services Field Codepoints registry] (https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml).

iptos_native()

(since OTP 22.0)

-type iptos_native() :: non_neg_integer().

iptos_tos()

(since OTP 22.0)

-type iptos_tos() ::
          #{precedence := iptos_tos_prec() | non_neg_integer(),
            tos := iptos_tos_value() | non_neg_integer()}.

Lowercase atom/0 values corresponding to the C library constants IPTOS_*. The atoms are named like The C library names, but to avoid platform depencendy, the set of names and values follow RFC 1349, not the C library header files.

An integer value is a field value that is not named in the RFC.

iptos_tos_prec()

(not exported) (since OTP 22.0)

-type iptos_tos_prec() ::
          netcontrol | internetcontrol | critical_ecp | flashoverride | flash | immediate | priority |
          routine.

iptos_tos_value()

(not exported) (since OTP 22.0)

-type iptos_tos_value() :: default | lowdelay | throughput | reliability | mincost.

iptos_value()

(since OTP 22.0)

-type iptos_value() :: iptos_tos() | iptos_dscp() | iptos_native().

ipv6_hops()

(since OTP 22.0)

-type ipv6_hops() :: default | 0..255.

IPv6 hop limit value.

The value default is only valid to set and is translated to the C value -1, meaning the route default.

ipv6_mreq()

(since OTP 22.0)

-type ipv6_mreq() :: #{multiaddr := in6_addr(), interface := non_neg_integer()}.

C: struct ipv6_mreq

Corresponds to the C struct ipv6_mreq for managing multicast groups. See also RFC 2553.

ipv6_pktinfo()

(since OTP 22.0)

-type ipv6_pktinfo() :: #{addr := in6_addr(), ifindex := integer()}.

C: struct in6_pktinfo

ipv6_pmtudisc()

(since OTP 22.0)

-type ipv6_pmtudisc() :: want | dont | do | probe.

C: IPV6_PMTUDISC_* values

Lowercase atom/0 values corresponding to the C library constants IPV6_PMTUDISC_*. Some constant(s) may be unsupported by the platform.

level()

(since OTP 22.0)

-type level() :: socket | protocol().

Protocol level.

A lowercase atom/0 OS protocol level, that is: socket or a protocol/0 name.

socket is the SOL_SOCKET protocol level in the OS header files, with options named SO_* .

linger()

(since OTP 22.0)

-type linger() :: #{onoff := boolean(), linger := non_neg_integer()}.

C: struct linger

Corresponds to the C struct linger for managing the socket option {socket, linger}.

msg()

(since OTP 22.0)

-type msg() :: msg_send() | msg_recv().

C: struct msghdr

msg_data_recv()

(not exported) (since OTP 22.0)

-type msg_data_recv() ::
          #{addr => sockaddr_recv(),
            iov := erlang:iovec(),
            ctrl := [cmsg_recv() | #{level := level() | integer(), type := integer(), data := binary()}],
            flags := [msg_flag() | integer()]}.

Message returned by recvmsg/1,2,3,5.

Corresponds to a C struct msghdr, see your platform documentation for recvmsg(2).

addr - Optional peer address, used on unconnected sockets. Corresponds to msg_name and msg_namelen fields of a struct msghdr. If NULL the map key is not present.

iov - Data as a list of binaries. The msg_iov and msg_iovlen fields of a struct msghdr.

ctrl - A possibly empty list of control messages (CMSG). Corresponds to the msg_control and msg_controllen fields of a struct msghdr.

flags - Message flags. Corresponds to the msg_flags field of a struct msghdr. Unknown flags, if any, are returned in one integer/0, last in the containing list.

msg_flag()

(since OTP 22.0)

-type msg_flag() ::
          cmsg_cloexec | confirm | ctrunc | dontroute | eor | errqueue | more | oob | peek | trunc.

Platform dependent message flags.

Translates to/from message flag constants on the platform. These flags are lowercase while the constants are uppercase with prefix MSG_; for example oob translates to MSG_OOB.

Some flags are only used for sending, some only for receiving, some in received control messages, and some for several of these. Not all flags are supported on all platforms. See the platform's documentation, supports(msg_flags), and is_supported(msg_flags, MsgFlag).

msg_notification_recv()

(not exported) (since OTP 29.0)

-type msg_notification_recv() ::
          #{addr => sockaddr_recv(),
            notification := sctp_notification(),
            ctrl := [#{level := level() | integer(), type := integer(), data := binary()}],
            flags := [notification | [msg_flag() | integer()]]}.

Notifications can be received on a SCTP socket (type = seqpacket and protocol = sctp).

msg_recv()

(since OTP 22.0)

-type msg_recv() :: msg_data_recv() | msg_notification_recv().

Message returned by recvmsg/1,2,3,5.

msg_send()

(since OTP 22.0)

-type msg_send() ::
          #{addr => sockaddr(),
            iov := erlang:iovec(),
            ctrl => [cmsg_send() | #{level := level() | integer(), type := integer(), data := binary()}]}.

Message sent by sendmsg/2,3,4.

Corresponds to a C struct msghdr, see your platform documentation for sendmsg(2).

addr - Optional peer address, used on unconnected sockets. Corresponds to msg_name and msg_namelen fields of a struct msghdr. If not used they are set to NULL, 0.

iov - Mandatory data as a list of binaries. The msg_iov and msg_iovlen fields of a struct msghdr.

ctrl - Optional list of control messages (CMSG). Corresponds to the msg_control and msg_controllen fields of a struct msghdr. If not used they are set to NULL, 0.

The msg_flags field of the struct msghdr is set to 0.

native_value()

(not exported) (since OTP 22.0)

-type native_value() :: integer() | boolean() | binary().

otp_socket_option()

(since OTP 22.0)

-type otp_socket_option() ::
          debug | iow | controlling_process | rcvbuf | rcvctrlbuf | sndctrlbuf | select_read | meta |
          use_registry | fd | domain.

Protocol level otp socket option.

Socket options for the otp pseudo protocol level, that is: {otp, Name} options.

This protocol level is the Erlang/OTP's socket implementation layer, hence above all OS protocol levels.

debug - boolean/0 - Activate debug logging.

iow - boolean/0 - Inform On Wrap of statistics counters.

controlling_process - pid/0 - The socket "owner". Only the current controlling process can set this option.

rcvbuf - BufSize :: (default | integer()>0) | {N :: integer()>0, BufSize :: (default | integer()>0)}- Receive buffer size.

The value default is only valid to set.

N specifies the number of read attempts to do in a tight loop before assuming no more data is pending.

This is the allocation size for the receive buffer used when calling the OS protocol stack's receive API, when no specific size (size 0) is requested. When the receive function returns the receive buffer is reallocated to the actually received size. If the data is copied or shrunk in place is up to the allocator, and can to some extent be configured in the Erlang VM.

The similar socket option; {socket,rcvbuf} is a related option for the OS' protocol stack that on Unix corresponds to SOL_SOCKET,SO_RCVBUF.

rcvctrlbuf - BufSize :: (default | integer()>0)- Allocation size for the ancillary data buffer used when calling the OS protocol stack's receive API.

The value default is only valid to set.

sndctrlbuf - BufSize :: (default | integer()>0)- Allocation size for the ancillary data buffer used when calling the OS protocol stack's sendmsg API.

The value default is only valid to set.

It is the user's responsibility to set a buffer size that has room for the encoded ancillary data in the message to send.

See sendmsg and also the ctrl field of the msg_send/0 type.

select_read - boolean/0 - On select implementations, see Asynchronous Calls, automatically activate select after a completed read.

Instead of {ok, Data} the receive operation returns {select_read, {SelectInfo, Data}}, and the calling process can wait for a select message containing SelectInfo when there is data available again.

Setting this option locks out other processes from receiving any data since the current process continues its operation, so it effectively disables receive operation queuing.

fd - integer/0 - Only valid to get. The OS protocol levels' socket descriptor. Functions open/1,2 can be used to create a socket according to this module from an existing OS socket descriptor.

use_registry - boolean/0 - Only valid to get. The value is set when the socket is created with open/2 or open/4.

Options not described here are intentionally undocumented and for Erlang/OTP internal use only.

packet_type()

(not exported) (since OTP 22.0)

-type packet_type() ::
          host | broadcast | multicast | otherhost | outgoing | loopback | user | kernel | fastroute |
          non_neg_integer().

port_number()

(since OTP 22.0)

-type port_number() :: 0..65535.

posix()

(not exported) (since OTP 22.0)

-type posix() :: inet:posix().

Posix error codes.

Local alias for inet:posix/0, a set of atom/0s.

protocol()

(since OTP 22.0)

-type protocol() :: atom().

Protocol name.

A lowercase atom/0 representing an OS protocol name. To be used for example in socket_option/0 in control messages.

They have the following names in the OS header files:

ip - IPPROTO_IP a.k.a SOL_IP with options named IP_*.

ipv6 - IPPROTO_IPV6 a.k.a SOL_IPV6 with options named IPV6_*.

tcp - IPPROTO_TCP with options named TCP_*.

mptcp - IPPROTO_MPTCP with a few options named MPTCP_*. Most TCP_* options apply which is the purpose of Multi-Path TCP.

udp - IPPROTO_UDP with options named UDP_*.

sctp - IPPROTO_SCTP with options named SCTP_*.

There are many other possible protocols, but the ones above are those for which this socket library implements socket options and/or control messages.

All protocols known to the OS are enumerated when the Erlang VM is started, through the C library call getprotoent(). See the OS man page for protocols(5). Those in the list above are valid if supported by the platform, even if they aren't enumerated.

The calls is_supported(ipv6) , is_supported(sctp) and is_supported(mptcp) can be used to find out if the protocols ipv6, sctp and mptcp are supported on the platform as in; appropriate header file and libraries exist.

The call is_supported(protocols, Protocol) can only be used to find out if the platform knows the protocol number for a named Protocol.

See open/2,3,4

sctp_adapt_event()

(not exported) (since OTP 22.0)

-type sctp_adapt_event() ::
          #{type := adaptation_event,
            flags := uint16(),
            adaption_ind := uint32(),
            assoc_id := sctp_assoc_id()}.

A peer has sent a Adaptation Layer Indication parameter.

C: struct sctp_adaptation_event

sctp_assoc_change()

(not exported) (since OTP 22.0)

-type sctp_assoc_change() ::
          #{type := assoc_change,
            flags := integer(),
            state := sctp_assoc_change_state(),
            error := sctp_operation_error(),
            outbound_streams := integer(),
            inbound_streams := integer(),
            assoc_id := sctp_assoc_id()}.

An SCTP association has either begun or ended.

C: struct sctp_assoc_change

sctp_assoc_change_state()

(not exported) (since OTP 22.0)

-type sctp_assoc_change_state() ::
          comm_up | comm_lost | restart | shutdown_comp | cant_str_assoc | integer().

sctp_assoc_id()

(since OTP 22.0)

-type sctp_assoc_id() :: integer().

C: sctp_assoc_t

sctp_assoc_reset_event()

(not exported) (since OTP 22.0)

-type sctp_assoc_reset_event() ::
          #{type := assoc_reset,
            flags := [denied | failed],
            assoc_id := sctp_assoc_id(),
            local_tsn := uint32(),
            remote_tsn := uint32()}.

C: struct sctp_assoc_reset_event

sctp_assoc_stats()

(since OTP 22.0)

-type sctp_assoc_stats() ::
          #{assoc_id := sctp_assoc_id(),
            max_rto_addr := sockaddr(),
            max_rto := uint64(),
            in_sacks := uint64(),
            out_sacks := uint64(),
            in_packets := uint64(),
            out_packets := uint64(),
            rtx_chunks := uint64(),
            out_of_seq_tsns := uint64(),
            in_dup_chunks := uint64(),
            gap_ack_recv := uint64(),
            in_unordered_chunks := uint64(),
            out_unordered_chunks := uint64(),
            in_ordered_chunks := uint64(),
            out_ordered_chunks := uint64(),
            in_ctrl_chunks := uint64(),
            out_ctrl_chunks := uint64()}.

C: struct sctp_assoc_stats.

sctp_assocparams()

(since OTP 22.0)

-type sctp_assocparams() ::
          #{assoc_id := sctp_assoc_id(),
            asocmaxrxt := uint16(),
            number_peer_destinations := uint16(),
            peer_rwnd := uint32(),
            local_rwnd := uint32(),
            cookie_life := uint32()}.

C: struct sctp_assocparams

sctp_authkey()

(not exported) (since OTP 22.0)

-type sctp_authkey() ::
          #{type := authkey,
            flags := uint16(),
            keynumber := uint16(),
            altkeynumber := uint16(),
            indication := uint32(),
            assoc_id := sctp_assoc_id()}.

When a receiver is using authentication, info about new keys and errors are provided in this notification.

C: struct sctp_authkey_event

sctp_event_subscribe()

(since OTP 22.0)

-type sctp_event_subscribe() ::
          #{data_io := boolean(),
            association := boolean(),
            address := boolean(),
            send_failure := boolean(),
            peer_error := boolean(),
            shutdown := boolean(),
            partial_delivery := boolean(),
            adaptation_layer => boolean(),
            sender_dry => boolean(),
            stream_reset => boolean(),
            assoc_reset => boolean(),
            stream_change => boolean()}.

C: struct sctp_event_subscribe.

Not all fields are implemented on all platforms; unimplemented fields are ignored, but implemented fields are mandatory. Note that the '_event' suffixes have been stripped from the C struct field names, for convenience.

sctp_initmsg()

(since OTP 22.0)

-type sctp_initmsg() ::
          #{num_ostreams := uint16(),
            max_instreams := uint16(),
            max_attempts := uint16(),
            max_init_timeo := uint16()}.

C: struct sctp_initmsg.

sctp_notification()

(not exported) (since OTP 22.0)

-type sctp_notification() ::
          sctp_assoc_change() |
          sctp_paddr_change() |
          sctp_send_failed() |
          sctp_remote_error() |
          sctp_shutdown_event() |
          sctp_adapt_event() |
          sctp_pdapi_event() |
          sctp_authkey() |
          sctp_sender_dry() |
          sctp_stream_reset_event() |
          sctp_assoc_reset_event() |
          sctp_stream_change_event() |
          sctp_send_failed_event() |
          sctp_notification_generic().

All possible notification types. All of them has at least two fields: 'type' and 'flags' ('flags' are not allways used).

C: union sctp_notification

sctp_notification_generic()

(not exported) (since OTP 22.0)

-type sctp_notification_generic() :: #{type := uint16(), flags := uint16()}.

C: union sctp_notification

This is intended as a fallback type for any notification we have not yet implemented.

sctp_operation_error()

(not exported) (since OTP 22.0)

-type sctp_operation_error() ::
          unknown | bad_sid | missing_parm | stale_cookie | no_resources | bad_addr | unrec_chunk |
          bad_mandparm | unrec_parm | no_usr_data | cookie_shut | restart_new_addrs | user_abort |
          delete_lastaddr | resource_shortage | delete_srcaddr | auth_err |
          pos_integer().

These error codes are (currently) defined in RFC 4960, and named as Operation Errors.

sctp_paddr_change()

(not exported) (since OTP 22.0)

-type sctp_paddr_change() ::
          #{type := peer_addr_change,
            flags := pos_integer(),
            addr := socket:sockaddr(),
            state := sctp_peer_addr_change_state(),
            error := pos_integer(),
            assoc_id := sctp_assoc_id()}.

A destination address on a multi-homed peer has encountered a change.

C: struct sctp_paddr_change

sctp_pap_flag()

(since OTP 22.0)

-type sctp_pap_flag() ::
          enable_heartbeats | disable_heartbeats | send_heartbeat_immediately | enable_pmtu_discovery |
          disable_pmtu_discovery | enable_sack | disable_sack | set_heartbeat_delay_to_zero |
          ipv6_flowlabel | dscp.

C: enum sctp_spp_flags.

sctp_pap_flags()

(since OTP 22.0)

-type sctp_pap_flags() :: integer() | [sctp_pap_flag()].

There are three pairs of flags that cannot be both be set (maybe obviously) at the same time:

enable_heartbeats and disable_heartbeats

enable_pmtu_discovery and disable_pmtu_discovery

enable_sack and disable_sack

sctp_pdapi_event()

(not exported) (since OTP 22.0)

-type sctp_pdapi_event() ::
          #{type := partial_delivery_event,
            flags := uint16(),
            indication := uint16(),
            assoc_id := sctp_assoc_id(),
            stream => uint32(),
            seq => uint32()}.

A receiver is engaged in a partial delivery.

Note that not all fields are available on all platforms. The stream and/or seq fields may not be present.

C: struct sctp_pdapi_event

sctp_peer_addr_change_state()

(not exported) (since OTP 22.0)

-type sctp_peer_addr_change_state() ::
          addr_available | addr_unreachable | addr_removed | addr_added | addr_made_prim |
          addr_confirmed | addr_potentially_failed |
          integer().

sctp_peer_address_info()

(since OTP 22.0)

-type sctp_peer_address_info() ::
          #{assoc_id := sctp_assoc_id(),
            address := sockaddr(),
            state := sctp_peer_address_state(),
            cwnd := uint32(),
            srtt := uint32(),
            rto := uint32(),
            mtu := uint32()}.

C: struct sctp_paddrinfo.

sctp_peer_address_parameters()

(since OTP 22.0)

-type sctp_peer_address_parameters() ::
          #{assoc_id := sctp_assoc_id(),
            addr := sockaddr(),
            heatbeat_interval := uint32(),
            path_max_rxt := uint16(),
            path_mtu => uint32(),
            sack_delay => uint32(),
            flags => sctp_pap_flags(),
            ipv6_flowlabel => uint32(),
            dscp => uint8()}.

C: struct sctp_paddrparams.

sctp_peer_address_state()

(since OTP 22.0)

-type sctp_peer_address_state() :: inactive | potentially_failed | active | unconfirmed | unknown.

C: enum sctp_spinfo_state.

sctp_remote_error()

(not exported) (since OTP 22.0)

-type sctp_remote_error() ::
          #{type := remote_error,
            flags := uint16(),
            error := sctp_operation_error(),
            assoc_id := sctp_assoc_id(),
            remote_causes := [integer()]}.

A remote peer may send an operational error message to its peer.

C: struct sctp_remote_error

sctp_rtoinfo()

(since OTP 22.0)

-type sctp_rtoinfo() ::
          #{assoc_id := sctp_assoc_id(), initial := uint32(), max := uint32(), min := uint32()}.

C: struct sctp_rtoinfo.

sctp_send_failed()

(not exported) (since OTP 22.0)

-type sctp_send_failed() ::
          #{type := send_failed,
            flags := uint16(),
            error := uint32(),
            info := sctp_snd_rcv_info(),
            assoc_id := sctp_assoc_id(),
            data := binary()}.

SCTP cannot deliver a message.

C: struct sctp_send_failed

Deprecated.

sctp_send_failed_event()

(not exported) (since OTP 22.0)

-type sctp_send_failed_event() ::
          #{type := send_failed_event,
            flags := [data_unsent | data_sent],
            error := uint32(),
            info := sctp_snd_info(),
            assoc_id := sctp_assoc_id(),
            data := binary()}.

SCTP cannot deliver a message.

C: struct sctp_send_failed_event

sctp_sender_dry()

(not exported) (since OTP 22.0)

-type sctp_sender_dry() :: #{type := sender_dry, flags := uint16(), assoc_id := sctp_assoc_id()}.

The SCTP stack has no more user data to send or retransmit.

C: struct sctp_sender_dry_event

sctp_set_adaptation_layer_ind()

(since OTP 22.0)

-type sctp_set_adaptation_layer_ind() :: #{ind := uint32()}.

C: struct sctp_setadaptation.

sctp_set_peer_primary_address()

(since OTP 22.0)

-type sctp_set_peer_primary_address() :: #{assoc_id := sctp_assoc_id(), addr := sockaddr()}.

C: struct sctp_setpeerprim.

sctp_set_primary_address()

(since OTP 22.0)

-type sctp_set_primary_address() :: #{assoc_id := sctp_assoc_id(), addr := sockaddr()}.

C: struct sctp_prim.

sctp_setadaption()

(since OTP 22.0)

-type sctp_setadaption() :: #{adaption_ind := uint32()}.

C: struct sctp_setadaption

sctp_shutdown_event()

(not exported) (since OTP 22.0)

-type sctp_shutdown_event() :: #{type := shutdown_event, flags := uint16(), assoc_id := sctp_assoc_id()}.

A peer has sent a SHUTDOWN.

C: struct sctp_shutdown_event

sctp_snd_info()

(not exported) (since OTP 22.0)

-type sctp_snd_info() ::
          #{sid := uint16(),
            flags := uint16(),
            ppid := uint16(),
            context := uint32(),
            assic_id := sctp_assoc_id()}.

C: struct sctp_sndinfo

sctp_snd_rcv_info()

(since OTP 22.0)

-type sctp_snd_rcv_info() ::
          #{stream := uint16(),
            ssn => uint16(),
            flags => sctp_snd_rcv_info_flags(),
            ppid => uint32(),
            context => uint32(),
            time_to_live => uint32(),
            tsn => uint32(),
            cum_tsn => uint32(),
            assoc_id := sctp_assoc_id()}.

SCTP options for sendmsg() and SCTP header information about a received message through recvmsg().

When sending, only the stream and assoc_id fields needs to be assigned. When receiving all values will be assigned.

C: struct sctp_sndrcvinfo

sctp_snd_rcv_info_flags()

(not exported) (since OTP 22.0)

-type sctp_snd_rcv_info_flags() :: [unordered | addr_over | abort | eof].

sctp_status()

(since OTP 22.0)

-type sctp_status() ::
          #{assoc_id := sctp_assoc_id(),
            state := sctp_peer_address_state(),
            rwnd := uint32(),
            unacked_data := uint16(),
            pending_data := uint16(),
            in_streams := uint16(),
            out_streams := uint16(),
            fragmentation_point := uint32(),
            primary := sctp_peer_address_info()}.

C: struct sctp_status.

sctp_stream_change_event()

(not exported) (since OTP 22.0)

-type sctp_stream_change_event() ::
          #{type := stream_change,
            flags := [denied | failed],
            assoc_id := sctp_assoc_id(),
            inbound_streams := uint16(),
            outbound_streams := uint16()}.

C: struct sctp_stream_change_event

sctp_stream_reset_event()

(not exported) (since OTP 22.0)

-type sctp_stream_reset_event() ::
          #{type := stream_reset,
            flags := [incoming_ssn | outgoing_ssn | denied | failed],
            assoc_id := sctp_assoc_id(),
            stream_list := [uint16()]}.

C: struct sctp_stream_reset_event

select_handle()

(since OTP 22.0)

-type select_handle() :: reference().

Select operation handle.

A reference/0 that uniquely identifies the (select) operation, contained in the returned select_info/0.

select_info()

(since OTP 22.0)

-type select_info() :: {select_info, SelectTag :: select_tag(), SelectHandle :: select_handle()}.

Select operation info.

Returned by an operation that requires the caller to wait for a select message containing the SelectHandle.

On select systems, if the option {otp, select_read} is set, {select_read, {select_info(), _}} is returned instead of {ok, _} to indicate that a new asynchronous receive operation has been initiated and the caller should wait for a select message containing the SelectHandle.

select_tag()

(since OTP 22.0)

-type select_tag() ::
          accept | connect |
          recv | recvfrom | recvmsg | recvmmsg | send | sendv | sendto | sendmsg | sendmmsg | sendfile |
          {recv | recvfrom | recvmsg | recvmmsg | send | sendv | sendto | sendmsg | sendmmsg | sendfile,
           ContData :: term()}.

Select operation tag.

A tag that describes the (select) operation (= function name), contained in the returned select_info/0.

sockaddr()

(since OTP 22.0)

-type sockaddr() ::
          sockaddr_in() |
          sockaddr_in6() |
          sockaddr_un() |
          sockaddr_ll() |
          sockaddr_dl() |
          sockaddr_unspec() |
          sockaddr_native().

sockaddr_dl()

(since OTP 22.0)

-type sockaddr_dl() ::
          #{family := link,
            index := non_neg_integer(),
            type := interface_type(),
            nlen := non_neg_integer(),
            alen := non_neg_integer(),
            slen := non_neg_integer(),
            data := binary()}.

C: struct sockaddr_dl

Link level address (PF_LINK) on BSD:s.

sockaddr_in6()

(since OTP 22.0)

-type sockaddr_in6() ::
          #{family := inet6,
            port := port_number(),
            addr := any | loopback | in6_addr(),
            flowinfo := in6_flow_info(),
            scope_id := in6_scope_id()}.

C: struct sockaddr_in6

Domain inet6 (IPv6) address.

sockaddr_in()

(since OTP 22.0)

-type sockaddr_in() ::
          #{family := inet, port := port_number(), addr := any | broadcast | loopback | in_addr()}.

C: struct sockaddr_in

Domain inet (IPv4) address.

sockaddr_ll()

(since OTP 22.0)

-type sockaddr_ll() ::
          #{family := packet,
            protocol := non_neg_integer(),
            ifindex := integer(),
            pkttype := packet_type(),
            hatype := hatype(),
            addr := binary()}.

C: struct sockaddr_ll

Domain packet, type raw (link level) address.

sockaddr_native()

(since OTP 22.0)

-type sockaddr_native() :: #{family := integer(), addr := binary()}.

C: struct sockaddr

In C, a struct sockaddr with the integer value of sa_family in the map/0 key family, and the content of sa_data in the map/0 key addr.

sockaddr_recv()

(since OTP 22.0)

-type sockaddr_recv() :: sockaddr() | binary().

sockaddr_un()

(since OTP 22.0)

-type sockaddr_un() :: #{family := local, path := binary() | string()}.

C: struct sockaddr_un.

A Unix Domain socket address, a.k.a local address (AF_LOCAL).

The path element will always be a binary when returned from this module. When supplied to an API function in this module it may be a string/0, which will be encoded into a binary according to the native file name encoding on the platform.

A terminating zero character will be appended before the address path is given to the OS, and the terminating zero will be stripped before giving the address path to the caller.

Linux's non-portable abstract socket address extension is handled by not doing any terminating zero processing in either direction, if the first byte of the address is zero.

sockaddr_unspec()

(since OTP 22.0)

-type sockaddr_unspec() :: #{family := unspec, addr := binary()}.

C: struct sockaddr of AF_UNSPEC

In C, a struct sockaddr with sa_family = AF_UNSPEC and the content of sa_data in the map/0 key addr.

socket()

(since OTP 22.0)

-type socket() :: {'$socket', socket_handle()}.

A socket, according to this module.

Created and returned by open/1,2,3,4 and accept/1,2.

socket_counters()

(since OTP 22.0)

-type socket_counters() ::
          #{read_byte := non_neg_integer(),
            read_fails := non_neg_integer(),
            read_pkg := non_neg_integer(),
            read_pkg_max := non_neg_integer(),
            read_tries := non_neg_integer(),
            read_waits := non_neg_integer(),
            write_byte := non_neg_integer(),
            write_fails := non_neg_integer(),
            write_pkg := non_neg_integer(),
            write_pkg_max := non_neg_integer(),
            write_tries := non_neg_integer(),
            write_waits := non_neg_integer(),
            sendfile => non_neg_integer(),
            sendfile_byte => non_neg_integer(),
            sendfile_fails => non_neg_integer(),
            sendfile_max => non_neg_integer(),
            sendfile_pkg => non_neg_integer(),
            sendfile_pkg_max => non_neg_integer(),
            sendfile_tries => non_neg_integer(),
            sendfile_waits => non_neg_integer(),
            acc_success := non_neg_integer(),
            acc_fails := non_neg_integer(),
            acc_tries := non_neg_integer(),
            acc_waits := non_neg_integer()}.

A map/0 of Name := Counter associations.

socket_handle()

(since OTP 22.0)

-opaque socket_handle()

Opaque socket handle unique for the socket.

socket_info()

(since OTP 22.0)

-type socket_info() ::
          #{domain := domain() | integer(),
            type := type() | integer(),
            protocol := protocol() | integer(),
            owner := pid(),
            ctype := normal | fromfd | {fromfd, integer()},
            counters := socket_counters(),
            num_readers := non_neg_integer(),
            num_writers := non_neg_integer(),
            num_acceptors := non_neg_integer(),
            writable := boolean(),
            readable := boolean(),
            rstates := [atom()],
            wstates := [atom()]}.

socket_option()

(since OTP 22.0)

-type socket_option() ::
          {Level :: socket,
           Opt ::
               acceptconn | acceptfilter | bindtodevice | broadcast | bsp_state | busy_poll | debug |
               domain | dontroute | error | exclusiveaddruse | keepalive | linger | mark | maxdg |
               max_msg_size | oobinline | passcred | peek_off | peercred | priority | protocol |
               rcvbuf | rcvbufforce | rcvlowat | rcvtimeo | reuseaddr | reuseport | rxq_ovfl | setfib |
               sndbuf | sndbufforce | sndlowat | sndtimeo | timestamp | timestampns | type} |
          {Level :: ip,
           Opt ::
               add_membership | add_source_membership | block_source | dontfrag | drop_membership |
               drop_source_membership | freebind | hdrincl | minttl | msfilter | mtu | mtu_discover |
               multicast_all | multicast_if | multicast_loop | multicast_ttl | nodefrag | options |
               pktinfo | recvdstaddr | recverr | recvif | recvopts | recvorigdstaddr | recvtos |
               recvttl | retopts | router_alert | sndsrcaddr | tos | transparent | ttl | unblock_source} |
          {Level :: ipv6,
           Opt ::
               addrform | add_membership | authhdr | auth_level | checksum | drop_membership | dstopts |
               esp_trans_level | esp_network_level | faith | flowinfo | hopopts | ipcomp_level |
               join_group | leave_group | mtu | mtu_discover | multicast_hops | multicast_if |
               multicast_loop | portrange | pktoptions | recverr | recvhoplimit | hoplimit |
               recvpktinfo | pktinfo | recvtclass | router_alert | rthdr | tclass | unicast_hops |
               use_min_mtu | v6only} |
          {Level :: tcp,
           Opt ::
               congestion | cork | info | keepcnt | keepidle | keepintvl | maxseg | md5sig | nodelay |
               noopt | nopush | syncnt | user_timeout} |
          {Level :: udp, Opt :: cork} |
          {Level :: sctp,
           Opt ::
               adaption_layer | associnfo | auth_active_key | auth_asconf | auth_chunk | auth_key |
               auth_delete_key | autoclose | context | default_send_param | delayed_ack_time |
               disable_fragments | hmac_ident | events | explicit_eor | fragment_interleave |
               get_peer_addr_info | initmsg | i_want_mapped_v4_addr | local_auth_chunks | maxseg |
               maxburst | nodelay | partial_delivery_point | peer_addr_params | peer_auth_chunks |
               primary_addr | reset_streams | rtoinfo | set_peer_primary_addr | status |
               use_ext_recvinfo}.

Socket option.

Socket options of the form {Level, Opt} where the OS protocol Level = level/0 and Opt is a socket option on that protocol level.

The OS name for an options is, except where otherwise noted, the Opt atom, in capitals, with prefix according to level/0.

Note

The IPv6 option pktoptions is a special (barf) case. It is intended for backward compatibility usage only.

Do not use this option.

Note

See the OS documentation for every socket option.

An option below that has the value type boolean/0 will translate the value false to a C int with value 0, and the value true to !!0 (not (not false)).

An option with value type integer/0 will be translated to a C int that may have a restricted range, for example byte: 0..255. See the OS documentation.

The calls supports(options), supports(options, Level) and is_supported(options, {Level, Opt}) can be used to find out which socket options that are supported by the platform.

Options for protocol level socket:

{socket, acceptconn} - Value = boolean()

{socket, bindtodevice} - Value = string()

{socket, broadcast} - Value = boolean()

{socket, debug} - Value = integer()

{socket, domain} - Value = domain/0

Only valid to get.

The socket's protocol domain. Does not work on for instance FreeBSD.

{socket, dontroute} - Value = boolean()

{socket, keepalive} - Value = boolean()

{socket, linger} - Value = abort | linger/0

The value abort is shorthand for #{onoff => true, linger => 0}, and only valid to set.

{socket, oobinline} - Value = boolean()

{socket, passcred} - Value = boolean()

{socket, peek_off} - Value = integer()

Currently disabled due to a possible infinite loop when calling recv/1-4 with peek in Flags.

{socket, priority} - Value = integer()

{socket, protocol} - Value = protocol/0

Only valid to get.

The socket's protocol. Does not work on for instance Darwin.

{socket, rcvbuf} - Value = integer()

{socket, rcvlowat} - Value = integer()

{socket, rcvtimeo} - Value = timeval/0

This option is unsupported per default; OTP has to be explicitly built with the --enable-esock-rcvsndtimeo configure option for this to be available.

Since our implementation uses non-blocking sockets, it is unknown if and how this option works, or even if it may cause malfunction. Therefore, we do not recommend setting this option.

Instead, use the Timeout argument to, for instance, the recv/3 function.

{socket, reuseaddr} - Value = boolean()

{socket, reuseport} - Value = boolean()

{socket, sndbuf} - Value = integer()

{socket, sndlowat} - Value = integer()

{socket, sndtimeo} - Value = timeval/0

This option is unsupported per default; OTP has to be explicitly built with the --enable-esock-rcvsndtimeo configure option for this to be available.

Since our implementation uses non-blocking sockets, it is unknown if and how this option works, or even if it may cause malfunction. Therefore, we do not recommend setting this option.

Instead, use the Timeout argument to, for instance, the send/3 function.

{socket, timestamp} - Value = boolean()

Enable or disable the SO_TIMESTAMP socket option. When enabled, the socket will receive timestamps in control messages for received packets.

{socket, timestampns} - Value = boolean()

Enable or disable the SO_TIMESTAMPNS socket option. When enabled, the socket will receive nanosecond-precision timestamps in control messages for received packets.

{socket, type} - Value = type/0

Only valid to get.

The socket's type.

Options for protocol level ip:

{ip, add_membership} - Value = ip_mreq/0

Only valid to set.

{ip, add_source_membership} - Value = ip_mreq_source/0

Only valid to set.

{ip, block_source} - Value = ip_mreq_source/0

Only valid to set.

{ip, drop_membership} - Value = ip_mreq/0

Only valid to set.

{ip, drop_source_membership} - Value = ip_mreq_source/0

Only valid to set.

{ip, freebind} - Value = boolean()

{ip, hdrincl} - Value = boolean()

{ip, minttl} - Value = integer()

{ip, msfilter} - Value = null | ip_msfilter/0

Only valid to set.

The value null passes a NULL pointer and size 0 to the C library call.

{ip, mtu} - Value = integer()

Only valid to get.

{ip, mtu_discover} - Value = ip_pmtudisc() | integer()

An integer/0 value according to the platform's header files.

{ip, multicast_all} - Value = boolean()

{ip, multicast_if} - Value = any | in_addr/0

{ip, multicast_loop} - Value = boolean()

{ip, multicast_ttl} - Value = integer()

{ip, nodefrag} - Value = boolean()

{ip, pktinfo} - Value = boolean()

{ip, recvdstaddr} - Value = boolean()

{ip, recverr} - Value = boolean()

Enable extended reliable error message passing.

Warning! When this option is enabled, error messages may arrive on the socket's error queue, which should be read using the message flag errqueue, and using recvmsg/1,2,3,4,5 to get all error information in the message's ctrl field as a control message #{level := ip, type := recverr}.

A working strategy should be to first poll the error queue using recvmsg/2,3,4 with Timeout =:= 0 and Flags containing errqueue (ignore the return value {error, timeout}) before reading the actual data to ensure that the error queue gets cleared. And read the data using one of the nowait | select_handle() recv functions: recv/3,4, recvfrom/3,4 or recvmsg/3,4,5. Otherwise you might accidentally cause a busy loop in and out of 'select' for the socket.

{ip, recvif} - Value = boolean()

{ip, recvopts} - Value = boolean()

{ip, recvorigdstaddr} - Value = boolean()

{ip, recvtos} - Value = boolean()

{ip, recvttl} - Value = boolean()

{ip, retopts} - Value = boolean()

{ip, router_alert} - Value = integer()

{ip, sendsrcaddr} - Value = boolean()

{ip, tos} - Value = iptos_value() | ip_tos()

When sending/setting the value is according to iptos_value/0. When reading/getting the value is according to ip_tos/0.

{ip, transparent} - Value = boolean()

{ip, ttl} - Value = integer()

{ip, unblock_source} - Value = ip_mreq_source/0

Only valid to set.

Options for protocol level ipv6:

{ipv6, addrform} - Value = domain/0

As far as we know the only valid value is inet and it is only allowed for an IPv6 socket that is connected and bound to an IPv4-mapped IPv6 address.

{ipv6, add_membership} - Value = ipv6_mreq/0

Only valid to set.

{ipv6, authhdr} - Value = boolean()

{ipv6, drop_membership} - Value = ipv6_mreq/0

Only valid to set.

{ipv6, dstopts} - Value = boolean()

{ipv6, flowinfo} - Value = boolean()

{ipv6, hoplimit} - Value = boolean()

{ipv6, hopopts} - Value = boolean()

{ipv6, mtu} - Value = integer()

{ipv6, mtu_discover} - Value = ipv6_pmtudisc() | integer()

An integer/0 value is according to the platform's header files.

{ipv6, multicast_hops} - Value = ipv6_hops/0

{ipv6, multicast_if} - Value = integer()

{ipv6, multicast_loop} - Value = boolean()

{ipv6, recverr} - Value = boolean()

Warning! See the socket option {ip, recverr} regarding the socket's error queue. The same warning applies for this option.

{ipv6, recvhoplimit} - Value = boolean()

{ipv6, recvpktinfo} - Value = boolean()

{ipv6, recvtclass} - Value = boolean()

{ipv6, router_alert} - Value = integer()

{ipv6, rthdr} - Value = boolean()

{ipv6, tclass} - Value = boolean()

{ipv6, unicast_hops} - Value = ipv6_hops/0

{ipv6, v6only} - Value = boolean()

Options for protocol level sctp. See also RFC 6458.

{sctp, associnfo} - Value = sctp_assocparams/0

{sctp, autoclose} - Value = integer()

{sctp, disable_fragments} - Value = boolean()

{sctp, events} - Value = sctp_event_subscribe/0

Only valid to set.

{sctp, initmsg} - Value = sctp_initmsg/0

{sctp, maxseg} - Value = integer()

{sctp, nodelay} - Value = boolean()

{sctp, rtoinfo} - Value = sctp_rtoinfo/0

{sctp, get_peer_addr_info} - Value = sctp_peer_address_info/0

Only valid for get. Also, requires an OptValue (containing sctp_assoc_id/0 and sockaddr/0) specifying the peer. See getopt/3 for more info.

{sctp, status} - Value = sctp_status/0

Only valid for get. Also, requires an OptValue (containing sctp_assoc_id/0) specifying the association. See getopt/3 for more info.

Options for protocol level tcp:

{tcp, congestion} - Value = string()

{tcp, cork} - Value = boolean()

{tcp, keepcnt} - Value = integer()

{tcp, keepidle} - Value = integer()

{tcp, keepintvl} - Value = integer()

{tcp, maxseg} - Value = integer()

{tcp, nodelay} - Value = boolean()

{tcp, nopush} - Value = boolean()

{tcp, user_timeout} - Value = non_neg_integer()

Options for protocol level udp:

{udp, cork} - Value = boolean()

timespec()

(since OTP 22.0)

-type timespec() :: #{sec := integer(), nsec := integer()}.

C: struct timespec

Corresponds to the C struct timespec. The field sec holds seconds, and nsec nanoseconds.

timeval()

(since OTP 22.0)

-type timeval() :: #{sec := integer(), usec := integer()}.

C: struct timeval

Corresponds to the C struct timeval. The field sec holds seconds, and usec microseconds.

type()

(since OTP 22.0)

-type type() :: stream | dgram | raw | rdm | seqpacket.

Protocol type.

A lowercase atom/0 representing a protocol type on the platform named SOCK_*. For example stream corresponds to SOCK_STREAM.

uint8()

(not exported) (since OTP 22.0)

-type uint8() :: 0..255.

uint16()

(not exported) (since OTP 22.0)

-type uint16() :: 0..65535.

uint32()

(not exported) (since OTP 22.0)

-type uint32() :: 0..4294967295.

uint64()

(not exported) (since OTP 22.0)

-type uint64() :: 0..18446744073709551615.

Functions

accept(ListenSocket)

(since OTP 22.0)

-spec accept(ListenSocket) -> Result
                when
                    Result :: {ok, Socket} | {error, Reason},
                    ListenSocket :: socket(),
                    Socket :: socket(),
                    Reason :: dynamic().

Equivalent to accept(ListenSocket, infinity).

accept/2

(since OTP 22.0)

-spec accept(ListenSocket, Timeout :: infinity) -> {ok, Socket} | {error, Reason}
                when
                    ListenSocket :: socket(),
                    Socket :: socket(),
                    Reason ::
                        posix() |
                        closed |
                        invalid() |
                        {create_accept_socket, posix()} |
                        {add_socket, posix()} |
                        {update_accept_context, posix()};
            (ListenSocket, Timeout :: non_neg_integer()) -> {ok, Socket} | {error, Reason}
                when
                    ListenSocket :: socket(),
                    Socket :: socket(),
                    Reason ::
                        posix() |
                        closed |
                        invalid() |
                        timeout |
                        {create_accept_socket, posix()} |
                        {add_socket, posix()} |
                        {update_accept_context, posix()};
            (ListenSocket, nowait | (Handle :: select_handle() | completion_handle())) ->
                {ok, Socket} | {select, SelectInfo} | {completion, CompletionInfo} | {error, Reason}
                when
                    ListenSocket :: socket(),
                    Socket :: socket(),
                    SelectInfo :: select_info(),
                    CompletionInfo :: completion_info(),
                    Reason ::
                        posix() |
                        closed |
                        invalid() |
                        {create_accept_socket, posix()} |
                        {add_accept_socket, posix()} |
                        {update_accept_context, posix()}.

Accept a connection on a listening socket.

ListenSocket has to be of a connection oriented type (types stream or seqpacket, see open/1), and set to listen (see listen/1).

If the Timeout argument is infinity; accepts the first pending incoming connection for the listen socket or wait for one to arrive, and return the new connection socket.

If the Timeout argument is a time-out value (non_neg_integer/0); returns {error, timeout} if no connection has arrived after Timeout milliseconds.

If the Handle argument nowait (since OTP 22.1), starts an asynchronous call if the operation couldn't be completed immediately.

If the Handle argument is a select_handle/0, (since OTP 24.0), or on Windows, the equivalent completion_handle/0 (since OTP 26.0), starts an asynchronous call like for nowait.

The possible values for CompletionStatus in the completion message are:

{ok, NewSocket} - Success; A connection has been accepted.

{error, Reason} - An error occured and no connection was established.

See the note Asynchronous Calls at the start of this module reference manual page.

bind(Socket, Addr)

(since OTP 22.0)

-spec bind(Socket, Addr) -> ok | {error, Reason}
              when
                  Socket :: socket(),
                  Addr :: sockaddr() | any | broadcast | loopback,
                  Reason :: posix() | closed | invalid().

Bind a name to a socket.

When a socket is created (with open), it has no address assigned to it. bind assigns the address specified by the Addr argument.

The rules used for name binding vary between domains.

If you bind a socket to an address in for example the inet or inet6 address families, with an ephemeral port number (0), and want to know which port that was chosen, you can find out using something like: {ok, #{port := Port}} =socket:sockname(Socket)

bind(Socket, Addrs, Action)

(since OTP 29.0)

-spec bind(Socket, Addrs, Action) -> ok | {error, Reason}
              when
                  Socket :: socket(),
                  Addrs :: [sockaddr_in()] | [sockaddr_in() | sockaddr_in6()],
                  Action :: add | remove,
                  Reason :: posix() | closed.

Bind a list of socket addreses to a socket.

When a socket is created (with open), it has no address assigned to it. This bind assigns the address specified by the Addr argument.

Calling this function is only valid if the socket is type = seqpacket and protocol = sctp.

If the domain is inet, then all addresses must be IPv4. If the domain is inet6, the addresses can be either IPv4 or IPv6.

cancel/2

(since OTP 22.1)

-spec cancel(Socket, SelectInfo | CompletionInfo) -> ok | {error, Reason}
                when
                    Socket :: socket(),
                    SelectInfo :: select_info(),
                    CompletionInfo :: completion_info(),
                    Reason :: closed | invalid().

Cancel an asynchronous call in progress.

Call this function to cancel an asynchronous call in progress, that is; it returned a value containing a completion_info/0 or select_info/0.

See the note Asynchronous Calls at the start of this module reference manual page.

If another process tries an operation of the same basic type (accept/1 | send/2 | recv/2) it will be enqueued and notified through a select or completion message when the current operation and all enqueued before it has been completed. If the current operation is canceled by this function it is treated as a completed operation; the process first in queue is notified.

If SelectInfo | CompletionInfo does not match an operation in progress for the calling process, this function returns {error, {invalid, SelectInfo | CompletionInfo}}.

cancel_monitor(MRef)

(since OTP 24.0)

-spec cancel_monitor(MRef :: reference()) -> boolean().

Cancel a socket monitor.

If MRef is a reference that the calling process obtained by calling monitor/1, this monitor is removed. If there is no such monitor for the calling process (or MRef doesn't correspond to a monitor), nothing happens.

The returned value is one of the following:

true - The monitor was found and removed. In this case, no 'DOWN' message corresponding to this monitor has been delivered and will not be delivered.

false - The monitor was not found so it couldn't be removed. This might be because the monitor has already triggered and there is a 'DOWN' message from this monitor in the caller message queue.

close(Socket)

(since OTP 22.0)

-spec close(Socket) -> ok | {error, Reason}
               when Socket :: socket(), Reason :: posix() | closed | timeout.

Close a socket.

Note

Note that for Protocol = tcp (see open/3), although TCP guarantees that when the other side sees the stream close all data that we sent before closing has been delivered, there is no way for us to know that the other side got all data and the stream close. All kinds of network and OS issues may obliterate that.

To get such a guarantee we need to implement an in-band acknowledge protocol on the connection, or we can use the shutdown function to signal that no more data will be sent and then wait for the other end to close the socket. Then we will see our read side getting a socket close. In this way we implement a small acknowledge protocol using shutdown/2. The other side cannot know that we ever saw the socket close, but in a client/server scenario that is often not relevant.

connect(Socket)

(since OTP 24.0)

-spec connect(Socket :: socket()) -> ok | {error, Reason} when Reason :: posix() | closed | invalid().

Finalize a connect/3 operation.

See the note Asynchronous Calls at the start of this module reference manual page.

On select systems this function finalizes a connection setup on a socket, after receiving a select message {'$socket', Socket, select,SelectHandle}, and returns whether the connection setup was successful or not.

Instead of calling this function, for backwards compatibility, it is allowed to call connect/2,3 again, but that incurs more overhead since the connect address and time-out argument are processed in vain.

The call that completes the connect operation, the second call, cannot return a select return value.

connect(Socket, SockAddr)

(since OTP 22.0)

-spec connect(Socket :: socket(), SockAddr :: sockaddr() | [SockAddr :: term()]) ->
                 ok | {error, Reason :: dynamic()}.

Equivalent to connect(Socket, SockAddr, infinity) or connect(Socket, SockAddrs, undefined, infinity).

connect/3

(since OTP 22.0)

-spec connect(Socket, SockAddrs, TimeoutOrHandle) -> {ok, AssocId} | {error, Reason}
                 when
                     Socket :: socket(),
                     SockAddrs :: [sockaddr_in()] | [sockaddr_in6()],
                     TimeoutOrHandle :: infinity | Timeout | nowait | Handle,
                     Timeout :: non_neg_integer(),
                     Handle :: select_handle(),
                     AssocId :: sctp_assoc_id(),
                     Reason :: posix() | closed | invalid() | already;
             (Socket, SockAddr, Timeout :: infinity) -> ok | {error, Reason}
                 when
                     Socket :: socket(),
                     SockAddr :: sockaddr(),
                     Reason ::
                         posix() |
                         closed |
                         invalid() |
                         already | not_bound |
                         {add_socket, posix()} |
                         {update_connect_context, posix()};
             (Socket, SockAddr, Timeout :: non_neg_integer()) -> ok | {error, Reason}
                 when
                     Socket :: socket(),
                     SockAddr :: sockaddr(),
                     Reason ::
                         posix() |
                         closed |
                         invalid() |
                         already | not_bound | timeout |
                         {add_socket, posix()} |
                         {update_connect_context, posix()};
             (Socket, SockAddr, nowait | Handle) ->
                 ok | {select, SelectInfo} | {completion, CompletionInfo} | {error, Reason}
                 when
                     Socket :: socket(),
                     SockAddr :: sockaddr(),
                     Handle :: select_handle() | completion_handle(),
                     SelectInfo :: select_info(),
                     CompletionInfo :: completion_info(),
                     Reason ::
                         posix() |
                         closed |
                         invalid() |
                         already | not_bound |
                         {add_socket, posix()} |
                         {update_connect_context, posix()}.

Connect the socket to the given address(s).

This function connects the socket to the address(s) specified by the SockAddr|SockAddrs argument.

If a connection attempt is already in progress (by another process), {error, already} is returned.

Note

On Windows the socket has to be bound.

If the time-out argument (argument 3) is infinity it is up to the OS implementation to decide when the connection attempt failed and then what to return; probably {error, etimedout}. The OS time-out may be very long.

If the time-out argument (argument 3) is a time-out value (non_neg_integer/0); return {error, timeout} if the connection hasn't been established within Timeout milliseconds.

Note

Note that when this call has returned {error, timeout} the connection state of the socket is uncertain since the platform's network stack may complete the connection at any time, up to some platform specific time-out.

Repeating a connection attempt towards the same address would be ok, but towards a different address could end up with a connection to either address.

The safe play is to close the socket and start over.

Also note that this applies to cancelling a nowait connect call described below.

If the time-out argument (argument 2) is nowait (since OTP 22.1), start an asynchronous call if the operation couldn't be completed immediately.

If the time-out argument (argument 2) is a Handle :: select_handle/0, (since OTP 24.0), or on Windows, the equivalent Handle :: completion_handle/0 (since OTP 26.0), start an asynchronous call like for nowait.

See the note Asynchronous Calls at the start of this module reference manual page.

After receiving a select message; call connect/1 to complete the operation.

If cancelling the operation with cancel/2 see the note above about connection time-out.

The possible values for CompletionStatus in the completion message are:

ok - Complete success; A connection has been established.

{error, Reason} - An error occured and no connection was established.

Note

Note that calling with a list of socket addresses only works for SCTP sockets (type = seqpacket). And that the family of all addresses in the list is either IPv4 (inet) or IPv6 (inet6).

getopt/2

(since OTP 24.0)

-spec getopt(socket(), SocketOption :: {Level :: otp, Opt :: otp_socket_option()}) ->
                {ok, Value :: term()} | {error, invalid() | closed};
            (socket(), SocketOption :: socket_option()) ->
                {ok, Value :: term()} | {error, posix() | invalid() | closed}.

Get the value of a socket option.

Gets the value of an OS protocol level socket option, or from the otp pseudo protocol level, which is this module's implementation level above the OS protocol levels.

See the type otp_socket_option() for a description of the otp protocol level.

See the type socket_option/0 for which OS protocol level options that this implementation knows about, how they are related to OS option names, and if there are known peculiarities with any of them.

What options that are valid depends on the OS, and on the kind of socket (domain/0,type/0 and protocol/0). See the type t:socket_option() and the socket options chapter in the User's Guide for more info.

Note

Not all options are valid, nor possible to get, on all platforms. That is, even if this socket implementation support an option; it doesn't mean that the underlying OS does.

getopt/3

(since OTP 22.0)

-spec getopt(Socket :: socket(),
             SocketOption :: {sctp, get_peer_addr_info},
             OptValue :: #{assoc_id := sctp_assoc_id(), addr := sockaddr()}) ->
                {ok, Value :: sctp_peer_address_info()} | {error, posix() | invalid() | closed};
            (Socket :: socket(),
             SocketOption :: {sctp, status},
             OptValue :: #{assoc_id := sctp_assoc_id()}) ->
                {ok, Value :: sctp_status()} | {error, posix() | invalid() | closed};
            (Socket :: socket(), Level :: level(), Opt :: term()) ->
                {ok, Value :: term()} | {error, posix() | invalid() | closed}.

Get a socket option, with a specifier (extra input) OptValue.

This function is used when the option takes an input 'value' argument. We only support this for a limited set of options: {sctp, get_peer_addr_info} and {sctp, status}.

Some uses of this function is for backwards compatibility reasons.

For instance, getopt(Socket, Level, Opt) is equivalent to getopt(Socket, {Level, Opt}), or as a special case if Opt = {NativeOpt ::integer/0, ValueSpec} equivalent to getopt_native(Socket, {Level, NativeOpt}, ValueSpec).

Use getopt/2 or getopt_native/3 instead to handle the option level and name as a single term, and to make the difference between known options and native options clear.

getopt_native/3

(since OTP 24.0)

-spec getopt_native(socket(),
                    SocketOption ::
                        socket_option() |
                        {Level :: level() | (NativeLevel :: integer()), NativeOpt :: integer()},
                    ValueType :: integer) ->
                       {ok, Value :: integer()} | {error, posix() | invalid() | closed};
                   (socket(),
                    SocketOption ::
                        socket_option() |
                        {Level :: level() | (NativeLevel :: integer()), NativeOpt :: integer()},
                    ValueType :: boolean) ->
                       {ok, Value :: boolean()} | {error, posix() | invalid() | closed};
                   (socket(),
                    SocketOption ::
                        socket_option() |
                        {Level :: level() | (NativeLevel :: integer()), NativeOpt :: integer()},
                    ValueSize :: non_neg_integer()) ->
                       {ok, Value :: binary()} | {error, posix() | invalid() | closed};
                   (socket(),
                    SocketOption ::
                        socket_option() |
                        {Level :: level() | (NativeLevel :: integer()), NativeOpt :: integer()},
                    ValueSpec :: binary()) ->
                       {ok, Value :: binary()} | {error, posix() | invalid() | closed}.

Get a "native" socket option.

Gets a socket option that may be unknown to our implementation, or that has a type not compatible with our implementation, that is; in "native mode".

The socket option may be specified with an ordinary socket_option() tuple, with a known Level = level() and an integer NativeOpt, or with both an integer NativeLevel and NativeOpt.

How to decode the option value has to be specified either with ValueType, by specifying the ValueSize for a binary/0 that will contain the fetched option value, or by specifying a binary/0 ValueSpec that will be copied to a buffer for the getsockopt() call to write the value in which will be returned as a new binary/0.

If ValueType is integer a C type (int) will be fetched, if it is boolean a C type (int) will be fetched and converted into a boolean/0 according to the C implementation's notion about true and false.

If an option is valid depends both on the platform and on what kind of socket it is (domain/0, type/0 and protocol/0).

The integer values for NativeLevel and NativeOpt as well as the Value encoding has to be deduced from the header files for the running system.

i()

(since OTP 24.1)

-spec i() -> ok.

Print information to the erlang shell in table format for all sockets.

The information printed for each socket is specified by the default set of info_keys/0 (all keys).

The sockets that are printed are all sockets created by this socket module's implementation.

i/1

(since OTP 24.1)

-spec i(InfoKeys :: info_keys()) -> ok;
       (Domain :: inet | inet6 | local) -> ok;
       (Proto :: sctp | tcp | udp) -> ok;
       (Type :: dgram | seqpacket | stream) -> ok.

Print information to the erlang shell in table format for all sockets.

If the argument is a list of info_keys/0, print the specified information for all sockets. See i/0.

Otherwise the same as i/2 with the same first argument and the default information (see i/0).

i/2

(since OTP 24.1)

-spec i(Domain :: inet | inet6 | local, InfoKeys) -> ok when InfoKeys :: info_keys();
       (Proto :: sctp | tcp | udp, InfoKeys) -> ok when InfoKeys :: info_keys();
       (Type :: dgram | seqpacket | stream, InfoKeys) -> ok when InfoKeys :: info_keys().

Print information to the erlang shell in table format for a selection of sockets.

The argument InfoKeys specifies which information is printed for each socket.

If the first argument is Domain print information for all sockets of that specific domain/0.

If the first argument is Proto print information for all sockets of that specific protocol/0.

If the first argument is Type print information for all sockets of that specific type/0.

info()

(since OTP 24.0)

-spec info() -> info().

Get miscellaneous information about this socket library.

The function returns a map with each information item as a key-value pair.

Note

In order to ensure data integrity, mutexes are taken when needed. So, don't call this function often.

info(Socket)

(since OTP 22.1)

-spec info(Socket) -> socket_info() when Socket :: socket().

Get miscellaneous info about a socket.

The function returns a map with each information item as a key-value pair reflecting the "current" state of the socket (such as counter values).

Note

In order to ensure data integrity, mutexes are taken when needed. So, don't call this function often.

ioctl/2

(since OTP 24.2)

-spec ioctl(Socket, GetRequest :: gifconf) ->
               {ok, IFConf :: [#{name := string, addr := sockaddr()}]} | {error, Reason}
               when Socket :: socket(), Reason :: posix() | closed;
           (Socket, GetRequest :: nread | nwrite | nspace) ->
               {ok, NumBytes :: non_neg_integer()} | {error, Reason}
               when Socket :: socket(), Reason :: posix() | closed;
           (Socket, GetRequest :: atmark) -> {ok, Available :: boolean()} | {error, Reason}
               when Socket :: socket(), Reason :: posix() | closed;
           (Socket, GetRequest :: tcp_info) -> {ok, Info :: map()} | {error, Reason}
               when Socket :: socket(), Reason :: posix() | closed.

Set socket (device) parameters.

This function retrieves a specific parameter, according to the GetRequest argument.

gifconf - Get a list of interface (transport layer) addresses.

Result; a list of map/0s, one for each interface, with its name and address.

nread - Get the number of bytes immediately available for reading (since OTP 26.1).

Result; the number of bytes, integer/0.

nwrite - Get the number of bytes in the send queue (since OTP 26.1).

Result; the number of bytes, integer/0.

nspace - Get the free space in the send queue (since OTP 26.1).

Result; the number of bytes, integer/0.

atmark - Test if there is OOB (out-of-bound) data waiting to be read (since OTP 26.1).

Result; a boolean/0.

tcp_info - Get miscellaneous TCP related information for a connected socket (since OTP 26.1).

Result; a map/0 with information items as key-value pairs.

Note

Not all requests are supported by all platforms. To see if a ioctl request is supported on the current platform:

      Request = nread,
      true = socket:is_supported(ioctl_requests, Request),
      :

ioctl/3

(since OTP 24.2)

-spec ioctl(Socket, GetRequest, NameOrIndex) -> {ok, Result} | {error, Reason}
               when
                   Socket :: socket(),
                   GetRequest ::
                       gifname | gifindex | gifaddr | gifdstaddr | gifbrdaddr | gifnetmask | gifhwaddr |
                       genaddr | gifmtu | giftxqlen | gifflags | tcp_info,
                   NameOrIndex :: string() | integer(),
                   Result :: dynamic(),
                   Reason :: posix() | closed;
           (Socket, SetRequest, Value) -> ok | {error, Reason}
               when
                   Socket :: socket(),
                   SetRequest :: rcvall,
                   Value :: off | on | iplevel,
                   Reason :: posix() | closed;
           (Socket, SetRequest, Value) -> ok | {error, Reason}
               when
                   Socket :: socket(),
                   SetRequest :: rcvall_igmpmcast | rcvall_mcast,
                   Value :: off | on,
                   Reason :: posix() | closed.

Get or set socket (device) parameters.

This function retrieves a specific parameter, according to one of the following GetRequest arguments. The third argument is the (lookup) "key", identifying the interface, for most requests the name of the interface as a string/0. Also, see the note above.

gifname - Get the name of the interface with the specified index (integer/0).

Result; the name of the interface, string/0.

gifindex - Get the index of the interface with the specified name.

Result; the interface index, integer/0.

gifaddr - Get the address of the interface with the specified name.

Result; the address of the interface, sockaddr/0.

gifdstaddr - Get the destination address of the point-to-point interface with the specified name.

Result; the destination address of the interface, sockaddr/0.

gifbrdaddr - Get the broadcast address of the interface with the specified name.

Result; broadcast address of the interface, sockaddr/0.

gifnetmask - Get the network mask of the interface with the specified name.

Result; the network mask of the interface, sockaddr/0.

gifhwaddr | genaddr - Get the hardware address for the interface with the specified name.

Result; the hardware address of the interface, sockaddr/0 | binary/0. The family field contains the 'ARPHRD' device type (or an integer).

gifmtu - Get the MTU (Maximum Transfer Unit) for the interface with the specified name.

Result; MTU of the interface, integer/0.

giftxqlen - Get the transmit queue length of the interface with the specified name.

Result; transmit queue length of the interface, integer/0.

gifflags - Get the active flag word of the interface with the specified name.

Result; the active flag word of the interface, is a list of ioctl_device_flag/0 | t:integer( ).

With the following SetRequest argument this function sets the Value for the request parameter (since OTP 26.1).

rcvall - Enables (or disables) a socket to receive all IPv4 or IPv6 packages passing through a network interface.

The Socket has to be one of:

An IPv4 socket - Created with the address domain inet, socket type raw and protocol ip.

An IPv6 socket - Created with the address domain inet6, socket type raw and protocol ipv6.

The socket must also be bound to an (explicit) local IPv4 or IPv6 interface (any isn't allowed).

Setting this IOCTL requires elevated privileges.

With the following SetRequest arguments this function sets the Value for the request parameter (since OTP 26.1).

rcvall_igmpmcall - Enables (or disables) a socket to receive IGMP multicast IP traffic, without receiving any other IP traffic.

The socket has to be created with the address domain inet, socket type raw and protocol igmp.

The socket must also be bound to an (explicit) local interface (any isn't allowed).

The receive buffer must be sufficiently large.

Setting this IOCTL requires elevated privileges.

rcvall_mcall - Enables (or disables) a socket to receive all multicast IP traffic (as in; all IP packets destined for IP addresses in the range 224.0.0.0 to 239.255.255.255).

The socket has to be created with the address domain inet, socket type raw and protocol udp.

The socket must also be bound to an (explicit) local interface (any isn't allowed), And bound to port 0.

The receive buffer must be sufficiently large.

Setting this IOCTL requires elevated privileges.

ioctl(Socket, SetRequest, Name, Value)

(since OTP 24.2)

-spec ioctl(Socket, SetRequest, Name, Value) -> ok | {error, Reason}
               when
                   Socket :: socket(),
                   SetRequest ::
                       sifflags | sifaddr | sifdstaddr | sifbrdaddr | sifnetmask | sifhwaddr | sifmtu |
                       siftxqlen,
                   Name :: string(),
                   Value :: dynamic(),
                   Reason :: posix() | closed.

Set socket (device) parameters.

This function sets a specific parameter, according to the SetRequest argument. The Name argument is the name of the interface, and the Value argument is the value to set.

These operations require elevated privileges.

sifflags - Set the the active flag word, #{Flag => boolean()}, of the interface with the specified name.

Each flag to be changed should be added to the value map/0, with the value true if the Flag should be set and false if the flag should be cleared.

sifaddr - Set the address, sockaddr/0, of the interface with the specified name.

sifdstaddr - Set the destination address, sockaddr/0, of a point-to-point interface with the specified name.

sifbrdaddr - Set the broadcast address, sockaddr/0, of the interface with the specified name.

sifnetmask - Set the network mask, sockaddr/0, of the interface with the specified name.

sifhwaddr - Set the hardware address, sockaddr/0, of the interface with the specified name.

sifmtu - Set the MTU (Maximum Transfer Unit), integer/0, for the interface with the specified name.

siftxqlen - Set the transmit queue length, integer/0, of the interface with the specified name.

is_supported(Key1)

(since OTP 23.0)

-spec is_supported(Key1 :: term()) -> boolean().

Check if a socket feature is supported.

Returns true if supports/0 has a {Key1, true} tuple or a {Key1, list()} tuple in its returned list, otherwise false (also for unknown keys).

Example:

true = socket:is_supported(local),

is_supported(Key1, Key2)

(since OTP 23.0)

-spec is_supported(Key1 :: term(), Key2 :: term()) -> boolean().

Check if a socket feature is supported.

Returns true if supports(Key1) has a {Key2, true} tuple in its returned list, otherwise false (also for unknown keys).

Example:

true = socket:is_supported(msg_flags, errqueue),

listen(Socket)

(since OTP 22.0)

-spec listen(Socket :: socket()) -> ok | {error, Reason :: posix() | closed}.

Make a socket listen for connections.

Equivalent to listen(Socket, Backlog) with a default value for Backlog (currently 5).

listen/2

(since OTP 22.0)

-spec listen(Socket, IsServer) -> ok | {error, Reason}
                when Socket :: socket(), IsServer :: boolean(), Reason :: posix() | closed;
            (Socket, Backlog) -> ok | {error, Reason}
                when Socket :: socket(), Backlog :: pos_integer(), Reason :: posix() | closed.

Make a socket listen for connections.

The IsServer clauses are intended to be used for SCTP sockets. The Backlog argument states the length of the queue for incoming not yet accepted connections. Exactly how that number is interpreted is up to the OS' protocol stack, but the resulting effective queue length will most probably be perceived as at least that long.

Note

On Windows the socket has to be bound.

monitor(Socket)

(since OTP 24.0)

-spec monitor(Socket :: socket()) -> MonitorRef :: reference().

Start a socket monitor.

If the Socket doesn't exist or when later the monitor is triggered, a 'DOWN' message is sent to the process that called monitor/1 with the following pattern:

	    {'DOWN', MonitorRef, socket, Socket, Info}

Info is the termination reason of the socket or nosock if Socket did not exist when the monitor was started.

Making several calls to socket:monitor/1 for the same Socket is not an error; each call creates an independent monitor instance.

number_of()

(since OTP 22.3)

-spec number_of() -> non_neg_integer().

Return the number of active sockets.

open(FD)

(since OTP 23.0)

-spec open(FD :: integer()) -> dynamic().

Equivalent to open(FD, #{}).

open/2

(since OTP 22.0)

-spec open(FD, Opts) -> {ok, Socket} | {error, Reason}
              when
                  FD :: integer(),
                  Opts ::
                      #{domain => domain() | integer(),
                        type => type() | integer(),
                        protocol => default | protocol() | integer(),
                        dup => boolean(),
                        debug => boolean(),
                        use_registry => boolean()},
                  Socket :: socket(),
                  Reason :: posix() | domain | type | protocol;
          (Domain, Type) -> {ok, Socket} | {error, Reason}
              when
                  Domain :: domain(),
                  Type :: type() | integer(),
                  Socket :: socket(),
                  Reason :: posix() | protocol.

Create a socket.

With arguments Domain and Type

Equivalent to open(Domain, Type, default, #{}).

With arguments FD and Opts (since OTP 23.0)

Creates an endpoint for communication (socket) based on an already existing file descriptor that must be a socket. This function attempts to retrieve the file descriptor's domain, type and protocol from the system. This is however not possible on all platforms; in that case they should be specified in Opts.

The Opts argument can provide extra information:

domain - The file descriptor's communication domain. See also

open/2,3,4.

type - The file descriptor's socket type.

See also open/2,3,4.

protocol - The file descriptor's protocol. The atom default is equivalent to the integer protocol number 0 which means the default protocol for a given domain and type.

If the protocol can not be retrieved from the platform for the socket, and protocol is not specified, the default protocol is used, which may or may not be correct.

See also open/2,3,4.

dup - If false don't duplicate the provided file descriptor.

Defaults to true; do duplicate the file descriptor.

debug - If true enable socket debug logging.

Defaults to false; don't enable socket debug logging.

use_registry - Enable or disable use of the socket registry for this socket. This overrides the global setting.

Defaults to the global setting, see use_registry/1.

Note

This function should be used with care!

On some platforms it is necessary to provide domain, type and protocol since they cannot be retrieved from the platform.

On some platforms it is not easy to get hold of a file descriptor to use in this function.

open/3

(since OTP 22.0)

-spec open(Domain, Type, Opts | Protocol) -> {ok, Socket} | {error, Reason}
              when
                  Domain :: domain() | integer(),
                  Type :: type() | integer(),
                  Opts :: map(),
                  Protocol :: default | protocol() | integer(),
                  Socket :: socket(),
                  Reason :: posix() | protocol.

Create a socket.

With arguments Domain, Type and Protocol

Equivalent to open(Domain, Type, Protocol, #{}).

With arguments Domain, Type and Opts (since OTP 24.0)

Equivalent to open(Domain, Type, default, #{}).

open(Domain, Type, Protocol, Opts)

(since OTP 22.0)

-spec open(Domain, Type, Protocol, Opts) -> {ok, Socket} | {error, Reason}
              when
                  Domain :: domain() | integer(),
                  Type :: type() | integer(),
                  Protocol :: default | protocol() | integer(),
                  Opts :: #{netns => string(), debug => boolean(), use_registry => boolean()},
                  Socket :: socket(),
                  Reason :: posix() | protocol.

Create a socket.

Creates an endpoint for communication (socket).

Domain and Type may be integer/0s, as defined in the platform's header files. The same goes for Protocol as defined in the platform's services(5) database. See also the OS man page for the library call socket(2).

Note

For some combinations of Domain and Type the platform has got a default protocol that can be selected with Protocol = default, and the platform may allow or require selecting the default protocol, or a specific protocol.

Examples:

socket:open(inet, stream, tcp) - It is common that for protocol domain and type inet,stream it is allowed to select the tcp protocol although that mostly is the default.

socket:open(local, dgram) - It is common that for the protocol domain local it is mandatory to not select a protocol, that is; to select the default protocol.

The Opts argument is intended for "other" options. The supported option(s) are described below:

netns: string() - Used to set the network namespace during the open call. Only supported on Linux.

debug: boolean() - Enable or disable debug logging.

Defaults to false.

use_registry: boolean() - Enable or disable use of the socket registry for this socket. This overrides the global value.

Defaults to the global value, see use_registry/1.

peeloff(Socket, AssocId)

(since OTP 29.0)

-spec peeloff(Socket, AssocId) -> {ok, NewSock} | {ok, NewSock, InheritErrs} | {error, Reason}
                 when
                     Socket :: socket(),
                     AssocId :: sctp_assoc_id(),
                     NewSock :: socket(),
                     InheritErrs :: [{SockOpt, get | set, Reason}],
                     SockOpt :: socket_option(),
                     Reason :: posix() | closed.

Branch off an association into a separate socket.

Equivalent to peeloff(Socket, AssocId, [])

peeloff(Socket, AssocId, InheritOpts)

(since OTP 29.0)

-spec peeloff(Socket, AssocId, InheritOpts) ->
                 {ok, NewSock} | {ok, NewSock, InheritErrs} | {error, Reason}
                 when
                     Socket :: socket(),
                     AssocId :: sctp_assoc_id(),
                     InheritOpts :: [socket_option()],
                     NewSock :: socket(),
                     InheritErrs :: [{SockOpt, get | set, Reason}],
                     SockOpt :: socket_option(),
                     Reason :: posix() | closed.

Branch off an association into a separate socket.

Create a new one-to-one socket from an existing one-to-many socket. The specified InheritOpts will be inherited by the new socket (get from existing socket and then set on the new socket).

If the peeloff operation is successful but some (or all) of the InheritOpts failed to transfer to the new socket, {'ok', NewSock, InheritErrs} is returned. It is then up to the caller to decide if this is acceptable.

peername(Socket)

(since OTP 22.0)

-spec peername(Socket :: socket()) -> {ok, SockAddr} | {error, Reason}
                  when SockAddr :: sockaddr_recv(), Reason :: posix() | closed.

Return the remote address of a socket.

Returns the address of the connected peer, that is, the remote end of the socket.

peernames(Socket, AssocId)

(since OTP 29.0)

-spec peernames(Socket :: socket(), AssocId :: sctp_assoc_id()) -> {ok, [SockAddr]} | {error, Reason}
                   when SockAddr :: sockaddr_recv(), Reason :: posix() | closed.

Return the remote (peer) address(s) of an association of a socket.

If the socket is IPv4 then all returned addresess will be IPv4. If the socket is IPv6, then the returned addresess can be a mix of IPv4 and IPv6.

For a one-to-many socket, AssocId specifies the association. For a one-to-one socket, AssocId is ignored.

The behaviour if AssocId is 0 (zero), is undefined for one-to-many sockets.

recv(Socket)

(since OTP 22.0)

-spec recv(Socket :: socket()) -> dynamic().

Equivalent to recv(Socket, 0, [], infinity).

recv/2

(since OTP 22.0)

-spec recv(Socket :: socket(), Flags :: [msg_flag() | integer()]) -> dynamic();
          (Socket :: socket(), Length :: non_neg_integer()) -> dynamic().

Receive data on a connected socket.

With argument Length; equivalent to recv(Socket, Length, [], infinity).

With argument Flags; equivalent to recv(Socket, 0, Flags, infinity) (since OTP 24.0).

recv/3

(since OTP 22.0)

-spec recv(Socket, Flags, TimeoutOrHandle) -> dynamic()
              when
                  Socket :: socket(),
                  Flags :: [msg_flag() | integer()],
                  TimeoutOrHandle :: timeout() | nowait | select_handle() | completion_handle();
          (Socket :: socket(), Length :: non_neg_integer(), Flags :: [msg_flag() | integer()]) ->
              dynamic();
          (Socket :: socket(), Length :: non_neg_integer(), TimeoutOrHandle) -> dynamic()
              when TimeoutOrHandle :: timeout() | nowait | select_handle() | completion_handle().

Receive data on a connected socket.

With arguments Length and Flags; equivalent to recv(Socket, Length, Flags, infinity).

With arguments Length and TimeoutOrHandle; equivalent to recv(Socket, Length, [], TimeoutOrHandle). TimeoutOrHandle :: nowait has been allowed since OTP 22.1. TimeoutOrHandle :: Handle has been allowed since OTP 24.0.

With arguments Flags and TimeoutOrHandle; equivalent to recv(Socket, 0, Flags, TimeoutOrHandle) (since OTP 24.0).

recv/4

(since OTP 22.0)

-spec recv(Socket, Length, Flags, Timeout :: infinity) ->
              {ok, Data} | {error, Reason} | {error, {Reason, Data}}
              when
                  Socket :: socket(),
                  Length :: non_neg_integer(),
                  Flags :: [msg_flag() | integer()],
                  Data :: binary(),
                  Reason :: posix() | closed | invalid();
          (Socket, Length, Flags, Timeout :: non_neg_integer()) ->
              {ok, Data} | {error, Reason} | {error, {Reason, Data}}
              when
                  Socket :: socket(),
                  Length :: non_neg_integer(),
                  Flags :: [msg_flag() | integer()],
                  Data :: binary(),
                  Reason :: posix() | closed | invalid() | timeout;
          (Socket, Length, Flags, nowait | Handle) ->
              {ok, Data} |
              {select, SelectInfo} |
              {select, {SelectInfo, Data}} |
              {select_read, {SelectInfo, Data}} |
              {completion, CompletionInfo} |
              {error, Reason}
              when
                  Socket :: socket(),
                  Length :: non_neg_integer(),
                  Flags :: [msg_flag() | integer()],
                  Handle :: select_handle() | completion_handle(),
                  Data :: binary(),
                  SelectInfo :: select_info(),
                  CompletionInfo :: completion_info(),
                  Reason :: posix() | closed | invalid().

Receive data on a connected socket.

The argument Length specifies the size of the receive buffer. Packet oriented sockets truncate the packet if the size is too small.

If Length == 0; a default buffer size is used, which can be set by socket:setopt(Socket, {otp,recvbuf}, BufSz).

For a socket of type stream, when a Timeout argument is used, the operation iterates until Length bytes has been received, or the operation times out. If Length == 0 all readily available data is returned.

On a select system, when the default receive buffer size option {otp,recvbuf} special value {N,BufSize} is used, N limits how many BufSize buffers that may be received in a tight loop before the receive operation returns. The option value {1,BufSize} is equivalent to just specifying a size value BufSize.

The message Flags may be symbolic msg_flag/0s and/or integer/0s as in the platform's appropriate header files. The values of all symbolic flags and integers are or:ed together.

When there is a socket error this function returns {error, Reason}, or if some data arrived before the error; {error, {Reason, Data}} (can only happen for a socket of type stream).

If the Timeout argument is infinity; waits for the data to arrive. For a socket of type stream this call won't return until all requested data can be delivered, or if "all available" was requested when the first data chunk arrives, or if the OS reports an error for the operation.

If the Timeout argument is a time-out value (non_neg_integer/0); return {error, timeout} if no data has arrived after Timeout milliseconds, or {error, {timeout, Data}} if some but not enough data has been received on a socket of type stream with Length > 0. It can also return directly with {ok, Data} (type dgram).

Timeout = 0 only polls the OS receive call and doesn't engage the Asynchronous Calls mechanisms. If no data is immediately available {error, timeout} is returned.On a socket of type stream, {error, {timeout, Data}} is returned if there is an insufficient amount of data immediately available.

If the Handle argument is nowait (since OTP 22.1), starts an asynchronous call if the operation couldn't be completed immediately.

If the Handle argument is a select_handle/0, (since OTP 24.0), or on Windows, the equivalent completion_handle/0 (since OTP 26.0), starts an asynchronous call like for nowait.

See the note Asynchronous Calls at the start of this module reference manual page.

The possible values for CompletionStatus in the completion message are:

{ok, Data} - Complete success; All requested data was read.

{more, Data} - Partial success; Some, but not all, data was read.

{error, Reason} - An error occured and no data was read.

On select systems, for a socket of type stream, if Length > 0 and there is some but not enough data available, this function will return {select, {SelectInfo, Data}} with partial Data. A repeated call to complete the operation may need an updated Length argument.

On select systems, if the option {otp, select_read} is set, {select_read, {SelectInfo, Data}} is returned instead of {ok, Data} and a new asynchronous receive operation has been initiated, which can be seen as an automatic nowait call whenever a receive operation is completed.

recvfrom(Socket)

(since OTP 22.0)

-spec recvfrom(Socket :: socket()) -> dynamic().

Equivalent to recvfrom(Socket, 0, [], infinity).

recvfrom/2

(since OTP 22.0)

-spec recvfrom(Socket :: socket(), Flags :: list()) -> dynamic();
              (Socket :: socket(), BufSz :: non_neg_integer()) -> dynamic().

Receive a message on a socket.

With argument BufSz; equivalent to recvfrom(Socket, BufSz, [], infinity).

With argument Flags; equivalent to recvfrom(Socket, 0, Flags, infinity) (since OTP 24.0).

recvfrom/3

(since OTP 22.0)

-spec recvfrom(Socket :: socket(), Flags :: [msg_flag() | integer()], TimeoutOrHandle :: dynamic()) ->
                  dynamic();
              (Socket :: socket(), BufSz :: non_neg_integer(), Flags :: [msg_flag() | integer()]) ->
                  dynamic();
              (Socket :: socket(), BufSz :: non_neg_integer(), TimeoutOrHandle) -> dynamic()
                  when TimeoutOrHandle :: timeout() | nowait | select_handle() | completion_handle().

Receive a message on a socket.

With arguments BufSz and Flags; equivalent to recvfrom(Socket, BufSz, Flags, infinity).

With arguments BufSz and TimeoutOrHandle; equivalent to recvfrom(Socket, BufSz, [], TimeoutOrHandle).

With arguments Flags and TimeoutOrHandle; equivalent to recvfrom(Socket, 0, Flags, TimeoutOrHandle)

TimeoutOrHandle :: 'nowait' has been allowed since OTP 22.1.

TimeoutOrHandle :: Handle has been allowed since OTP 24.0.

recvfrom/4

(since OTP 22.0)

-spec recvfrom(Socket, BufSz, Flags, Timeout :: infinity) -> {ok, {Source, Data}} | {error, Reason}
                  when
                      Socket :: socket(),
                      BufSz :: non_neg_integer(),
                      Flags :: [msg_flag() | integer()],
                      Source :: sockaddr_recv(),
                      Data :: binary(),
                      Reason :: posix() | closed | invalid();
              (Socket, BufSz, Flags, Timeout :: non_neg_integer()) ->
                  {ok, {Source, Data}} | {error, Reason}
                  when
                      Socket :: socket(),
                      BufSz :: non_neg_integer(),
                      Flags :: [msg_flag() | integer()],
                      Source :: sockaddr_recv(),
                      Data :: binary(),
                      Reason :: posix() | closed | invalid() | timeout;
              (Socket, BufSz, Flags, nowait | Handle) ->
                  {ok, {Source, Data}} |
                  {select, SelectInfo} |
                  {select_read, {SelectInfo, {Source, Data}}} |
                  {completion, CompletionInfo} |
                  {error, Reason}
                  when
                      Socket :: socket(),
                      BufSz :: non_neg_integer(),
                      Flags :: [msg_flag() | integer()],
                      Handle :: select_handle() | completion_handle(),
                      Source :: sockaddr_recv(),
                      Data :: binary(),
                      SelectInfo :: select_info(),
                      CompletionInfo :: completion_info(),
                      Reason :: posix() | closed | invalid().

Receive a message on a socket.

This function is intended primarily for sockets that are not connection oriented such as type dgram or seqpacket where messages may arrive from different source addresses.

Argument BufSz specifies the number of bytes for the receive buffer. If the buffer size is too small, the message will be truncated.

If BufSz is 0, a default buffer size is used, which can be set by socket:setopt(Socket, {otp,recvbuf}, BufSz).

If there is no known appropriate buffer size, it may be possible to use the receive message flag peek. When this flag is used, the message is not "consumed" from the underlying buffers, so another recvfrom/1,2,3,4 call is needed, possibly with an adjusted buffer size.

The message Flags may be symbolic msg_flag/0s and/or integer/0s, as in the platform's appropriate header files. The values of all symbolic flags and integers are or:ed together.

If the Timeout argument is infinity; waits for a message to arrive, or for a socket error.

If the Timeout argument is a time-out value (non_neg_integer/0); returns {error, timeout} if no message has arrived after Timeout milliseconds.

Timeout = 0 only polls the OS receive call and doesn't engage the Asynchronous Calls mechanisms. If no message is immediately available {error, timeout} is returned.

If the Handle argument is nowait (since OTP 22.1), starts an asynchronous call if the operation couldn't be completed immediately.

If the 'Handle' argument is a select_handle/0, (since OTP 24.0), or on Windows, the equivalent completion_handle/0 (since OTP 26.0), starts an asynchronous call like for nowait.

See the note Asynchronous Calls at the start of this module reference manual page.

The possible values for CompletionStatus in the completion message are:

{ok, {Source, Data}} - Success.

{error, Reason} - An error occured and no data was read.

recvmmsg/6

(since OTP 29.0)

-spec recvmmsg(Socket, VLen, BufSz, CtrlSz, Flags, Timeout :: infinity) -> {ok, Msgs} | {error, Reason}
                  when
                      Socket :: socket(),
                      VLen :: non_neg_integer(),
                      BufSz :: non_neg_integer(),
                      CtrlSz :: non_neg_integer(),
                      Flags :: [msg_flag() | integer()],
                      Msgs :: [msg_recv()],
                      Reason :: posix() | closed | invalid();
              (Socket, VLen, BufSz, CtrlSz, Flags, Timeout :: non_neg_integer()) ->
                  {ok, Msgs} | {error, Reason}
                  when
                      Socket :: socket(),
                      VLen :: non_neg_integer(),
                      BufSz :: non_neg_integer(),
                      CtrlSz :: non_neg_integer(),
                      Flags :: [msg_flag() | integer()],
                      Msgs :: [msg_recv()],
                      Reason :: posix() | closed | invalid() | timeout;
              (Socket, VLen, BufSz, CtrlSz, Flags, nowait | Handle) ->
                  {ok, Msgs} |
                  {select, SelectInfo} |
                  {select_read, {SelectInfo, Msgs}} |
                  {completion, CompletionInfo} |
                  {error, Reason}
                  when
                      Socket :: socket(),
                      VLen :: non_neg_integer(),
                      BufSz :: non_neg_integer(),
                      CtrlSz :: non_neg_integer(),
                      Handle :: select_handle() | completion_handle(),
                      Flags :: [msg_flag() | integer()],
                      Msgs :: [msg_recv()],
                      SelectInfo :: select_info(),
                      CompletionInfo :: completion_info(),
                      Reason :: posix() | closed | invalid().

Receive multiple messages on a socket.

This function is equivalent to calling recvmsg/5 multiple times, but uses the platform's recvmmsg syscall for better performance when receiving multiple datagrams.

Note

This function is only available on Linux and BSD systems (not macOS/Darwin or Windows). On unsupported platforms, it will return {error, notsup}.

Arguments:

VLen - Maximum number of messages to receive (must be >= 1).

BufSz - Buffer size for each message (0 uses default).

CtrlSz - Control message buffer size for each message (0 uses default).

Flags - Receive flags (same as recvmsg/5).

Timeout - Timeout or nowait or infinity.

Returns a list of message maps, one per received message. The list length indicates how many messages were actually received.

recvmsg(Socket)

(since OTP 22.0)

-spec recvmsg(Socket :: socket()) -> dynamic().

Equivalent to recvmsg(Socket, 0, 0, [], infinity).

recvmsg/2

(since OTP 22.0)

-spec recvmsg(Socket :: socket(), Flags :: list()) -> dynamic();
             (Socket :: socket(), TimeoutOrHandle) -> dynamic()
                 when
                     TimeoutOrHandle :: timeout() | nowait | Handle,
                     Handle :: select_handle() | completion_handle().

Receive a message on a socket.

With argument Flags; equivalent to recvmsg(Socket, 0, 0, Flags, infinity).

With argument TimeoutOrHandle; equivalent to recvmsg(Socket, 0, 0, [], TimeoutOrHandle).

TimeoutOrHandle :: nowait has been allowed since OTP 22.1.

TimeoutOrHandle :: Handle has been allowed since OTP 24.0.

recvmsg/3

(since OTP 22.0)

-spec recvmsg(Socket :: dynamic(), Flags :: list(), TimeoutOrHandle :: dynamic()) -> dynamic();
             (Socket :: dynamic(), BufSz :: integer(), CtrlSz :: integer()) -> dynamic().

Receive a message on a socket.

With arguments Flags; equivalent to recvmsg(Socket, 0, 0, Flags, infinity).

With argument TimeoutOrHandle; equivalent to recvmsg(Socket, 0, 0, [], TimeoutOrHandle).

TimeoutOrHandle :: nowait has been allowed since OTP 22.1.

TimeoutOrHandle :: Handle has been allowed since OTP 24.0.

recvmsg(Socket, BufSz, CtrlSz, TimeoutOrHandle)

(since OTP 24.0)

-spec recvmsg(Socket :: socket(),
              BufSz :: non_neg_integer(),
              CtrlSz :: non_neg_integer(),
              TimeoutOrHandle :: dynamic()) ->
                 dynamic().

Equivalent to recvmsg(Socket, BufSz, CtrlSz, [], TimeoutOrHandle).

recvmsg/5

(since OTP 22.0)

-spec recvmsg(Socket, BufSz, CtrlSz, Flags, Timeout :: infinity) -> {ok, Msg} | {error, Reason}
                 when
                     Socket :: socket(),
                     BufSz :: non_neg_integer(),
                     CtrlSz :: non_neg_integer(),
                     Flags :: [msg_flag() | integer()],
                     Msg :: msg_recv(),
                     Reason :: posix() | closed | invalid();
             (Socket, BufSz, CtrlSz, Flags, Timeout :: non_neg_integer()) -> {ok, Msg} | {error, Reason}
                 when
                     Socket :: socket(),
                     BufSz :: non_neg_integer(),
                     CtrlSz :: non_neg_integer(),
                     Flags :: [msg_flag() | integer()],
                     Msg :: msg_recv(),
                     Reason :: posix() | closed | invalid() | timeout;
             (Socket, BufSz, CtrlSz, Flags, nowait | Handle) ->
                 {ok, Msg} |
                 {select, SelectInfo} |
                 {select_read, {SelectInfo, Msg}} |
                 {completion, CompletionInfo} |
                 {error, Reason}
                 when
                     Socket :: socket(),
                     BufSz :: non_neg_integer(),
                     CtrlSz :: non_neg_integer(),
                     Handle :: select_handle() | completion_handle(),
                     Flags :: [msg_flag() | integer()],
                     Msg :: msg_recv(),
                     SelectInfo :: select_info(),
                     CompletionInfo :: completion_info(),
                     Reason :: posix() | closed | invalid().

Receive a message on a socket.

This function receives a data message with control messages as well as its source address.

Arguments BufSz and CtrlSz specifies the number of bytes for the receive buffer and the control message buffer. If the buffer size(s) is(are) too small, the message and/or control message list will be truncated.

If BufSz is 0, a default buffer size is used, which can be set by socket:setopt(Socket, {otp,recvbuf}, BufSz). The same applies to CtrlSz and socket:setopt(Socket, {otp,recvctrlbuf}, CtrlSz).

If there is no known appropriate buffer size, it may be possible to use the receive message flag peek. When this flag is used, the message is not "consumed" from the underlying buffers, so another recvfrom/1,2,3,4 call is needed, possibly with an adjusted buffer size.

The message Flags may be symbolic msg_flag/0s and/or integer/0s, as in the platform's appropriate header files. The values of all symbolic flags and integers are or:ed together.

If the Timeout argument is infinity; waits for the message to arrive, or for a socket error.

If the Timeout argument is a time-out value (non_neg_integer/0); return {error, timeout} if no message has arrived after Timeout milliseconds.

Timeout = 0 only polls the OS receive call and doesn't engage the Asynchronous Calls mechanisms. If no message is immediately available {error, timeout} is returned.

If the Handle argument is nowait (since OTP 22.1), starts an asynchronous call if the operation couldn't be completed immediately.

If the 'Handle' argument is a select_handle/0, (since OTP 24.0), or on Windows, the equivalent completion_handle/0 (since OTP 26.0), starts an asynchronous call like for nowait.

See the note Asynchronous Calls at the start of this module reference manual page.

The possible values for CompletionStatus in the completion message are:

{ok, Msg} - Success.

{error, Reason} - An error occured and no data was read.

rest_iov(Written, IOV)

(since OTP 28.0.2)

-spec rest_iov(Written, IOV) -> RestIOV
                  when Written :: non_neg_integer(), IOV :: erlang:iovec(), RestIOV :: erlang:iovec().

Calculate the rest I/O vector after a partially successful sendv (CompletionStatus was {ok, Written}).

send(Socket, Data)

(since OTP 22.0)

-spec send(Socket, Data) -> Result
              when
                  Socket :: socket(),
                  Data :: iodata(),
                  Result ::
                      ok |
                      {ok, RestData :: binary()} |
                      {select, SelectInfo :: dynamic()} |
                      {completion, CompletionInfo :: dynamic()} |
                      {error, Reason :: dynamic()}.

Equivalent to send(Socket, Data, [], infinity).

send/3

(since OTP 22.0)

-spec send(Socket :: term(), Data :: term(), Cont :: tuple()) -> _;
          (Socket :: term(), Data :: term(), Flags :: list()) -> _;
          (Socket :: term(), Data :: term(), Timeout :: timeout()) -> _.

Send data on a connected socket.

With argument Timeout; equivalent to send(Socket, Data, [], Timeout).

With argument Flags; equivalent to send(Socket, Data, Flags, infinity).

With argument Cont; equivalent to send(Socket, Data, Cont, infinity) (since OTP 24.0).

send/4

(since OTP 22.0)

-spec send(Socket, Data, Flags | Cont, Timeout :: infinity) ->
              ok | {ok, RestData} | {error, Reason} | {error, {Reason, RestData}}
              when
                  Socket :: socket(),
                  Data :: iodata(),
                  Flags :: [msg_flag() | integer()],
                  Cont :: select_info(),
                  RestData :: binary(),
                  Reason :: posix() | closed | invalid() | netname_deleted | too_many_cmds | eei();
          (Socket, Data, Flags | Cont, Timeout :: non_neg_integer()) ->
              ok | {ok, RestData} | {error, Reason | timeout} | {error, {Reason | timeout, RestData}}
              when
                  Socket :: socket(),
                  Data :: iodata(),
                  Flags :: [msg_flag() | integer()],
                  Cont :: select_info(),
                  RestData :: binary(),
                  Reason :: posix() | closed | invalid() | netname_deleted | too_many_cmds | eei();
          (Socket, Data, Flags | Cont, nowait | Handle) ->
              ok |
              {ok, RestData} |
              {select, SelectInfo} |
              {select, {SelectInfo, RestData}} |
              {completion, CompletionInfo} |
              {error, Reason}
              when
                  Socket :: socket(),
                  Data :: iodata(),
                  Flags :: [msg_flag() | integer()],
                  Cont :: select_info(),
                  Handle :: select_handle() | completion_handle(),
                  RestData :: binary(),
                  SelectInfo :: select_info(),
                  CompletionInfo :: completion_info(),
                  Reason :: posix() | closed | invalid() | netname_deleted | too_many_cmds | eei().

Send data on a connected socket.

The message Flags may be symbolic msg_flag/0s and/or integer/0s as in the platform's appropriate header files. The values of all symbolic flags and integers are or:ed together.

The Data, if it is not a binary/0, is copied into one before calling the platform network API, because a single buffer is required. A returned RestData is a sub binary of it.

The return value indicates the result from the platform's network layer:

ok - All data was accepted by the OS for delivery

{ok, RestData} - Some but not all data was accepted, but no error was reported (partially successful send). RestData is the tail of Data that wasn't accepted.

This cannot happen for a socket of type stream where such a partially successful send is retried until the data is either accepted for delivery or there is an error.

For a socket of type dgram this should probably also not happen since a message that cannot be passed atomically should render an error.

It is nevertheless possible for the platform's network layer to return this, surely more possible for a socket of type seqpacket.

{error, Reason} - An error has been reported and no data was accepted for delivery. Reason :: posix/0 is what the platform's network layer reported. closed means that this socket library was informed that the socket was closed, and invalid/0 means that this socket library found an argument to be invalid.

{error, {Reason, RestData}} - An error was reported but before that some data was accepted for delivery. RestData is the tail of Data that wasn't accepted. See {error, Reason} above.

This can only happen for a socket of type stream when a partially successful send is retried until there is an error.

If the Timeout argument is infinity; wait for the OS to complete the send operation (take responsibility for the data), or return an error.

If the Timeout argument is a time-out value (non_neg_integer/0); return {error, timeout} if no data has been sent within Timeout millisecond, or {error, {timeout, RestData}} if some data was sent (accepted by the OS for delivery). RestData is the tail of the data that hasn't been sent.

If the Handle argument is nowait (since OTP 22.1), starts an asynchronous call if the operation couldn't be completed immediately.

If the Handle argument is a select_handle/0, (since OTP 24.0), or on Windows, the equivalent completion_handle/0 (since OTP 26.0), starts an asynchronous call like for nowait.

See the note Asynchronous Calls at the start of this module reference manual page.

The possible values for CompletionStatus in the completion message are:

ok - Complete success; The data was written in its entirety.

{ok, Written} - Partial success; Some but not all data was written, but no error was reported. Written is the number of bytes that was written.

{error, Reason} - An error occured and no data was sent.

If the function is called with a Cont argument, that is; the SelectInfo from the previous send/3,4 call; the send is continued with preprocessed send parameters in the SelectInfo. Using this argument variant avoids for example having to validate and encode message flags in every call but the first.

sendfile(Socket, FileHandle_Cont)

(since OTP 24.0)

-spec sendfile(Socket, FileHandle | Continuation) -> dynamic()
                  when Socket :: socket(), FileHandle :: file:fd(), Continuation :: select_info().

Send a file on a socket.

Equivalent to sendfile(Socket, FileHandle_or_Continuation, 0, 0, infinity).

sendfile(Socket, FileHandle_Cont, Timeout_Handle)

(since OTP 24.0)

-spec sendfile(Socket, FileHandle | Continuation, Timeout | Handle) -> dynamic()
                  when
                      Socket :: socket(),
                      FileHandle :: file:fd(),
                      Continuation :: select_info(),
                      Timeout :: infinity | non_neg_integer(),
                      Handle :: nowait | select_handle().

Send a file on a socket.

Equivalent to sendfile(Socket, FileHandle_or_Continuation, 0, 0, Timeout_or_Handle).

sendfile(Socket, FileHandle_Cont, Offset, Count)

(since OTP 24.0)

-spec sendfile(Socket, FileHandle | Continuation, Offset, Count) -> dynamic()
                  when
                      Socket :: socket(),
                      FileHandle :: file:fd(),
                      Continuation :: select_info(),
                      Offset :: integer(),
                      Count :: non_neg_integer().

Send a file on a socket.

Equivalent to sendfile(Socket, FileHandle_or_Continuation, Offset, Count, infinity).

sendfile/5

(since OTP 24.0)

-spec sendfile(Socket, FileHandle | Continuation, Offset, Count, Timeout :: infinity) ->
                  {ok, BytesSent} | {error, Reason} | {error, {Reason, BytesSent}}
                  when
                      Socket :: socket(),
                      FileHandle :: file:fd(),
                      Continuation :: select_info(),
                      Offset :: integer(),
                      Count :: non_neg_integer(),
                      BytesSent :: non_neg_integer(),
                      Reason :: posix() | closed | invalid();
              (Socket, FileHandle | Continuation, Offset, Count, Timeout :: non_neg_integer()) ->
                  {ok, BytesSent} | {error, Reason} | {error, {Reason, BytesSent}}
                  when
                      Socket :: socket(),
                      FileHandle :: file:fd(),
                      Continuation :: select_info(),
                      Offset :: integer(),
                      Count :: non_neg_integer(),
                      BytesSent :: non_neg_integer(),
                      Reason :: posix() | closed | invalid() | timeout;
              (Socket,
               FileHandle | Continuation,
               Offset, Count,
               nowait | (SelectHandle :: select_handle())) ->
                  {ok, BytesSent} |
                  {select, SelectInfo} |
                  {select, {SelectInfo, BytesSent}} |
                  {error, Reason}
                  when
                      Socket :: socket(),
                      FileHandle :: file:fd(),
                      Continuation :: select_info(),
                      Offset :: integer(),
                      Count :: non_neg_integer(),
                      BytesSent :: non_neg_integer(),
                      SelectInfo :: select_info(),
                      Reason :: posix() | closed | invalid().

Send a file on a socket.

Note

This function unsupported on Windows.

The FileHandle argument must refer to an open raw file as described in file:open/2.

The Offset argument is the file offset to start reading from. The default offset is 0.

The Count argument is the number of bytes to transfer from FileHandle to Socket. If Count = 0 (the default) the transfer stops at the end of file.

The return value indicates the result from the platform's network layer:

{ok, BytesSent} - The transfer completed successfully after BytesSent bytes of data.

{error, Reason} - An error has been reported and no data was transferred. Reason :: posix/0 is what the platform's network layer reported. closed means that this socket library was informed that the socket was closed, and invalid/0 means that this socket library found an argument to be invalid.

{error, {Reason, BytesSent}} - An error has been reported but before that some data was transferred. See {error, Reason} and {ok, BytesSent} above.

If the Timeout argument is infinity; wait for the OS to complete the send operation (take responsibility for the data), or return an error.

If the Timeout argument is a time-out value (non_neg_integer/0); return {error, timeout} if no data has been sent within Timeout millisecond, or {error, {timeout, BytesSent}} if some but not all data was sent (accepted by the OS for delivery).

If the Handle argument is nowait, starts an asynchronous call if the operation couldn't be completed immediately.

If the Handle argument is a select_handle/0, starts an asynchronous call like for nowait.

See the note Asynchronous Calls at the start of this module reference manual page.

After receiving a select message; call sendfile/2,3,4,5 with SelectInfo as the Continuation argument, to complete the operation.

If the function is called with a Continuation argument, that is; the SelectInfo from the previous sendfile/5 call; the transfer is continued with preprocessed parameters in the SelectInfo.

The Offset and maybe Count arguments will probably need to be updated between continuation calls.

sendmmsg/4

(since OTP 29.0)

-spec sendmmsg(Socket, Msgs, Flags, Timeout :: infinity) -> ok | {ok, Rest} | {error, Reason}
                  when
                      Socket :: socket(),
                      Msgs :: [msg_send()],
                      Flags :: [msg_flag() | integer()],
                      Rest :: [erlang:iovec()],
                      Reason :: posix() | closed | invalid();
              (Socket, Msgs, Flags, Timeout :: non_neg_integer()) ->
                  ok | {ok, Rest} | {error, Reason | timeout}
                  when
                      Socket :: socket(),
                      Msgs :: [msg_send()],
                      Flags :: [msg_flag() | integer()],
                      Rest :: [erlang:iovec()],
                      Reason :: posix() | closed | invalid();
              (Socket, Msgs, Flags, nowait | Handle) ->
                  ok |
                  {ok, Rest} |
                  {select_write, {SelectInfo, SentCount}} |
                  {select, SelectInfo} |
                  {completion, CompletionInfo} |
                  {error, Reason}
                  when
                      Socket :: socket(),
                      Msgs :: [msg_send()],
                      Flags :: [msg_flag() | integer()],
                      Handle :: select_handle() | completion_handle(),
                      Rest :: [erlang:iovec()],
                      SentCount :: non_neg_integer(),
                      SelectInfo :: select_info(),
                      CompletionInfo :: completion_info(),
                      Reason :: posix() | closed | invalid().

Send multiple messages on a socket.

This function is equivalent to calling sendmsg/4 multiple times, but uses the platform's sendmmsg syscall for better performance when sending multiple datagrams.

Note

This function is only available on Linux and BSD systems (not macOS/Darwin or Windows). On unsupported platforms, it will return {error, notsup}.

On success, returns either:

ok – when all messages were sent in full (or there were zero messages).

{ok, Rest} – when one or more messages had a partial write. Rest is a list with one element per message that was not fully sent, in message order. Each element is the remaining data for that message in the same form as sendmsg/4's rest data (erlang:iovec/0), so you can retry with sendmsg for each.

On error returns {error, Reason}.

sendmsg(Socket, Msg)

(since OTP 22.0)

-spec sendmsg(Socket, Msg) -> Result
                 when Socket :: socket(), Msg :: msg_send() | erlang:iovec(), Result :: dynamic().

Equivalent to sendmsg(Socket, Msg, [], infinity).

sendmsg/3

(since OTP 22.0)

-spec sendmsg(Socket :: socket(), Msg :: msg_send(), Flags :: list()) -> dynamic();
             (Socket :: socket(), Data :: msg_send() | erlang:iovec(), Cont :: select_info()) ->
                 dynamic();
             (Socket :: socket(), Msg :: msg_send(), Timeout :: infinity) -> dynamic().

Send data and control messages on a socket.

With arguments Msg and Timeout; equivalent to sendmsg(Socket, Msg, [], Timeout).

With arguments Msg and Flags; equivalent to sendmsg(Socket, Msg, Flags, infinity).

With arguments Data and Cont; equivalent to sendmsg(Socket, Data, Cont, infinity) since OTP 24.0.

sendmsg/4

(since OTP 22.0)

-spec sendmsg(Socket, Msg, Flags, Timeout :: infinity) ->
                 ok | {ok, RestData} | {error, Reason} | {error, {Reason, RestData}}
                 when
                     Socket :: socket(),
                     Msg :: msg_send(),
                     Flags :: [msg_flag() | integer()],
                     RestData :: erlang:iovec(),
                     Reason :: posix() | closed | invalid();
             (Socket, Msg, Flags, Timeout :: non_neg_integer()) ->
                 ok | {ok, RestData} | {error, Reason | timeout} | {error, {Reason | timeout, RestData}}
                 when
                     Socket :: socket(),
                     Msg :: msg_send(),
                     Flags :: [msg_flag() | integer()],
                     RestData :: erlang:iovec(),
                     Reason :: posix() | closed | invalid();
             (Socket, Msg, Flags, nowait | Handle) ->
                 ok |
                 {ok, RestData} |
                 {select, SelectInfo} |
                 {select, {SelectInfo, RestData}} |
                 {completion, CompletionInfo} |
                 {error, Reason} |
                 {error, {Reason, RestData}}
                 when
                     Socket :: socket(),
                     Msg :: msg_send(),
                     Flags :: [msg_flag() | integer()],
                     Handle :: select_handle() | completion_handle(),
                     RestData :: erlang:iovec(),
                     SelectInfo :: select_info(),
                     CompletionInfo :: completion_info(),
                     Reason :: posix() | closed | invalid();
             (Socket, Data, Cont, Timeout :: infinity) ->
                 ok | {ok, RestData} | {error, Reason} | {error, {Reason, RestData}}
                 when
                     Socket :: socket(),
                     Data :: msg_send() | erlang:iovec(),
                     Cont :: select_info(),
                     RestData :: erlang:iovec(),
                     Reason :: posix() | closed | invalid();
             (Socket, Data, Cont, Timeout :: non_neg_integer()) ->
                 ok | {ok, RestData} | {error, Reason | timeout} | {error, {Reason | timeout, RestData}}
                 when
                     Socket :: socket(),
                     Data :: msg_send() | erlang:iovec(),
                     Cont :: select_info(),
                     RestData :: erlang:iovec(),
                     Reason :: posix() | closed | invalid();
             (Socket, Data, Cont, nowait | Handle) ->
                 ok |
                 {ok, RestData} |
                 {select, SelectInfo} |
                 {select, {SelectInfo, RestData}} |
                 {completion, CompletionInfo} |
                 {error, Reason} |
                 {error, {Reason, RestData}}
                 when
                     Socket :: socket(),
                     Data :: msg_send() | erlang:iovec(),
                     Cont :: select_info(),
                     Handle :: select_handle(),
                     RestData :: erlang:iovec(),
                     SelectInfo :: select_info(),
                     CompletionInfo :: completion_info(),
                     Reason :: posix() | closed | invalid().

Send data and control messages on a socket.

The argument Msg is a map that contains the data to be sent under the key iov as anerlang:iovec/0 (list of binary/0). It may also contain the destination address under the key addr, which is mandatory if the socket isn't connected. If the socket is connected it is best to not have an addr key since the platform may regard that as an error (or ignore it). Under the key ctrl there may be a list of protocol and platform dependent control messages (a.k.a ancillary data, a.k.a control information) to send.

The message data is given to the platform's network layer as an I/O vector without copying the content. If the number of elements in the I/O vector is larger than allowed on the platform (reported in the iov_max field from info/0), on a socket of type stream the send is iterated over all elements, but for other socket types the call fails.

See send/4 for a description of the Flags argument and the return values.

Note

On Windows, this function can only be used with datagram and raw sockets.

If the Timeout argument is infinity; wait for the OS to complete the send operation (take responsibility for the data), or return an error.

If the Timeout argument is a time-out value (non_neg_integer/0); return {error, timeout} if no data has been sent within Timeout millisecond, or {error, {timeout, RestData}} if some data was sent (accepted by the OS for delivery). RestData is the tail of the data that hasn't been sent.

If the Handle argument is nowait (since OTP 22.1), starts an asynchronous call if the operation couldn't be completed immediately.

If the Handle argument is a select_handle/0, (since OTP 24.0), or on Windows, the equivalent completion_handle/0 (since OTP 26.0), starts an asynchronous call like for nowait.

See the note Asynchronous Calls at the start of this module reference manual page.

The possible values for CompletionStatus in the completion message are:

ok - Complete success; The data was written in its entirety.

{ok, Written} - Partial success; Some but not all data was written, but no error was reported. Written is the number of bytes that was written.

{error, Reason} - An error occured and no data was sent.

After receiving a select message; call sendmsg/3,4 with SelectInfo as the Cont argument, to complete the operation.

With the arguments Data and Cont, continues the send operation. Cont should be the SelectInfo returned from the previous sendmsg/2,3,4 call.

Data can be a Msg map/0 where only the key iov is used, or an erlang:iovec/0.

sendto/3

(since OTP 22.0)

-spec sendto(Socket :: socket(), Data :: iodata(), Cont | Dest) -> Result
                when
                    Cont :: select_info(),
                    Dest :: sockaddr(),
                    Result :: ok | {ok, RestData} | {error, Reason} | {error, {Reason, RestData}},
                    RestData :: binary(),
                    Reason :: posix() | closed | invalid().

Send data on a socket.

With argument Dest; equivalent to sendto(Socket, Data, Dest, [], infinity).

With argument Cont; equivalent to sendto(Socket, Data, Cont, infinity) since OTP 24.0.

sendto/4

(since OTP 22.0)

-spec sendto(Socket :: socket(),
             Data :: iodata(),
             Dest :: sockaddr(),
             Flags :: [msg_flag() | integer()]) ->
                dynamic();
            (Socket :: socket(),
             Data :: iodata(),
             Cont :: select_info(),
             Timeout :: timeout() | nowait | (Handle :: select_handle())) ->
                dynamic();
            (Socket :: socket(),
             Data :: iodata(),
             Dest :: sockaddr(),
             Timeout :: timeout() | nowait | (Handle :: select_handle() | completion_handle())) ->
                dynamic().

Send data on a socket.

With arguments Dest and TimeoutOrHandle; equivalent to sendto(Socket, Data, Dest, [], TimeoutOrHandle).

With arguments Dest and Flags; equivalent to sendto(Socket, Data, Dest, Flags, infinity).

With arguments Cont and TimeoutOrHandle; Cont must be the SelectInfo from the previous sendto/3,4,5 call and the send is continued with preprocessed send parameters in the SelectInfo. Using this argument variant avoids for example having o validate and encode message flags in every call but the first. (Since OTP 24.0)

See the last argument (argument 5) of sendto/5 for an explanation of TimeoutOrHandle.

sendto/5

(since OTP 22.0)

-spec sendto(Socket, Data, Dest, Flags, Timeout :: infinity) ->
                ok | {ok, RestData} | {error, Reason} | {error, {Reason, RestData}}
                when
                    Socket :: socket(),
                    Data :: iodata(),
                    Dest :: sockaddr(),
                    Flags :: [msg_flag() | integer()],
                    RestData :: binary(),
                    Reason :: posix() | closed | invalid();
            (Socket, Data, Dest, Flags, Timeout :: non_neg_integer()) ->
                ok | {ok, RestData} | {error, Reason | timeout} | {error, {Reason | timeout, RestData}}
                when
                    Socket :: socket(),
                    Data :: iodata(),
                    Dest :: sockaddr(),
                    Flags :: [msg_flag() | integer()],
                    RestData :: binary(),
                    Reason :: posix() | closed | invalid();
            (Socket, Data, Dest, Flags, nowait | Handle) ->
                ok |
                {ok, RestData} |
                {select, SelectInfo} |
                {select, {SelectInfo, RestData}} |
                {completion, CompletionInfo} |
                {error, Reason}
                when
                    Socket :: socket(),
                    Data :: iodata(),
                    Dest :: sockaddr(),
                    Flags :: [msg_flag() | integer()],
                    Handle :: select_handle() | completion_handle(),
                    RestData :: binary(),
                    SelectInfo :: select_info(),
                    CompletionInfo :: completion_info(),
                    Reason :: posix() | closed | invalid().

Send data on a socket.

The To argument is the destination address where to send the data. For a connected socket this argument is still passed to the OS call that may ignore the address or return an error.

See send/4 for a description of the Flags and Data arguments, and the return values.

If the Timeout argument is infinity; wait for the OS to complete the send operation (take responsibility for the data), or return an error.

If the Timeout argument is a time-out value (non_neg_integer/0); return {error, timeout} if no data has been sent within Timeout millisecond, or {error, {timeout, RestData}} if some data was sent (accepted by the OS for delivery). RestData is the tail of the data that hasn't been sent.

If the Handle argument is nowait (since OTP 22.1), starts an asynchronous call if the operation couldn't be completed immediately.

If the Handle argument is a select_handle/0, (since OTP 24.0), or on Windows, the equivalent completion_handle/0 (since OTP 26.0), starts an asynchronous call like for nowait.

See the note Asynchronous Calls at the start of this module reference manual page.

The possible values for CompletionStatus in the completion message are:

ok - Complete success; The data was written in its entirety.

{ok, Written} - Partial success; Some but not all data was written, but no error was reported. Written is the number of bytes that was written.

{error, Reason} - An error occured and no data was sent.

After receiving a select message; call sendto/3,4 with SelectInfo as the Cont argument, to complete the operation.

sendv(Socket, IOV)

(since OTP 27.0)

-spec sendv(Socket, IOV) -> ok | {ok, RestIOV} | {error, Reason} | {error, {Reason, RestIOV}}
               when
                   Socket :: socket(),
                   IOV :: erlang:iovec(),
                   RestIOV :: erlang:iovec(),
                   Reason :: posix() | closed | invalid().

Equivalent to sendv(Socket, IOV, infinity).

sendv/3

(since OTP 27.0)

-spec sendv(Socket, IOV, Timeout :: infinity) ->
               ok | {ok, RestIOV} | {error, Reason} | {error, {Reason, RestIOV}}
               when
                   Socket :: socket(),
                   IOV :: erlang:iovec(),
                   RestIOV :: erlang:iovec(),
                   Reason :: posix() | closed | invalid();
           (Socket, IOV, Timeout :: non_neg_integer()) ->
               ok | {ok, RestIOV} | {error, Reason} | {error, {Reason, RestIOV}}
               when
                   Socket :: socket(),
                   IOV :: erlang:iovec(),
                   RestIOV :: erlang:iovec(),
                   Reason :: posix() | closed | invalid() | timeout;
           (Socket, IOV, nowait | Handle) ->
               ok |
               {ok, RestIOV} |
               {select, SelectInfo} |
               {select, {SelectInfo, RestIOV}} |
               {completion, CompletionInfo} |
               {completion, {CompletionInfo, RestIOV}} |
               {error, Reason} |
               {error, {Reason, RestIOV}}
               when
                   Socket :: socket(),
                   IOV :: erlang:iovec(),
                   Handle :: select_handle() | completion_handle(),
                   RestIOV :: erlang:iovec(),
                   SelectInfo :: select_info(),
                   CompletionInfo :: completion_info(),
                   Reason :: posix() | closed | invalid();
           (Socket, IOV, Cont) -> ok | {ok, RestIOV} | {error, Reason} | {error, {Reason, RestIOV}}
               when
                   Socket :: socket(),
                   IOV :: erlang:iovec(),
                   Cont :: select_info(),
                   RestIOV :: erlang:iovec(),
                   Reason :: posix() | closed | invalid().

Send erlang:iovec/0 data on a connected socket.

See sendmsg/4 about how the IOV data is handled towards the platform's network layer.

The return value indicates the result from the platform's network layer:

ok - All data has been accepted by the OS for delivery.

{ok, RestIOV} - Some but not all data was accepted, but no error was reported (partially successful send). RestIOV is the tail of IOV that wasn't accepted.

{error, Reason} - An error has been reported and no data was accepted for delivery. Reason :: posix/0 is what the platform's network layer reported. closed means that this socket library was informed that the socket was closed, and invalid/0 means that this socket library found an argument to be invalid.

{error, {Reason, RestIOV}} - - An error was reported but before that some data was accepted for delivery. RestIOV is the tail of IOV that wasn't accepted. See {error, Reason} above.

If the Timeout argument is infinity; wait for the OS to complete the send operation (take responsibility for the data), or return an error.

If the Timeout argument is a time-out value (non_neg_integer/0); return {error, timeout} if no data has been sent within Timeout millisecond, or {error, {timeout, RestIOV}} if some data was sent (accepted by the OS for delivery). RestIOV is the tail of the data that hasn't been sent.

If the Handle argument is nowait, starts an asynchronous call if the operation couldn't be completed immediately.

If the Handle argument is a select_handle/0, or on Windows, the equivalent completion_handle/0, starts an asynchronous call like for nowait.

See the note Asynchronous Calls at the start of this module reference manual page.

The possible values for CompletionStatus in the completion message are:

ok - Complete success; The I/O vector was written in its entirety.

{ok, Written} - Partial success; Some but not all data was written, but no error was reported. Written is the number of bytes that was written. rest_iov(Written, IOV) can be used to calculate the rest I/O vector (from the original IOV).

{error, Reason} - An error occured and no data was sent.

With the argument Cont, equivalent to sendv(Socket, IOV, Cont, infinity).

sendv/4

(since OTP 27.0)

-spec sendv(Socket, IOV, Cont, Timeout :: infinity) ->
               ok | {ok, RestIOV} | {error, Reason} | {error, {Reason, RestIOV}}
               when
                   Socket :: socket(),
                   IOV :: erlang:iovec(),
                   Cont :: select_info(),
                   RestIOV :: erlang:iovec(),
                   Reason :: posix() | closed | invalid();
           (Socket, IOV, Cont, Timeout :: non_neg_integer()) ->
               ok | {ok, RestIOV} | {error, Reason} | {error, {Reason | RestIOV}}
               when
                   Socket :: socket(),
                   IOV :: erlang:iovec(),
                   Cont :: select_info(),
                   RestIOV :: erlang:iovec(),
                   Reason :: posix() | closed | invalid() | timeout;
           (Socket, IOV, Cont, nowait | SelectHandle) ->
               ok |
               {ok, RestIOV} |
               {select, SelectInfo} |
               {select, {SelectInfo, RestIOV}} |
               {error, Reason} |
               {error, {Reason, RestIOV}}
               when
                   Socket :: socket(),
                   IOV :: erlang:iovec(),
                   Cont :: select_info(),
                   SelectHandle :: select_handle(),
                   RestIOV :: erlang:iovec(),
                   SelectInfo :: select_info(),
                   Reason :: posix() | closed | invalid().

Send data on a connected socket, continuation.

Continues sending data on a connected socket. Cont is the SelectInfo returned from the previous sendv/2,3 call. IOV should be the rest data that wasn't sent.

See asynchronous calls about continuing unfinished calls.

See sendv/3 about the return values.

setopt/3

(since OTP 24.0)

-spec setopt(Socket, SocketOption, Value) -> ok | {error, invalid() | closed}
                when
                    Socket :: socket(),
                    SocketOption :: {Level :: otp, Opt :: otp_socket_option()},
                    Value :: dynamic();
            (Socket, SocketOption, Value) -> ok | {error, posix() | invalid() | closed}
                when Socket :: socket(), SocketOption :: socket_option(), Value :: dynamic().

Set a socket option.

Set an OS protocol level option, or an otp pseudo protocol level option. The latter level is this module's implementation level above the OS protocol levels.

See the type otp_socket_option() for a description of the otp protocol level.

See the type socket_option/0 for which OS protocol level options that this implementation knows about, how they are related to OS option names, and if there are known peculiarities with any of them.

What options that are valid depends on the OS, and on the kind of socket (domain/0,type/0 and protocol/0). See the type t:socket_option() and the socket options chapter in the User's Guide for more info.

Note

Not all options are valid, nor possible to set, on all platforms. That is, even if this socket implementation support an option; it doesn't mean that the underlying OS does.

setopt/4

(since OTP 22.0)

-spec setopt(socket(), Level :: term(), Opt :: term(), Value :: term()) -> _.

Set a socket option (backwards compatibility function).

Equivalent to setopt(Socket, {Level, Opt}, Value), or as a special case if Opt = NativeOpt :: integer/0 and Value = binary/0 equivalent to setopt_native(Socket, {Level, NativeOpt}, ValueSpec).

Use setopt/3 or setopt_native/3 instead to handle the option level and name as a single term, and to make the difference between known options and native options clear.

setopt_native(Socket, Option, Value)

(since OTP 24.0)

-spec setopt_native(Socket, Option, Value) -> ok | {error, posix() | invalid() | closed}
                       when
                           Socket :: socket(),
                           Option :: socket_option() | {Level, NativeOpt} | {NativeLevel, NativeOpt},
                           Value :: native_value(),
                           Level :: level(),
                           NativeLevel :: integer(),
                           NativeOpt :: integer().

Set a "native" socket option.

Sets a socket option that may be unknown to our implementation, or that has a type not compatible with our implementation, that is; in "native mode".

If Value is an integer/0 it will be used as a C type (int), if it is a boolean/0 it will be used as a C type (int) with the C implementations values for false or true, and if it is a binary/0 its content and size will be used as the option value.

The socket option may be specified with an ordinary socket_option/0 tuple, with a symbolic Level as {Level :: level/0,NativeOpt :: integer/0}, or with integers for both NativeLevel and NativeOpt as {NativeLevel :: integer/0,NativeOpt :: integer/0}.

If an option is valid depends both on the platform and on what kind of socket it is (domain/0, type/0 and protocol/0).

The integer values for NativeLevel and NativeOpt as well as the Value encoding has to be deduced from the header files for the running system.

shutdown(Socket, How)

(since OTP 22.0)

-spec shutdown(Socket, How) -> ok | {error, Reason}
                  when Socket :: socket(), How :: read | write | read_write, Reason :: posix() | closed.

Shut down all or part of a full-duplex connection.

sockname(Socket)

(since OTP 22.0)

-spec sockname(Socket :: socket()) -> {ok, SockAddr} | {error, Reason}
                  when SockAddr :: sockaddr_recv(), Reason :: posix() | closed.

Get the socket's address.

Returns the address to which the socket is currently bound. If the bind address had the wildcard port 0, the address returned by this function contains the ephemeral port selected by the OS.

socknames(Socket, AssocId)

(since OTP 29.0)

-spec socknames(Socket :: socket(), AssocId :: sctp_assoc_id()) -> {ok, [SockAddr]} | {error, Reason}
                   when SockAddr :: sockaddr_recv(), Reason :: posix() | closed.

Get the socket's address.

Returns all the locally bound addresses to which the socket is currently bound.

If the socket is IPv4 then all returned addresess will be IPv4. If the socket is IPv6, then the returned addresess can be a mix of IPv4 and IPv6.

For a one-to-many socket, AssocId specifies the association. For a one-to-one socket, AssocId is ignored.

If AssocId is 0 (zero), then the returned addresses are without any particular association.

supports()

(since OTP 22.0)

-spec supports() ->
                  [{Key1 :: term(),
                    boolean() | [{Key2 :: term(), boolean() | [{Key3 :: term(), boolean()}]}]}].

Retrieve information about what socket features the module and the platform supports.

Returns a list of, in no particular order, {Key1,supports(Key1)} tuples for every Key1 described in supports/1, and {Key, boolean()} tuples for each of the following keys:

sctp - SCTP support

ipv6 - IPv6 support

local - Unix Domain sockets support (AF_UNIX | AF_LOCAL)

netns - Network Namespaces support (Linux, setns(2))

sendfile - Sendfile support (sendfile(2))

supports(Key1)

(since OTP 22.0)

-spec supports(Key1 :: term()) -> [{Key2 :: term(), boolean() | [{Key3 :: term(), boolean()}]}].

Retrieve information about what socket features the module and the platform supports.

If Key1 = msg_flags returns a list of {Flag, boolean()} tuples for every Flag in msg_flag/0 with the boolean/0 indicating if the flag is supported on this platform.

If Key1 = protocols returns a list of {Name, boolean()} tuples for every Name inprotocol/0 with the boolean/0 indicating if the protocol is supported on this platform.

If Key1 = options returns a list of {SocketOption, boolean()} tuples for every SocketOption in socket_option/0 with the boolean/0 indicating if the socket option is supported on this platform.

There is no particular order of any of the returned lists.

For other values of Key1 returns []. Note that in future versions of this module or on different platforms, there might be more supported keys.

supports(Key1, Key2)

(since OTP 22.0)

-spec supports(Key1 :: term(), Key2 :: term()) -> [{Key3 :: term(), boolean()}].

Retrieve information about what socket features the module and the platform supports.

If Key1 = options, for a Key2 in level/0 returns a list of {Opt, boolean()} tuples for all known socket options Opt on that Level = Key2 with the boolean/0 indicating if the socket option is supported on this platform. See setopt/3 and getopt/2.

There is no particular order of any of the returned lists.

For other values of Key1 or Key2 returns []. Note that in future versions of this module or on different platforms, there might be more supported keys.

use_registry(D)

(since OTP 23.1)

-spec use_registry(D :: boolean()) -> ok.

Set the global use_registry option default value.

Globally change if the socket registry is to be used or not. Note that its still possible to override this explicitly when creating an individual sockets, see open/2,3,4 for more info (the Opts :: map/0).

which_sockets()

(since OTP 22.3)

-spec which_sockets() -> [socket()].

Return a list of all known sockets.

Equivalent to which_sockets(fun (_) -> true end).

which_sockets(FilterRule)

(since OTP 22.3)

-spec which_sockets(FilterRule) -> [socket()]
                       when
                           FilterRule ::
                               inet | inet6 | local | stream | dgram | seqpacket | sctp | tcp | udp |
                               pid() |
                               fun((socket_info()) -> boolean()).

Return a filtered list of known sockets.

There are several predefined FilterRules and one general:

inet | inet6 - Only the sockets with matching domain/0 are returned.

stream | dgram | seqpacket - Only the sockets with matching type/0 are returned.

sctp | tcp | udp - Only the sockets with matching protocol/0 are returned.

pid/0 - Only the sockets with matching Controlling Process are returned. See the OTP socket option controlling_process.

fun((socket_info()) -> boolean()) - The general filter rule. A fun that takes the socket info and returns a boolean/0 indicating if the socket should be returned or not.

disk_log

disk_log is a disk-based term logger that enables efficient logging of items on files.

Three types of logs are supported:

halt logs - Appends items to a single file, which size can be limited by the disk_log module.

wrap logs - Uses a sequence of wrap log files of limited size. As a wrap log file is filled up, further items are logged on to the next file in the sequence, starting all over with the first file when the last file is filled up.

rotate logs - Uses a sequence of rotate log files of limited size. As a log file is filled up, it is rotated and then compressed. There is one active log file and upto the configured number of compressed log files. Only externally formatted logs are supported. It follows the same naming convention as the handler logger_std_h for Logger. For more details about the naming convention check the file parameter for open/1.

It follows the same naming convention as that for the compressed files for Linux's logrotate and BSD's newsyslog.

For efficiency reasons, items are always written to files as binaries.

Two formats of the log files are supported:

internal format - Supports automatic repair of log files that are not properly closed and enables efficient reading of logged items in chunks using a set of functions defined in this module. This is the only way to read internally formatted logs. An item logged to an internally formatted log must not occupy more than 4 GB of disk space (the size must fit in 4 bytes).

external format - Leaves it up to the user to read and interpret the logged data. The disk_log module cannot repair externally formatted logs.

For each open disk log, one process handles requests made to the disk log. This process is created when open/1 is called, provided there exists no process handling the disk log. A process that opens a disk log can be an owner or an anonymous user of the disk log. Each owner is linked to the disk log process, and an owner can close the disk log either explicitly (by calling close/1) or by terminating.

Owners can subscribe to notifications, messages of the form {disk_log, Node, Log, Info}, which are sent from the disk log process when certain events occur, see the functions and in particular the open/1 option notify. A log can have many owners, but a process cannot own a log more than once. However, the same process can open the log as a user more than once.

For a disk log process to close its file properly and terminate, it must be closed by its owners and once by some non-owner process for each time the log was used anonymously. The users are counted and there must not be any users left when the disk log process terminates.

Items can be logged synchronously by using functions log/2, blog/2, log_terms/2, and blog_terms/2. For each of these functions, the caller is put on hold until the items are logged (but not necessarily written, use sync/1 to ensure that). By adding an a to each of the mentioned function names, we get functions that log items asynchronously. Asynchronous functions do not wait for the disk log process to write the items to the file, but return the control to the caller more or less immediately.

When using the internal format for logs, use functions log/2, log_terms/2, alog/2, and alog_terms/2. These functions log one or more Erlang terms. By prefixing each of the functions with a b (for "binary"), we get the corresponding blog() functions for the external format. These functions log one or more chunks of bytes. For example, to log the string "hello" in ASCII format, you can use disk_log:blog(Log, "hello"), or disk_log:blog(Log, list_to_binary("hello")). The two alternatives are equally efficient.

The blog() functions can also be used for internally formatted logs, but in this case they must be called with binaries constructed with calls to term_to_binary/1. There is no check to ensure this, it is entirely the responsibility of the caller. If these functions are called with binaries that do not correspond to Erlang terms, the chunk/2,3 and automatic repair functions fail. The corresponding terms (not the binaries) are returned when chunk/2,3 is called.

An open disk log is only accessible from the node where the disk log process runs. All processes on the node where the disk log process runs can log items or otherwise change, inspect, or close the log.

Errors are reported differently for asynchronous log attempts and other uses of the disk_log module. When used synchronously, this module replies with an error message, but when called asynchronously, this module does not know where to send the error message. Instead, owners subscribing to notifications receive an error_status message.

The disk_log module does not report errors to the error_logger module. It is up to the caller to decide whether to employ the error logger. Function format_error/1 can be used to produce readable messages from error replies. However, information events are sent to the error logger in two situations, namely when a log is repaired, or when a file is missing while reading chunks.

Error message no_such_log means that the specified disk log is not open. Nothing is said about whether the disk log files exist or not.

Note

If an attempt to reopen or truncate a log fails (see reopen/2,3 and truncate/1,2) the disk log process terminates immediately. Before the process terminates, links to owners and blocking processes (see block/1,2) are removed. The effect is that the links work in one direction only. Any process using a disk log must check for error message no_such_log if some other process truncates or reopens the log simultaneously.

See Also

file, wrap_log_reader

Summary

Types

bchunk_ret()

block_error_rsn()

chunk_error_rsn()

chunk_ret()

close_error_rsn()

continuation()

Chunk continuation returned by chunk/2,3, bchunk/2,3, or chunk_step/3.

dlog_format()

dlog_head_opt()

dlog_info()

dlog_mode()

dlog_optattr()

dlog_option()

dlog_options()

dlog_size()

dlog_type()

file_error()

inc_wrap_error_rsn()

invalid_header()

log()

log_error_rsn()

next_file_error_rsn()

notify_ret()

open_error_rsn()

open_ret()

reopen_error_rsn()

sync_error_rsn()

trunc_error_rsn()

unblock_error_rsn()

Functions

all()

Returns the names of the disk logs accessible on the current node.

alog(Log, Term)

Asynchronously version of log/2.

alog_terms(Log, TermList)

Asynchronously version of log_terms/2.

balog(Log, Bytes)

Asynchronously version of blog/2.

balog_terms(Log, ByteList)

Asynchronously version of blog_terms/2.

bchunk(Log, Continuation)

Equivalent to bchunk(Log, Cont, infinity).

bchunk(Log, Continuation, N)

Equivalent to chunk(Log, Continuation, N) except that it returns the binaries read from the file, that is it does not call binary_to_term/1.

block(Log)

Equivalent to block(Log, true).

block(Log, QueueLogRecords)

With a call to block/2 a process can block a log.

blog(Log, Bytes)

Equivalent to log/2 except that it is used for externally formatted logs.

blog_terms(Log, BytesList)

Equivalent to log_terms/2 except that it is used for externally formatted logs.

breopen(Log, File, BHead)

Equivalent to reopen except that it is used for externally formatted logs.

btruncate(Log, BHead)

Equivalent to truncate/2 for externally formatted logs.

change_header(Log, Header)

Changes the value of option head or head_func for an owner of a disk log.

change_notify(Log, Owner, Notify)

Changes the value of option notify for an owner of a disk log.

change_size(Log, Size)

Changes the size of an open log. For a halt log, the size can always be increased, but it cannot be decreased to something less than the current file size.

chunk(Log, Continuation)

Equivalent to chunk(Log, Continuation, infinity).

chunk(Log, Continuation, N)

Efficiently reads the terms that are appended to an internally formatted log.

chunk_info(Continuation)

Returns the pair {node, Node}, describing the chunk continuation returned by chunk/2,3, bchunk/2,3, or chunk_step/3.

chunk_step(Log, Continuation, Step)

Can be used with chunk/2,3 and bchunk/2,3 to search through an internally formatted wrap log.

close(Log)

Closes a disk log properly.

format_error(Error)

Given the error returned by any function in this module, this function returns a descriptive string of the error in English.

inc_wrap_file(Log) deprecated

Forces the internally formatted disk log to start logging to the next log file. It can be used, for example, with change_size/2 to reduce the amount of disk space allocated by the disk log.

info(Log)

Returns a list of {Tag, Value} pairs describing a log running on the node.

log(Log, Term)

Synchronously appends a term to a internally formatted disk log. Returns ok or {error, Reason} when the term is written to disk.

log_terms(Log, TermList)

Synchronously appends a list of items to an internally formatted log.

next_file(Log)

For wrap logs, it forces the disk log to start logging to the next log file. It can be used, for example, with change_size/2 to reduce the amount of disk space allocated by the disk log.

open(ArgL)

Open a new disk_log file for reading or writing.

pid2name(Pid)

Returns the log name given the pid of a disk log process on the current node, or undefined if the specified pid is not a disk log process.

reopen(Log, File)

Equivalent to reopen(Log, File, Head) where Head is the Head specified in open/1.

reopen(Log, File, Head)

Renames an internally formatted log file to File and then recreates a new log file. If a wrap/rotate log exists, File is used as the base name of the renamed files.

sync(Log)

Ensures that the contents of the log are written to the disk. This is usually a rather expensive operation.

truncate(Log)

Equivalent to truncate(Log, Head) where Head is the Head specified in open/1.

truncate(Log, Head)

Removes all items from an internally formatted disk log. The argument Head or is written first in the newly truncated log.

unblock(Log)

Unblocks a log. A log can only be unblocked by the blocking process.

Types

bchunk_ret()

(not exported)

-type bchunk_ret() ::
          {Continuation2 :: continuation(), Binaries :: [binary()]} |
          {Continuation2 :: continuation(), Binaries :: [binary()], Badbytes :: non_neg_integer()} |
          eof |
          {error, Reason :: chunk_error_rsn()}.

block_error_rsn()

(not exported)

-type block_error_rsn() :: no_such_log | nonode | {blocked_log, log()}.

chunk_error_rsn()

(not exported)

-type chunk_error_rsn() ::
          no_such_log |
          {format_external, log()} |
          {blocked_log, log()} |
          {badarg, continuation} |
          {not_internal_wrap, log()} |
          {corrupt_log_file, FileName :: file:filename()} |
          {file_error, file:filename(), file_error()}.

chunk_ret()

(not exported)

-type chunk_ret() ::
          {Continuation2 :: continuation(), Terms :: [term()]} |
          {Continuation2 :: continuation(), Terms :: [term()], Badbytes :: non_neg_integer()} |
          eof |
          {error, Reason :: chunk_error_rsn()}.

close_error_rsn()

(not exported)

-type close_error_rsn() :: no_such_log | nonode | {file_error, file:filename(), file_error()}.

continuation()

-opaque continuation()

Chunk continuation returned by chunk/2,3, bchunk/2,3, or chunk_step/3.

dlog_format()

(not exported)

-type dlog_format() :: external | internal.

dlog_head_opt()

(not exported)

-type dlog_head_opt() :: none | term() | iodata().

dlog_info()

(not exported)

-type dlog_info() ::
          {name, Log :: log()} |
          {file, File :: file:filename()} |
          {type, Type :: dlog_type()} |
          {format, Format :: dlog_format()} |
          {size, Size :: dlog_size()} |
          {mode, Mode :: dlog_mode()} |
          {owners, [{pid(), Notify :: boolean()}]} |
          {users, Users :: non_neg_integer()} |
          {status, Status :: ok | {blocked, QueueLogRecords :: boolean()}} |
          {node, Node :: node()} |
          {head, Head :: none | {head, binary()} | (MFA :: {atom(), atom(), list()})} |
          {no_written_items, NoWrittenItems :: non_neg_integer()} |
          {full, Full :: boolean} |
          {no_current_bytes, non_neg_integer()} |
          {no_current_items, non_neg_integer()} |
          {no_items, non_neg_integer()} |
          {current_file, pos_integer()} |
          {no_overflows, {SinceLogWasOpened :: non_neg_integer(), SinceLastInfo :: non_neg_integer()}}.

dlog_mode()

(not exported)

-type dlog_mode() :: read_only | read_write.

dlog_optattr()

(not exported)

-type dlog_optattr() ::
          name | file | linkto | repair | type | format | size | notify | head | head_func | mode.

dlog_option()

(not exported)

-type dlog_option() ::
          {name, Log :: log()} |
          {file, FileName :: file:filename()} |
          {linkto, LinkTo :: none | pid()} |
          {repair, Repair :: true | false | truncate} |
          {type, Type :: dlog_type()} |
          {format, Format :: dlog_format()} |
          {size, Size :: dlog_size()} |
          {notify, boolean()} |
          {head, Head :: dlog_head_opt()} |
          {head_func, MFA :: {atom(), atom(), list()}} |
          {quiet, boolean()} |
          {mode, Mode :: dlog_mode()}.

dlog_options()

(not exported)

-type dlog_options() :: [dlog_option()].

dlog_size()

(not exported)

-type dlog_size() ::
          infinity | pos_integer() | {MaxNoBytes :: pos_integer(), MaxNoFiles :: pos_integer()}.

dlog_type()

(not exported)

-type dlog_type() :: halt | wrap | rotate.

file_error()

(not exported)

-type file_error() :: term().

inc_wrap_error_rsn()

(not exported)

-type inc_wrap_error_rsn() :: next_file_error_rsn().

invalid_header()

(not exported)

-type invalid_header() :: term().

log()

(not exported)

-type log() :: term().

log_error_rsn()

(not exported)

-type log_error_rsn() ::
          no_such_log | nonode |
          {read_only_mode, log()} |
          {format_external, log()} |
          {blocked_log, log()} |
          {full, log()} |
          {invalid_header, invalid_header()} |
          {file_error, file:filename(), file_error()}.

next_file_error_rsn()

(not exported)

-type next_file_error_rsn() ::
          no_such_log | nonode |
          {read_only_mode, log()} |
          {blocked_log, log()} |
          {halt_log, log()} |
          {rotate_log, log()} |
          {invalid_header, invalid_header()} |
          {file_error, file:filename(), file_error()}.

notify_ret()

(not exported)

-type notify_ret() :: ok | {error, no_such_log}.

open_error_rsn()

(not exported)

-type open_error_rsn() ::
          no_such_log |
          {badarg, term()} |
          {size_mismatch, CurrentSize :: dlog_size(), NewSize :: dlog_size()} |
          {arg_mismatch, OptionName :: dlog_optattr(), CurrentValue :: term(), Value :: term()} |
          {name_already_open, Log :: log()} |
          {open_read_write, Log :: log()} |
          {open_read_only, Log :: log()} |
          {need_repair, Log :: log()} |
          {not_a_log_file, FileName :: file:filename()} |
          {invalid_index_file, FileName :: file:filename()} |
          {invalid_header, invalid_header()} |
          {file_error, file:filename(), file_error()} |
          {node_already_open, Log :: log()}.

open_ret()

(not exported)

-type open_ret() ::
          {ok, Log :: log()} |
          {repaired,
           Log :: log(),
           {recovered, Rec :: non_neg_integer()},
           {badbytes, Bad :: non_neg_integer()}} |
          {error, open_error_rsn()}.

reopen_error_rsn()

(not exported)

-type reopen_error_rsn() ::
          no_such_log | nonode |
          {read_only_mode, log()} |
          {blocked_log, log()} |
          {same_file_name, log()} |
          {invalid_index_file, file:filename()} |
          {invalid_header, invalid_header()} |
          {file_error, file:filename(), file_error()}.

sync_error_rsn()

(not exported)

-type sync_error_rsn() ::
          no_such_log | nonode |
          {read_only_mode, log()} |
          {blocked_log, log()} |
          {file_error, file:filename(), file_error()}.

trunc_error_rsn()

(not exported)

-type trunc_error_rsn() ::
          no_such_log | nonode |
          {read_only_mode, log()} |
          {blocked_log, log()} |
          {invalid_header, invalid_header()} |
          {file_error, file:filename(), file_error()}.

unblock_error_rsn()

(not exported)

-type unblock_error_rsn() :: no_such_log | nonode | {not_blocked, log()} | {not_blocked_by_pid, log()}.

Functions

all()

(since OTP 24.0)

-spec all() -> [Log] when Log :: log().

Returns the names of the disk logs accessible on the current node.

alog(Log, Term)

-spec alog(Log, Term) -> notify_ret() when Log :: log(), Term :: term().

Asynchronously version of log/2.

Owners subscribing to notifications receive message read_only, blocked_log, or format_external if the item cannot be written on the log, and possibly one of the messages wrap, full, or error_status if an item is written on the log. Message error_status is sent if something is wrong with the header function or if a file error occurs.

alog_terms(Log, TermList)

-spec alog_terms(Log, TermList) -> notify_ret() when Log :: log(), TermList :: [term()].

Asynchronously version of log_terms/2.

Owners subscribing to notifications receive message read_only, blocked_log, or format_external if the items cannot be written on the log, and possibly one or more of the messages wrap, full, and error_status if items are written on the log. Message error_status is sent if something is wrong with the header function or if a file error occurs.

balog(Log, Bytes)

-spec balog(Log, Bytes) -> notify_ret() when Log :: log(), Bytes :: iodata().

Asynchronously version of blog/2.

Owners subscribing to notifications receive message read_only, blocked_log, or format_external if the item cannot be written on the log, and possibly one of the messages wrap, full, or error_status if an item is written on the log. Message error_status is sent if something is wrong with the header function or if a file error occurs.

balog_terms(Log, ByteList)

-spec balog_terms(Log, ByteList) -> notify_ret() when Log :: log(), ByteList :: [iodata()].

Asynchronously version of blog_terms/2.

Owners subscribing to notifications receive message read_only, blocked_log, or format_external if the items cannot be written on the log, and possibly one or more of the messages wrap, full, and error_status if items are written on the log. Message error_status is sent if something is wrong with the header function or if a file error occurs.

bchunk(Log, Continuation)

-spec bchunk(Log, Continuation) -> bchunk_ret()
                when Log :: log(), Continuation :: start | continuation().

Equivalent to bchunk(Log, Cont, infinity).

bchunk(Log, Continuation, N)

-spec bchunk(Log, Continuation, N) -> bchunk_ret()
                when Log :: log(), Continuation :: start | continuation(), N :: pos_integer() | infinity.

Equivalent to chunk(Log, Continuation, N) except that it returns the binaries read from the file, that is it does not call binary_to_term/1.

block(Log)

-spec block(Log) -> ok | {error, block_error_rsn()} when Log :: log().

Equivalent to block(Log, true).

block(Log, QueueLogRecords)

-spec block(Log, QueueLogRecords) -> ok | {error, block_error_rsn()}
               when Log :: log(), QueueLogRecords :: boolean().

With a call to block/2 a process can block a log.

If the blocking process is not an owner of the log, a temporary link is created between the disk log process and the blocking process. The link ensures that the disk log is unblocked if the blocking process terminates without first closing or unblocking the log.

Any process can probe a blocked log with info/1 or close it with close/1. The blocking process can also use functions chunk/2,3, bchunk/2,3, chunk_step/3, and unblock/1 without being affected by the block. Any other attempt than those mentioned so far to update or read a blocked log suspends the calling process until the log is unblocked or returns error message {blocked_log, Log}, depending on whether the value of QueueLogRecords is true or false.

blog(Log, Bytes)

-spec blog(Log, Bytes) -> ok | {error, Reason :: log_error_rsn()} when Log :: log(), Bytes :: iodata().

Equivalent to log/2 except that it is used for externally formatted logs.

blog/2 can also be used for internally formatted logs if the binaries are constructed with calls to term_to_binary/1.

blog_terms(Log, BytesList)

-spec blog_terms(Log, BytesList) -> ok | {error, Reason :: log_error_rsn()}
                    when Log :: log(), BytesList :: [iodata()].

Equivalent to log_terms/2 except that it is used for externally formatted logs.

blog_terms/2 can also be used for internally formatted logs if the binaries are constructed with calls to term_to_binary/1.

breopen(Log, File, BHead)

-spec breopen(Log, File, BHead) -> ok | {error, reopen_error_rsn()}
                 when Log :: log(), File :: file:filename(), BHead :: iodata().

Equivalent to reopen except that it is used for externally formatted logs.

btruncate(Log, BHead)

-spec btruncate(Log, BHead) -> ok | {error, trunc_error_rsn()} when Log :: log(), BHead :: iodata().

Equivalent to truncate/2 for externally formatted logs.

change_header(Log, Header)

-spec change_header(Log, Header) -> ok | {error, Reason}
                       when
                           Log :: log(),
                           Header ::
                               {head, dlog_head_opt()} | {head_func, MFA :: {atom(), atom(), list()}},
                           Reason ::
                               no_such_log | nonode |
                               {read_only_mode, Log} |
                               {blocked_log, Log} |
                               {badarg, head}.

Changes the value of option head or head_func for an owner of a disk log.

change_notify(Log, Owner, Notify)

-spec change_notify(Log, Owner, Notify) -> ok | {error, Reason}
                       when
                           Log :: log(),
                           Owner :: pid(),
                           Notify :: boolean(),
                           Reason ::
                               no_such_log | nonode |
                               {blocked_log, Log} |
                               {badarg, notify} |
                               {not_owner, Owner}.

Changes the value of option notify for an owner of a disk log.

change_size(Log, Size)

-spec change_size(Log, Size) -> ok | {error, Reason}
                     when
                         Log :: log(),
                         Size :: dlog_size(),
                         Reason ::
                             no_such_log | nonode |
                             {read_only_mode, Log} |
                             {blocked_log, Log} |
                             {new_size_too_small, Log, CurrentSize :: pos_integer()} |
                             {badarg, size} |
                             {file_error, file:filename(), file_error()}.

Changes the size of an open log. For a halt log, the size can always be increased, but it cannot be decreased to something less than the current file size.

For a wrap or rotate log, both the size and the number of files can always be increased, as long as the number of files does not exceed 65000. For wrap logs, if the maximum number of files is decreased, the change is not valid until the current file is full and the log wraps to the next file. The redundant files are removed the next time the log wraps around, that is, starts to log to file number 1.

As an example, assume that the old maximum number of files is 10 and that the new maximum number of files is 6. If the current file number is not greater than the new maximum number of files, files 7-10 are removed when file 6 is full and the log starts to write to file number 1 again. Otherwise, the files greater than the current file are removed when the current file is full (for example, if the current file is 8, files 9 and 10 are removed). The files between the new maximum number of files and the current file (that is, files 7 and 8) are removed the next time file 6 is full.

For rotate logs, if the maximum number of files is decreased, the redundant files are deleted instantly.

If the size of the files is decreased, the change immediately affects the current log. It does not change the size of log files already full until the next time they are used.

If the log size is decreased, for example, to save space, function next_file/1, can be used to force the log to wrap.

chunk(Log, Continuation)

-spec chunk(Log, Continuation) -> chunk_ret() when Log :: log(), Continuation :: start | continuation().

Equivalent to chunk(Log, Continuation, infinity).

chunk(Log, Continuation, N)

-spec chunk(Log, Continuation, N) -> chunk_ret()
               when Log :: log(), Continuation :: start | continuation(), N :: pos_integer() | infinity.

Efficiently reads the terms that are appended to an internally formatted log.

It minimizes disk I/O by reading 64 kilobyte chunks from the file.

The first time chunk() is called, an initial continuation, the atom start, must be provided.

When chunk/3 is called, N controls the maximum number of terms that are read from the log in each chunk. infinity means that all the terms contained in the 64 kilobyte chunk are read. If less than N terms are returned, this does not necessarily mean that the end of the file is reached.

chunk/3 returns a tuple {Continuation2, Terms}, where Terms is a list of terms found in the log. Continuation2 is yet another continuation, which must be passed on to any subsequent calls to chunk(). With a series of calls to chunk(), all terms from a log can be extracted.

chunk/3 returns a tuple {Continuation2, Terms, Badbytes} if the log is opened in read-only mode and the read chunk is corrupt. Badbytes is the number of bytes in the file found not to be Erlang terms in the chunk. Notice that the log is not repaired. When trying to read chunks from a log opened in read-write mode, tuple {corrupt_log_file, FileName} is returned if the read chunk is corrupt.

chunk/3 returns eof when the end of the log is reached, or {error, Reason} if an error occurs. If a wrap log file is missing, a message is output on the error log.

When chunk/2,3 is used with wrap logs, the returned continuation might not be valid in the next call to chunk/3. This is because the log can wrap and delete the file into which the continuation points. To prevent this, the log can be blocked during the search.

chunk_info(Continuation)

-spec chunk_info(Continuation) -> InfoList | {error, Reason}
                    when
                        Continuation :: continuation(),
                        InfoList :: [{node, Node :: node()}, ...],
                        Reason :: {no_continuation, Continuation}.

Returns the pair {node, Node}, describing the chunk continuation returned by chunk/2,3, bchunk/2,3, or chunk_step/3.

Terms are read from the disk log running on Node.

chunk_step(Log, Continuation, Step)

-spec chunk_step(Log, Continuation, Step) -> {ok, any()} | {error, Reason}
                    when
                        Log :: log(),
                        Continuation :: start | continuation(),
                        Step :: integer(),
                        Reason ::
                            no_such_log | end_of_log |
                            {format_external, Log} |
                            {blocked_log, Log} |
                            {badarg, continuation} |
                            {file_error, file:filename(), file_error()}.

Can be used with chunk/2,3 and bchunk/2,3 to search through an internally formatted wrap log.

It takes as argument a continuation as returned by chunk/2,3, bchunk/2,3, or chunk_step/3, and steps forward (or backward) Step files in the wrap log. The continuation returned, points to the first log item in the new current file.

If atom start is specified as continuation, the first file of the wrap log is chosen as the new current file.

If the wrap log is not full because all files are not yet used, {error, end_of_log} is returned if trying to step outside the log.

close(Log)

-spec close(Log) -> ok | {error, close_error_rsn()} when Log :: log().

Closes a disk log properly.

An internally formatted log must be closed before the Erlang system is stopped. Otherwise, the log is regarded as unclosed and the automatic repair procedure is activated next time the log is opened.

The disk log process is not terminated as long as there are owners or users of the log. All owners must close the log, possibly by terminating. Also, any other process, not only the processes that have opened the log anonymously, can decrement the users counter by closing the log. Attempts to close a log by a process that is not an owner are ignored if there are no users.

If the log is blocked by the closing process, the log is also unblocked.

format_error(Error)

-spec format_error(Error) -> io_lib:chars() when Error :: term().

Given the error returned by any function in this module, this function returns a descriptive string of the error in English.

For file errors, function format_error/1 in module file is called.

inc_wrap_file(Log)

This function is deprecated. disk_log:inc_wrap_file/1 is deprecated; use disk_log:next_file/1 instead.

-spec inc_wrap_file(Log) -> ok | {error, inc_wrap_error_rsn()} when Log :: log().

Forces the internally formatted disk log to start logging to the next log file. It can be used, for example, with change_size/2 to reduce the amount of disk space allocated by the disk log.

Owners subscribing to notifications normally receive a wrap message, but if an error occurs with a reason tag of invalid_header or file_error, an error_status message is sent.

info(Log)

-spec info(Log) -> InfoList | {error, no_such_log} when Log :: log(), InfoList :: [dlog_info()].

Returns a list of {Tag, Value} pairs describing a log running on the node.

The following pairs are returned for all logs:

{name, Log} - Log is the log name as specified by the open/1 option name.

{file, File} - For halt logs File is the filename, and for wrap logs File is the base name.

{type, Type} - Type is the log type as specified by the open/1 option type.

{format, Format} - Format is the log format as specified by the open/1 option format.

{size, Size} - Size is the log size as specified by the open/1 option size, or the size set by change_size/2. The value set by change_size/2 is reflected immediately.

{mode, Mode} - Mode is the log mode as specified by the open/1 option mode.

{owners, [{pid(), Notify}]} - Notify is the value set by the open/1 option notify or function change_notify/3 for the owners of the log.

{users, Users} - Users is the number of anonymous users of the log, see the open/1 option linkto.

{status, Status} - Status is ok or {blocked, QueueLogRecords} as set by functions block/1,2 and unblock/1.

{node, Node} - The information returned by the current invocation of function info/1 is gathered from the disk log process running on Node.

The following pairs are returned for all logs opened in read_write mode:

{head, Head} - Depending on the value of the open/1 options head and head_func, or set by function change_header/2, the value of Head is none (default), {head, H} (head option), or {M,F,A} (head_func option).

{no_written_items, NoWrittenItems} - NoWrittenItems is the number of items written to the log since the disk log process was created.

The following pair is returned for halt logs opened in read_write mode:

{full, Full} - Full is true or false depending on whether the halt log is full or not.

The following pairs are returned for wrap logs opened in read_write mode:

{no_current_bytes, integer() >= 0} - The number of bytes written to the current wrap log file.

{no_current_items, integer() >= 0} - The number of items written to the current wrap log file, header inclusive.

{no_items, integer() >= 0} - The total number of items in all wrap log files.

{current_file, integer()} - The ordinal for the current wrap log file in the range 1..MaxNoFiles, where MaxNoFiles is specified by the open/1 option size or set by change_size/2.

{no_overflows, {SinceLogWasOpened, SinceLastInfo}} - SinceLogWasOpened (SinceLastInfo) is the number of times a wrap log file has been filled up and a new one is opened or inc_wrap_file/1 has been called since the disk log was last opened (info/1 was last called). The first time info/2 is called after a log was (re)opened or truncated, the two values are equal.

Notice that functions chunk/2,3, bchunk/2,3, and chunk_step/3 do not affect any value returned by info/1.

log(Log, Term)

-spec log(Log, Term) -> ok | {error, Reason :: log_error_rsn()} when Log :: log(), Term :: term().

Synchronously appends a term to a internally formatted disk log. Returns ok or {error, Reason} when the term is written to disk.

Terms are written by the ordinary write() function of the operating system. Hence, it is not guaranteed that the term is written to disk, it can linger in the operating system kernel for a while. To ensure that the item is written to disk, function sync/1 must be called.

Owners subscribing to notifications are notified of an error with an error_status message if the error reason tag is invalid_header or file_error.

log_terms(Log, TermList)

-spec log_terms(Log, TermList) -> ok | {error, Reason :: log_error_rsn()}
                   when Log :: log(), TermList :: [term()].

Synchronously appends a list of items to an internally formatted log.

It is more efficient to use this functions instead of log/2. The specified list is split into as large sublists as possible (limited by the size of wrap log files), and each sublist is logged as one single item, which reduces the overhead.

Owners subscribing to notifications are notified of an error with an error_status message if the error reason tag is invalid_header or file_error.

next_file(Log)

(since OTP 26.0)

-spec next_file(Log) -> ok | {error, next_file_error_rsn()} when Log :: log().

For wrap logs, it forces the disk log to start logging to the next log file. It can be used, for example, with change_size/2 to reduce the amount of disk space allocated by the disk log.

Owners subscribing to notifications normally receive a wrap message, but if an error occurs with a reason tag of invalid_header or file_error, an error_status message is sent.

For rotate logs, it forces rotation of the currently active log file, compresses it and opens a new active file for logging.

open(ArgL)

-spec open(ArgL) -> open_ret() when ArgL :: dlog_options().

Open a new disk_log file for reading or writing.

Parameter ArgL is a list of the following options:

{name, Log} - Specifies the log name. This name must be passed on as a parameter in all subsequent logging operations. A name must always be supplied.

{file, FileName} - Specifies the name of the file to be used for logged terms. If this value is omitted and the log name is an atom or a string, the filename defaults to lists:concat([Log, ".LOG"]) for halt logs.

For wrap logs, this is the base name of the files. Each file in a wrap log is called <FileName>.N, where N is an integer. Each wrap log also has two files called <FileName>.idx and <FileName>.siz.

For rotate logs, this is the name of the active log file. The compressed files are named as <FileName>.N.gz, where N is an integer and <FileName>.0.gz is the latest compressed log file. All the compressed files are renamed at each rotation so that the latest files have the smallest index. The maximum value for N is the value of MaxNoFiles minus 1.

{linkto, LinkTo}
If LinkTo is a pid, it becomes an owner of the log. If LinkTo is none, the log records that it is used anonymously by some process by incrementing the users counter. By default, the process that calls open/1 owns the log.

{repair, Repair} - If Repair is true, the current log file is repaired, if needed. As the restoration is initiated, a message is output on the error log. If false is specified, no automatic repair is attempted. Instead, the tuple {error, {need_repair, Log}} is returned if an attempt is made to open a corrupt log file. If truncate is specified, the log file becomes truncated, creating an empty log, regardless of previous content. Defaults to true, which has no effect on logs opened in read-only mode.

{type, Type} - The log type. Defaults to halt.

{format, Format} - Disk log format. Defaults to internal.

{size, Size} - Log size.

When a halt log has reached its maximum size, all attempts to log more items are rejected. Defaults to infinity, which for halt implies that there is no maximum size.

For wrap and rotate logs, parameter Size can be a pair {MaxNoBytes, MaxNoFiles}. For wrap logs it can also be infinity. In the latter case, if the files of an existing wrap log with the same name can be found, the size is read from the existing wrap log, otherwise an error is returned.

Wrap logs write at most MaxNoBytes bytes on each file and use MaxNoFiles files before starting all over with the first wrap log file. Regardless of MaxNoBytes, at least the header (if there is one) and one item are written on each wrap log file before wrapping to the next file.

The first time an existing wrap log is opened, that is, when the disk log process is created, the value of the option size is allowed to differ from the current log size, and the size of the disk log is changed as per change_size/2.

When opening an existing wrap log, it is not necessary to supply a value for option size, but if the log is already open, that is, the disk log process exists, the supplied value must equal the current log size, otherwise the tuple {error, {size_mismatch, CurrentSize, NewSize}} is returned.

Note

Before Erlang/OTP 24.0, the supplied value of option size was to be equal to the current log size when opening an existing wrap log for the first time, that is, when creating the disk log process.

Rotate logs write at most MaxNoBytes bytes on the active log file and keep the latest MaxNoFiles compressed files. Regardless of MaxNoBytes, at least the header (if there is one) and one item are written on each rotate log file before rotation.

When opening an already open halt log, option size is ignored.

{notify, boolean()} - If true, the log owners are notified when certain log events occur. Defaults to false. The owners are sent one of the following messages when an event occurs:

{disk_log, Node, Log, {wrap, NoLostItems}} - Sent when a wrap log has filled up one of its files and a new file is opened. NoLostItems is the number of previously logged items that were lost when truncating existing files.

{disk_log, Node, Log, {truncated, NoLostItems}} - Sent when a log is truncated or reopened. For halt logs NoLostItems is the number of items written on the log since the disk log process was created. For wrap logs NoLostItems is the number of items on all wrap log files.

{disk_log, Node, Log, {read_only, Items}} - Sent when an asynchronous log attempt is made to a log file opened in read-only mode. Items is the items from the log attempt.

{disk_log, Node, Log, {blocked_log, Items}} - Sent when an asynchronous log attempt is made to a blocked log that does not queue log attempts. Items is the items from the log attempt.

{disk_log, Node, Log, {format_external, Items}} - Sent when function alog/2 or alog_terms/2 is used for internally formatted logs. Items is the items from the log attempt.

{disk_log, Node, Log, full} - Sent when an attempt to log items to a wrap log would write more bytes than the limit set by option size.

{disk_log, Node, Log, {error_status, Status}} - Sent when the error status changes. The error status is defined by the outcome of the last attempt to log items to the log, or to truncate the log, or the last use of function sync/1, inc_wrap_file/1, or change_size/2. Status is either ok or {error, Error}, the former is the initial value.

{head, Head} - Specifies a header to be written first on the log file. If the log is a wrap or rotate log, the item Head is written first in each new file. Head is to be a term if the format is internal, otherwise an iodata/0. Defaults to none, which means that no header is written first on the file.

{head_func, {M,F,A}} - Specifies a function to be called each time a new log file is opened. The call M:F(A) is assumed to return {ok, Head}. The item Head is written first in each file. Head is to be a term if the format is internal, otherwise an iodata/0.

{mode, Mode} - Specifies if the log is to be opened in read-only or read-write mode. Defaults to read_write.

{quiet, Boolean} - Specifies if messages will be sent to error_logger on recoverable errors with the log files. Defaults to false.

open/1 returns {ok, Log} if the log file is successfully opened. If the file is successfully repaired, the tuple {repaired, Log, {recovered, Rec}, {badbytes, Bad}} is returned, where Rec is the number of whole Erlang terms found in the file and Bad is the number of bytes in the file that are non-Erlang terms.

When a disk log is opened in read-write mode, any existing log file is checked for. If there is none, a new empty log is created, otherwise the existing file is opened at the position after the last logged item, and the logging of items starts from there. If the format is internal and the existing file is not recognized as an internally formatted log, a tuple {error, {not_a_log_file, FileName}} is returned.

open/1 cannot be used for changing the values of options of an open log. When there are prior owners or users of a log, all option values except name, linkto, and notify are only checked against the values supplied before as option values to function open/1, change_header/2, change_notify/3, or change_size/2. Thus, none of the options except name is mandatory. If some specified value differs from the current value, a tuple {error, {arg_mismatch, OptionName, CurrentValue, Value}} is returned.

Note

If an owner attempts to open a log as owner once again, it is acknowledged with the return value {ok, Log}, but the state of the disk log is not affected.

A log file can be opened more than once by giving different values to option name or by using the same file when opening a log on different nodes. It is up to the user of module disk_log to ensure that not more than one disk log process has write access to any file, otherwise the file can be corrupted.

If an attempt to open a log file for the first time fails, the disk log process terminates with the EXIT message {{failed,Reason},[{disk_log,open,1}]}. The function returns {error, Reason} for all other errors.

pid2name(Pid)

-spec pid2name(Pid) -> {ok, Log} | undefined when Pid :: pid(), Log :: log().

Returns the log name given the pid of a disk log process on the current node, or undefined if the specified pid is not a disk log process.

This function is meant to be used for debugging only.

reopen(Log, File)

-spec reopen(Log, File) -> ok | {error, reopen_error_rsn()} when Log :: log(), File :: file:filename().

Equivalent to reopen(Log, File, Head) where Head is the Head specified in open/1.

reopen(Log, File, Head)

-spec reopen(Log, File, Head) -> ok | {error, reopen_error_rsn()}
                when Log :: log(), File :: file:filename(), Head :: term().

Renames an internally formatted log file to File and then recreates a new log file. If a wrap/rotate log exists, File is used as the base name of the renamed files.

Writes the value of Head first in the newly opened log file. The header argument is used only once. Next time a wrap/rotate log file is opened, the header given to open/1 is used.

Owners subscribing to notifications receive a truncate message.

Upon failure to reopen the log, the disk log process terminates with the EXIT message {{failed,Error},[{disk_log,Fun,Arity}]}. Other processes having requests queued receive the message {disk_log, Node, {error, disk_log_stopped}}.

sync(Log)

-spec sync(Log) -> ok | {error, sync_error_rsn()} when Log :: log().

Ensures that the contents of the log are written to the disk. This is usually a rather expensive operation.

truncate(Log)

-spec truncate(Log) -> ok | {error, trunc_error_rsn()} when Log :: log().

Equivalent to truncate(Log, Head) where Head is the Head specified in open/1.

This function can be used for both internally and externally formatted logs.

truncate(Log, Head)

-spec truncate(Log, Head) -> ok | {error, trunc_error_rsn()} when Log :: log(), Head :: term().

Removes all items from an internally formatted disk log. The argument Head or is written first in the newly truncated log.

The header argument is used only once. Next time a wrap/rotate log file is opened, the header given to open/1 is used.

Owners subscribing to notifications receive a truncate message.

If the attempt to truncate the log fails, the disk log process terminates with the EXIT message {{failed,Reason},[{disk_log,Fun,Arity}]}. Other processes having requests queued receive the message {disk_log, Node, {error, disk_log_stopped}}.

unblock(Log)

-spec unblock(Log) -> ok | {error, unblock_error_rsn()} when Log :: log().

Unblocks a log. A log can only be unblocked by the blocking process.

error_logger

Erlang error logger.

Note

In Erlang/OTP 21.0, a new API for logging was added. The old error_logger module can still be used by legacy code, but log events are redirected to the new Logger API. New code should use the Logger API directly.

error_logger is no longer started by default, but is automatically started when an event handler is added with error_logger:add_report_handler/1,2. The error_logger module is then also added as a handler to the new logger.

See logger and the Logging chapter in the User's Guide for more information.

The Erlang error logger is an event manager (see OTP Design Principles and gen_event), registered as error_logger.

Error logger is no longer started by default, but is automatically started when an event handler is added with add_report_handler/1,2. The error_logger module is then also added as a handler to the new logger, causing log events to be forwarded from logger to error logger, and consequently to all installed error logger event handlers.

User-defined event handlers can be added to handle application-specific events.

Existing event handlers provided by STDLIB and SASL are still available, but are no longer used by OTP.

Warning events were introduced in Erlang/OTP R9C and are enabled by default as from Erlang/OTP 18.0. To retain backwards compatibility with existing user-defined event handlers, the warning events can be tagged as errors or info using command-line flag +W <e | i | w>, thus showing up as ERROR REPORT or INFO REPORT in the logs.

Events

All event handlers added to the error logger must handle the following events. Gleader is the group leader pid of the process that sent the event, and Pid is the process that sent the event.

{error, Gleader, {Pid, Format, Data}} - Generated when error_msg/1,2 or format/2 is called.

{error_report, Gleader, {Pid, std_error, Report}} - Generated when error_report/1 is called.

{error_report, Gleader, {Pid, Type, Report}} - Generated when error_report/2 is called.

{warning_msg, Gleader, {Pid, Format, Data}} - Generated when warning_msg/1,2 is called if warnings are set to be tagged as warnings.

{warning_report, Gleader, {Pid, std_warning, Report}} - Generated when warning_report/1 is called if warnings are set to be tagged as warnings.

{warning_report, Gleader, {Pid, Type, Report}} - Generated when warning_report/2 is called if warnings are set to be tagged as warnings.

{info_msg, Gleader, {Pid, Format, Data}} - Generated when info_msg/1,2 is called.

{info_report, Gleader, {Pid, std_info, Report}} - Generated when info_report/1 is called.

{info_report, Gleader, {Pid, Type, Report}} - Generated when info_report/2 is called.

Notice that some system-internal events can also be received. Therefore a catch-all clause last in the definition of the event handler callback function gen_event:handle_event/2 is necessary. This also applies for gen_event:handle_info/2, as the event handler must also take care of some system-internal messages.

See Also

gen_event, logger, log_mf_h, kernel, sasl

Summary

Types

open_error()

report()

Functions

add_report_handler(Handler)

Equivalent to add_report_handler(Handler, []).

add_report_handler(Handler, Args)

Adds a new event handler to the error logger. The event handler must be implemented as a gen_event callback module.

delete_report_handler(Handler)

Deletes an event handler from the error logger by calling gen_event:delete_handler(error_logger, Handler, []).

error_msg(Format)

Equivalent to error_msg(Format, []).

error_msg(Format, Data)

Log a standard error event. The Format and Data arguments are the same as the arguments of io:format/2 in STDLIB.

error_report(Report)

Log a standard error event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

error_report(Type, Report)

Log a user-defined error event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

format(Format, Data)

Equivalent to error_msg(Format, Data).

get_format_depth()

Returns max(10, Depth), where Depth is the value of error_logger_format_depth in the Kernel application, if Depth is an integer. Otherwise, unlimited is returned.

info_msg(Format)

Equivalent to info_msg(Format, []).

info_msg(Format, Data)

Log a standard information event. The Format and Data arguments are the same as the arguments of io:format/2 in STDLIB.

info_report(Report)

Log a standard information event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

info_report(Type, Report)

Log a user-defined information event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

logfile/1

Enables or disables printout of standard events to a file.

tty(Flag)

Enables (Flag == true) or disables (Flag == false) printout of standard events to the terminal.

warning_map()

Returns the current mapping for warning events.

warning_msg(Format)

Equivalent to warning_msg(Format, []).

warning_msg(Format, Data)

Log a standard warning event. The Format and Data arguments are the same as the arguments of io:format/2 in STDLIB.

warning_report(Report)

Log a standard warning event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

warning_report(Type, Report)

Log a user-defined warning event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

Types

open_error()

(not exported)

-type open_error() :: file:posix() | badarg | system_limit.

report()

(not exported)

-type report() :: [{Tag :: term(), Data :: term()} | term()] | string() | term().

Functions

add_report_handler(Handler)

-spec add_report_handler(Handler) -> any() when Handler :: module().

Equivalent to add_report_handler(Handler, []).

add_report_handler(Handler, Args)

-spec add_report_handler(Handler, Args) -> Result
                            when
                                Handler :: module(),
                                Args :: gen_event:handler_args(),
                                Result :: gen_event:add_handler_ret().

Adds a new event handler to the error logger. The event handler must be implemented as a gen_event callback module.

Handler is typically the name of the callback module and Args is an optional term (defaults to []) passed to the initialization callback function gen_event:init/1. The function returns ok if successful.

The event handler must be able to handle the events in this module, see section Events.

The first time this function is called, error_logger is added as a Logger handler, and the error_logger process is started.

delete_report_handler(Handler)

-spec delete_report_handler(Handler) -> Result
                               when Handler :: module(), Result :: gen_event:del_handler_ret().

Deletes an event handler from the error logger by calling gen_event:delete_handler(error_logger, Handler, []).

If no more event handlers exist after the deletion, error_logger is removed as a Logger handler, and the error_logger process is stopped.

error_msg(Format)

-spec error_msg(Format) -> ok when Format :: string().

Equivalent to error_msg(Format, []).

error_msg(Format, Data)

-spec error_msg(Format, Data) -> ok when Format :: string(), Data :: list().

Log a standard error event. The Format and Data arguments are the same as the arguments of io:format/2 in STDLIB.

Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler.

This function is kept for backwards compatibility and must not be used by new code. Use the ?LOG_ERROR macro or logger:error/1,2,3 instead.

Example:

1> error_logger:error_msg("An error occurred in ~p", [a_module]).
=ERROR REPORT==== 22-May-2018::11:18:43.376917 ===
An error occurred in a_module
ok

Warning

If the Unicode translation modifier (t) is used in the format string, all event handlers must ensure that the formatted output is correctly encoded for the I/O device.

error_report(Report)

-spec error_report(Report) -> ok when Report :: report().

Log a standard error event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler.

This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_ERROR macro or logger:error/1,2,3 instead.

Example:

2> error_logger:error_report([{tag1,data1},a_term,{tag2,data}]).
=ERROR REPORT==== 22-May-2018::11:24:23.699306 ===
    tag1: data1
    a_term
    tag2: data
ok
3> error_logger:error_report("Serious error in my module").
=ERROR REPORT==== 22-May-2018::11:24:45.972445 ===
Serious error in my module
ok

error_report(Type, Report)

-spec error_report(Type, Report) -> ok when Type :: term(), Report :: report().

Log a user-defined error event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

Error logger also adds a domain field with value [Type] to this event's metadata, causing the filters of the default Logger handler to discard the event. A different Logger handler, or an error logger event handler, must be added to handle this event.

It is recommended that Report follows the same structure as for error_report/1.

This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_ERROR macro or logger:error/1,2,3 instead.

format(Format, Data)

-spec format(Format, Data) -> ok when Format :: string(), Data :: list().

Equivalent to error_msg(Format, Data).

get_format_depth()

(since OTP 20.0)

-spec get_format_depth() -> unlimited | pos_integer().

Returns max(10, Depth), where Depth is the value of error_logger_format_depth in the Kernel application, if Depth is an integer. Otherwise, unlimited is returned.

Note

The error_logger_format_depth variable is deprecated since the Logger API was introduced in Erlang/OTP 21.0. The variable, and this function, are kept for backwards compatibility since they still might be used by legacy report handlers.

info_msg(Format)

-spec info_msg(Format) -> ok when Format :: string().

Equivalent to info_msg(Format, []).

info_msg(Format, Data)

-spec info_msg(Format, Data) -> ok when Format :: string(), Data :: list().

Log a standard information event. The Format and Data arguments are the same as the arguments of io:format/2 in STDLIB.

Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler.

These functions are kept for backwards compatibility and must not be used by new code. Use the ?LOG_INFO macro or logger:info/1,2,3 instead.

Example:

1> error_logger:info_msg("Something happened in ~p", [a_module]).
=INFO REPORT==== 22-May-2018::12:03:32.612462 ===
Something happened in a_module
ok

Warning

If the Unicode translation modifier (t) is used in the format string, all event handlers must ensure that the formatted output is correctly encoded for the I/O device.

info_report(Report)

-spec info_report(Report) -> ok when Report :: report().

Log a standard information event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler.

This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_INFO macro or logger:info/1,2,3 instead.

Example:

2> error_logger:info_report([{tag1,data1},a_term,{tag2,data}]).
=INFO REPORT==== 22-May-2018::12:06:35.994440 ===
    tag1: data1
    a_term
    tag2: data
ok
3> error_logger:info_report("Something strange happened").
=INFO REPORT==== 22-May-2018::12:06:49.066872 ===
Something strange happened
ok

info_report(Type, Report)

-spec info_report(Type, Report) -> ok when Type :: any(), Report :: report().

Log a user-defined information event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

Error logger also adds a domain field with value [Type] to this event's metadata, causing the filters of the default Logger handler to discard the event. A different Logger handler, or an error logger event handler, must be added to handle this event.

It is recommended that Report follows the same structure as for info_report/1.

This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_INFO macro or logger:info/1,2,3 instead.

logfile/1

-spec logfile(Request :: {open, Filename}) -> ok | {error, OpenReason}
                 when Filename :: file:name(), OpenReason :: allready_have_logfile | open_error();
             (Request :: close) -> ok | {error, CloseReason} when CloseReason :: module_not_found;
             (Request :: filename) -> Filename | {error, FilenameReason}
                 when Filename :: file:name(), FilenameReason :: no_log_file.

Enables or disables printout of standard events to a file.

This is done by adding or deleting the error_logger_file_h event handler, and thus indirectly adding error_logger as a Logger handler.

Notice that this function does not manipulate the Logger configuration directly, meaning that if the default Logger handler is already logging to a file, this function can potentially cause logging to a second file.

This function is useful as a shortcut during development and testing, but must not be used in a production system. See section Logging in the Kernel User's Guide, and the logger manual page for information about how to configure Logger for live systems.

Request is one of the following:

{open, Filename} - Opens log file Filename. Returns ok if successful, or {error, allready_have_logfile} if logging to file is already enabled, or an error tuple if another error occurred (for example, if Filename cannot be opened). The file is opened with encoding UTF-8.

close - Closes the current log file. Returns ok, or {error, module_not_found}.

filename - Returns the name of the log file Filename, or {error, no_log_file} if logging to file is not enabled.

tty(Flag)

-spec tty(Flag) -> ok when Flag :: boolean().

Enables (Flag == true) or disables (Flag == false) printout of standard events to the terminal.

This is done by manipulating the Logger configuration. The function is useful as a shortcut during development and testing, but must not be used in a production system. See section Logging in the Kernel User's Guide, and the logger manual page for information about how to configure Logger for live systems.

warning_map()

-spec warning_map() -> Tag when Tag :: error | warning | info.

Returns the current mapping for warning events.

Events sent using warning_msg/1,2 or warning_report/1,2 are tagged as errors, warnings (default), or info, depending on the value of command-line flag +W.

Example:

os$ erl
Erlang (BEAM) emulator version 5.4.8 [hipe] [threads:0] [kernel-poll]

Eshell V5.4.8  (abort with ^G)
1> error_logger:warning_map().
warning
2> error_logger:warning_msg("Warnings tagged as: ~p~n", [warning]).

=WARNING REPORT==== 11-Aug-2005::15:31:55 ===
Warnings tagged as: warning
ok
3>
User switch command
 --> q
os$ erl +W e
Erlang (BEAM) emulator version 5.4.8 [hipe] [threads:0] [kernel-poll]

Eshell V5.4.8  (abort with ^G)
1> error_logger:warning_map().
error
2> error_logger:warning_msg("Warnings tagged as: ~p~n", [error]).

=ERROR REPORT==== 11-Aug-2005::15:31:23 ===
Warnings tagged as: error
ok

warning_msg(Format)

-spec warning_msg(Format) -> ok when Format :: string().

Equivalent to warning_msg(Format, []).

warning_msg(Format, Data)

-spec warning_msg(Format, Data) -> ok when Format :: string(), Data :: list().

Log a standard warning event. The Format and Data arguments are the same as the arguments of io:format/2 in STDLIB.

Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler. The log level can be changed to error or info, see warning_map/0.

These functions are kept for backwards compatibility and must not be used by new code. Use the ?LOG_WARNING macro or logger:warning/1,2,3 instead.

Warning

If the Unicode translation modifier (t) is used in the format string, all event handlers must ensure that the formatted output is correctly encoded for the I/O device.

warning_report(Report)

-spec warning_report(Report) -> ok when Report :: report().

Log a standard warning event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler. The log level can be changed to error or info, see warning_map/0.

This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_WARNING macro or logger:warning/1,2,3 instead.

warning_report(Type, Report)

-spec warning_report(Type, Report) -> ok when Type :: any(), Report :: report().

Log a user-defined warning event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

Error logger also adds a domain field with value [Type] to this event's metadata, causing the filters of the default Logger handler to discard the event. A different Logger handler, or an error logger event handler, must be added to handle this event.

The log level can be changed to error or info, see warning_map/0.

It is recommended that Report follows the same structure as for warning_report/1.

This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_WARNING macro or logger:warning/1,2,3 instead.

logger

API module for Logger, the standard logging facility in Erlang/OTP.

This module implements the main API for logging in Erlang/OTP. To create a log event, use the API functions or the log macros, for example:

?LOG_ERROR("error happened because: ~p", [Reason]).   % With macro
logger:error("error happened because: ~p", [Reason]). % Without macro

To configure the Logger backend, use Kernel configuration parameters or configuration functions in the logger API.

By default, the Kernel application installs one log handler at system start. This handler is named default. It receives and processes standard log events produced by the Erlang runtime system, standard behaviours and different Erlang/OTP applications. The log events are by default printed to the terminal.

If you want your systems logs to be printed to a file instead, you must configure the default handler to do so. The simplest way is to include the following in your sys.config:

[{kernel,
  [{logger,
    [{handler, default, logger_std_h,
      #{config => #{file => "path/to/file.log"}}}]}]}].

For more information about:

the Logger facility in general, see the User's Guide.

how to configure Logger, see the Configuration section in the User's Guide.

the built-in handlers, see logger_std_h and logger_disk_log_h.

the built-in formatter, see logger_formatter.

built-in filters, see logger_filters.

Macros

The following macros are defined in logger.hrl, which is included in a module with the directive

    -include_lib("kernel/include/logger.hrl").

?LOG_EMERGENCY(StringOrReport[,Metadata])

?LOG_EMERGENCY(FunOrFormat,Args[,Metadata])

?LOG_ALERT(StringOrReport[,Metadata])

?LOG_ALERT(FunOrFormat,Args[,Metadata])

?LOG_CRITICAL(StringOrReport[,Metadata])

?LOG_CRITICAL(FunOrFormat,Args[,Metadata])

?LOG_ERROR(StringOrReport[,Metadata])

?LOG_ERROR(FunOrFormat,Args[,Metadata])

?LOG_WARNING(StringOrReport[,Metadata])

?LOG_WARNING(FunOrFormat,Args[,Metadata])

?LOG_NOTICE(StringOrReport[,Metadata])

?LOG_NOTICE(FunOrFormat,Args[,Metadata])

?LOG_INFO(StringOrReport[,Metadata])

?LOG_INFO(FunOrFormat,Args[,Metadata])

?LOG_DEBUG(StringOrReport[,Metadata])

?LOG_DEBUG(FunOrFormat,Args[,Metadata])

?LOG(Level,StringOrReport[,Metadata])

?LOG(Level,FunOrFormat,Args[,Metadata])

All macros expand to a call to Logger, where Level is taken from the macro name, or from the first argument in the case of the ?LOG macro. Location data is added to the metadata as described under the metadata/0 type definition.

The call is wrapped in a case statement and will be evaluated only if Level is equal to or below the configured log level.

See Also

config, erlang, io, logger_disk_log_h, logger_filters, logger_handler, logger_formatter, logger_std_h, unicode

Summary

Types

config_handler()

Configuration used when adding or updating a handler.

filter()

A filter which can be installed as a handler filter, or as a primary filter in Logger.

filter_arg()

The second argument to the filter fun.

filter_id()

A unique identifier for a filter.

filter_return()

The return value from the filter fun.

formatter_config()

Configuration data for the formatter. See logger_formatter for an example of a formatter implementation.

handler_config()

Handler configuration data for Logger.

handler_id()

A unique identifier for a handler instance.

level()

The severity level for the message to be logged.

log_event()

A log event passed to filters and handlers

metadata()

Metadata for the log event.

msg_fun()

msg_fun_return()

olp_config()

Overload protection configuration.

primary_config()

Primary configuration data for Logger. The following default values apply

report()

A log report.

report_cb()

A fun which converts a report() to a format string and arguments, or directly to a string.

report_cb_config()

timestamp()

A timestamp produced with logger:timestamp().

Logging API functions

alert(StringOrReport)

Equivalent to alert(StringOrReport, #{}).

alert(FormatOrFun, Args)

Create a alert log event.

alert(FormatOrFun, Args, Metadata)

Equivalent to log(alert, FormatOrFun, Args, Metadata).

critical(StringOrReport)

Equivalent to critical(StringOrReport, #{}).

critical(FormatOrFun, Args)

Create a critical log event.

critical(FormatOrFun, Args, Metadata)

Equivalent to log(critical, FormatOrFun, Args, Metadata).

debug(StringOrReport)

Equivalent to debug(StringOrReport, #{}).

debug(FormatOrFun, Args)

Create a debug log event.

debug(FormatOrFun, Args, Metadata)

Equivalent to log(debug, FormatOrFun, Args, Metadata).

emergency(StringOrReport)

Equivalent to emergency(StringOrReport, #{}).

emergency(FormatOrFun, Args)

Create a emergency log event.

emergency(FormatOrFun, Args, Metadata)

Equivalent to log(emergency, FormatOrFun, Args, Metadata).

error(StringOrReport)

Equivalent to error(StringOrReport, #{}).

error(FormatOrFun, Args)

Create a error log event.

error(FormatOrFun, Args, Metadata)

Equivalent to log(error, FormatOrFun, Args, Metadata).

info(StringOrReport)

Equivalent to info(StringOrReport, #{}).

info(FormatOrFun, Args)

Create a info log event.

info(FormatOrFun, Args, Metadata)

Equivalent to log(info, FormatOrFun, Args, Metadata).

log(Level, StringOrReport)

Equivalent to log(Level, StringOrReport, #{}).

log/3

Create a log event at the given log level, with the given message to be logged and metadata.

log(Level, FunOrFormat, Args, Metadata)

Create a log event at the given log level, with the given message to be logged and metadata.

notice(StringOrReport)

Equivalent to notice(StringOrReport, #{}).

notice(FormatOrFun, Args)

Create a notice log event.

notice(FormatOrFun, Args, Metadata)

Equivalent to log(notice, FormatOrFun, Args, Metadata).

warning(StringOrReport)

Equivalent to warning(StringOrReport, #{}).

warning(FormatOrFun, Args)

Create a warning log event.

warning(FormatOrFun, Args, Metadata)

Equivalent to log(warning, FormatOrFun, Args, Metadata).

Functions

add_handler(HandlerId, Module, Config)

Add a handler with the given configuration.

add_handler_filter(HandlerId, FilterId, Filter)

Add a filter to the specified handler.

add_handlers/1

Reads the application configuration parameter logger and calls add_handlers/1 with its contents.

add_primary_filter(FilterId, Filter)

Add a primary filter to Logger.

compare_levels(Level1, Level2)

Compare the severity of two log levels. Returns gt if Level1 is more severe than Level2, lt if Level1 is less severe, and eq if the levels are equal.

format_report(Report)

Convert a log message on report form to {Format, Args}. This is the default report callback used by logger_formatter when no custom report callback is found. See section Log Message in the Kernel User's Guide for information about report callbacks and valid forms of log messages.

get_config()

Look up all current Logger configuration, including primary, handler, and proxy configuration, and module level settings.

get_handler_config()

Look up the current configuration for all handlers.

get_handler_config(HandlerId)

Look up the current configuration for the given handler.

get_handler_ids()

Look up the identities for all installed handlers.

get_module_level()

Look up all current module levels. Returns a list containing one {Module,Level} element for each module for which the module level was previously set with set_module_level/2.

get_module_level(Modules)

Look up the current level for the given modules. Returns a list containing one {Module,Level} element for each of the given modules for which the module level was previously set with set_module_level/2.

get_primary_config()

Look up the current primary configuration for Logger.

get_process_metadata()

Retrieve data set with set_process_metadata/1 or update_process_metadata/1.

get_proxy_config()

Look up the current configuration for the Logger proxy.

i()

Pretty print all Logger configuration.

i(What)

Pretty print the Logger configuration.

reconfigure()

Reconfigure Logger using updated kernel configuration that was set after kernel application was loaded.

remove_handler(HandlerId)

Remove the handler identified by HandlerId.

remove_handler_filter(HandlerId, FilterId)

Remove the filter identified by FilterId from the handler identified by HandlerId.

remove_primary_filter(FilterId)

Remove the primary filter identified by FilterId from Logger.

set_application_level(Application, Level)

Set the log level for all the modules of the specified application.

set_handler_config(HandlerId, Config)

Set configuration data for the specified handler. This overwrites the current handler configuration.

set_handler_config(HandlerId, Key, Value)

Add or update configuration data for the specified handler. If the given Key already exists, its associated value will be changed to the given value. If it does not exist, it will be added.

set_module_level(Modules, Level)

Set the log level for the specified modules.

set_primary_config(Config)

Set primary configuration data for Logger. This overwrites the current configuration.

set_primary_config(Key, Value)

Add or update primary configuration data for Logger. If the given Key already exists, its associated value will be changed to the given value. If it does not exist, it will be added.

set_process_metadata(Meta)

Set metadata which Logger shall automatically insert in all log events produced on the current process.

set_proxy_config(Config)

Set configuration data for the Logger proxy. This overwrites the current proxy configuration. Keys that are not specified in the Config map gets default values.

timestamp()

Return a timestamp that can be inserted as the time field in the meta data for a log event. It is produced with os:system_time(microsecond).

unset_application_level(Application)

Unset the log level for all the modules of the specified application.

unset_module_level()

Remove module specific log settings. After this, the primary log level is used for all modules.

unset_module_level(Modules)

Remove module specific log settings. After this, the primary log level is used for the specified modules.

unset_process_metadata()

Delete data set with set_process_metadata/1 or update_process_metadata/1.

update_formatter_config(HandlerId, FormatterConfig)

Update the formatter configuration for the specified handler.

update_formatter_config(HandlerId, Key, Value)

Equivalent to update_formatter_config(HandlerId, #{Key => Value}).

update_handler_config(HandlerId, Config)

Update configuration data for the specified handler. This function behaves as if it was implemented as follows

update_handler_config(HandlerId, Key, Value)

Add or update configuration data for the specified handler. If the given Key already exists, its associated value will be changed to the given value. If it does not exist, it will be added.

update_primary_config(Config)

Update primary configuration data for Logger. This function behaves as if it was implemented as follows

update_process_metadata(Meta)

Set or update metadata to use when logging from current process

update_proxy_config(Config)

Update configuration data for the Logger proxy. This function behaves as if it was implemented as follows

Types

config_handler()

(since OTP 21.0)

-type config_handler() :: {handler, logger_handler:id(), module(), logger_handler:config()}.

Configuration used when adding or updating a handler.

filter()

(since OTP 21.0)

-type filter() :: {fun((log_event(), filter_arg()) -> filter_return()), filter_arg()}.

A filter which can be installed as a handler filter, or as a primary filter in Logger.

filter_arg()

(since OTP 21.0)

-type filter_arg() :: term().

The second argument to the filter fun.

filter_id()

(since OTP 21.0)

-type filter_id() :: atom().

A unique identifier for a filter.

filter_return()

(since OTP 21.0)

-type filter_return() :: stop | ignore | log_event().

The return value from the filter fun.

formatter_config()

(since OTP 21.0)

-type formatter_config() :: #{atom() => term()}.

Configuration data for the formatter. See logger_formatter for an example of a formatter implementation.

handler_config()

(since OTP 21.0)

-type handler_config() :: logger_handler:config().

Handler configuration data for Logger.

Note

DEPRECATED: Use logger_handler:config/0 instead.

handler_id()

(since OTP 21.0)

-type handler_id() :: logger_handler:id().

A unique identifier for a handler instance.

Note

DEPRECATED: Use logger_handler:id/0 instead.

level()

(since OTP 21.0)

-type level() :: emergency | alert | critical | error | warning | notice | info | debug.

The severity level for the message to be logged.

log_event()

(since OTP 21.0)

-type log_event() ::
          #{level := level(),
            msg := {io:format(), [term()]} | {report, report()} | {string, unicode:chardata()},
            meta := metadata()}.

A log event passed to filters and handlers

metadata()

(since OTP 21.0)

-type metadata() ::
          #{pid => pid(),
            gl => pid(),
            time => timestamp(),
            mfa => {module(), atom(), non_neg_integer()},
            file => file:filename(),
            line => non_neg_integer(),
            domain => [atom()],
            report_cb => report_cb(),
            atom() => term()}.

Metadata for the log event.

Logger adds the following metadata to each log event:

pid => self()

gl => group_leader()

time => logger:timestamp()

When a log macro is used, Logger also inserts location information:

mfa => {?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY}

file => ?FILE

line => ?LINE

You can add custom metadata, either by:

specifying a map as the last parameter to any of the log macros or the logger API functions.

setting process metadata with set_process_metadata/1 or update_process_metadata/1.

setting primary metadata with set_primary_config/1 or through the kernel configuration parameter logger_metadata

Note

When adding custom metadata, make sure not to use any of the keys mentioned above as that may cause a lot of confusion about the log events.

Logger merges all the metadata maps before forwarding the log event to the handlers. If the same keys occur, values from the log call overwrite process metadata, which overwrites the primary metadata, which in turn overwrite values set by Logger.

The following custom metadata keys have special meaning:

domain - The value associated with this key is used by filters for grouping log events originating from, for example, specific functional areas. See logger_filters:domain/2 for a description of how this field can be used.

report_cb - If the log message is specified as a report/0, the report_cb key can be associated with a fun (report callback) that converts the report to a format string and arguments, or directly to a string. See the type definition of report_cb/0, and section Log Message in the User's Guide for more information about report callbacks.

msg_fun()

(since OTP 21.0)

-type msg_fun() :: fun((term()) -> msg_fun_return() | {msg_fun_return(), metadata()}).

msg_fun_return()

(not exported) (since OTP 21.0)

-type msg_fun_return() :: {io:format(), [term()]} | report() | unicode:chardata() | ignore.

olp_config()

(since OTP 21.0)

-type olp_config() :: logger_handler:olp_config().

Overload protection configuration.

Note

DEPRECATED: Use logger_handler:olp_config/0 instead.

primary_config()

(since OTP 21.0)

-type primary_config() ::
          #{level => level() | all | none,
            metadata => metadata(),
            filter_default => log | stop,
            filters => [{filter_id(), filter()}]}.

Primary configuration data for Logger. The following default values apply:

level => info

filter_default => log

filters => []

report()

(since OTP 21.0)

-type report() :: map() | [{atom(), term()}, ...].

A log report.

report_cb()

(since OTP 21.0)

-type report_cb() ::
          fun((report()) -> {io:format(), [term()]}) |
          fun((report(), report_cb_config()) -> unicode:chardata()).

A fun which converts a report() to a format string and arguments, or directly to a string.

See section Log Message in the User's Guide for more information.

report_cb_config()

(since OTP 21.0)

-type report_cb_config() ::
          #{depth := pos_integer() | unlimited,
            chars_limit := pos_integer() | unlimited,
            single_line := boolean()}.

timestamp()

(since OTP 21.0)

-type timestamp() :: integer().

A timestamp produced with logger:timestamp().

Logging API functions

alert(StringOrReport)

(since OTP 21.0)

-spec alert(String :: unicode:chardata()) -> ok;
           (Report :: report()) -> ok.

Equivalent to alert(StringOrReport, #{}).

alert(FormatOrFun, Args)

(since OTP 21.0)

-spec alert(String :: unicode:chardata(), Metadata :: metadata()) -> ok;
           (Report :: report(), Metadata :: metadata()) -> ok;
           (Format :: io:format(), Args :: [term()]) -> ok;
           (Fun :: msg_fun(), FunArgs :: term()) -> ok.

Create a alert log event.

Equivalent to log(alert, StringOrReport, Metadata) if called as alert(StringOrReport, Metadata).

Equivalent to alert(FormatOrFun, Args, #{}) if called as alert(FormatOrFun, Args).

alert(FormatOrFun, Args, Metadata)

(since OTP 21.0)

-spec alert(Format :: io:format(), Args :: [term()], Metadata :: metadata()) -> ok;
           (Fun :: msg_fun(), FunArgs :: term(), Metadata :: metadata()) -> ok.

Equivalent to log(alert, FormatOrFun, Args, Metadata).

critical(StringOrReport)

(since OTP 21.0)

-spec critical(String :: unicode:chardata()) -> ok;
              (Report :: report()) -> ok.

Equivalent to critical(StringOrReport, #{}).

critical(FormatOrFun, Args)

(since OTP 21.0)

-spec critical(String :: unicode:chardata(), Metadata :: metadata()) -> ok;
              (Report :: report(), Metadata :: metadata()) -> ok;
              (Format :: io:format(), Args :: [term()]) -> ok;
              (Fun :: msg_fun(), FunArgs :: term()) -> ok.

Create a critical log event.

Equivalent to log(critical, StringOrReport, Metadata) if called as critical(StringOrReport, Metadata).

Equivalent to critical(FormatOrFun, Args, #{}) if called as critical(FormatOrFun, Args).

critical(FormatOrFun, Args, Metadata)

(since OTP 21.0)

-spec critical(Format :: io:format(), Args :: [term()], Metadata :: metadata()) -> ok;
              (Fun :: msg_fun(), FunArgs :: term(), Metadata :: metadata()) -> ok.

Equivalent to log(critical, FormatOrFun, Args, Metadata).

debug(StringOrReport)

(since OTP 21.0)

-spec debug(String :: unicode:chardata()) -> ok;
           (Report :: report()) -> ok.

Equivalent to debug(StringOrReport, #{}).

debug(FormatOrFun, Args)

(since OTP 21.0)

-spec debug(String :: unicode:chardata(), Metadata :: metadata()) -> ok;
           (Report :: report(), Metadata :: metadata()) -> ok;
           (Format :: io:format(), Args :: [term()]) -> ok;
           (Fun :: msg_fun(), FunArgs :: term()) -> ok.

Create a debug log event.

Equivalent to log(debug, StringOrReport, Metadata) if called as debug(StringOrReport, Metadata).

Equivalent to debug(FormatOrFun, Args, #{}) if called as debug(FormatOrFun, Args).

debug(FormatOrFun, Args, Metadata)

(since OTP 21.0)

-spec debug(Format :: io:format(), Args :: [term()], Metadata :: metadata()) -> ok;
           (Fun :: msg_fun(), FunArgs :: term(), Metadata :: metadata()) -> ok.

Equivalent to log(debug, FormatOrFun, Args, Metadata).

emergency(StringOrReport)

(since OTP 21.0)

-spec emergency(String :: unicode:chardata()) -> ok;
               (Report :: report()) -> ok.

Equivalent to emergency(StringOrReport, #{}).

emergency(FormatOrFun, Args)

(since OTP 21.0)

-spec emergency(String :: unicode:chardata(), Metadata :: metadata()) -> ok;
               (Report :: report(), Metadata :: metadata()) -> ok;
               (Format :: io:format(), Args :: [term()]) -> ok;
               (Fun :: msg_fun(), FunArgs :: term()) -> ok.

Create a emergency log event.

Equivalent to log(emergency, StringOrReport, Metadata) if called as emergency(StringOrReport, Metadata).

Equivalent to emergency(FormatOrFun, Args, #{}) if called as emergency(FormatOrFun, Args).

emergency(FormatOrFun, Args, Metadata)

(since OTP 21.0)

-spec emergency(Format :: io:format(), Args :: [term()], Metadata :: metadata()) -> ok;
               (Fun :: msg_fun(), FunArgs :: term(), Metadata :: metadata()) -> ok.

Equivalent to log(emergency, FormatOrFun, Args, Metadata).

error(StringOrReport)

(since OTP 21.0)

-spec error(String :: unicode:chardata()) -> ok;
           (Report :: report()) -> ok.

Equivalent to error(StringOrReport, #{}).

error(FormatOrFun, Args)

(since OTP 21.0)

-spec error(String :: unicode:chardata(), Metadata :: metadata()) -> ok;
           (Report :: report(), Metadata :: metadata()) -> ok;
           (Format :: io:format(), Args :: [term()]) -> ok;
           (Fun :: msg_fun(), FunArgs :: term()) -> ok.

Create a error log event.

Equivalent to log(error, StringOrReport, Metadata) if called as error(StringOrReport, Metadata).

Equivalent to error(FormatOrFun, Args, #{}) if called as error(FormatOrFun, Args).

error(FormatOrFun, Args, Metadata)

(since OTP 21.0)

-spec error(Format :: io:format(), Args :: [term()], Metadata :: metadata()) -> ok;
           (Fun :: msg_fun(), FunArgs :: term(), Metadata :: metadata()) -> ok.

Equivalent to log(error, FormatOrFun, Args, Metadata).

info(StringOrReport)

(since OTP 21.0)

-spec info(String :: unicode:chardata()) -> ok;
          (Report :: report()) -> ok.

Equivalent to info(StringOrReport, #{}).

info(FormatOrFun, Args)

(since OTP 21.0)

-spec info(String :: unicode:chardata(), Metadata :: metadata()) -> ok;
          (Report :: report(), Metadata :: metadata()) -> ok;
          (Format :: io:format(), Args :: [term()]) -> ok;
          (Fun :: msg_fun(), FunArgs :: term()) -> ok.

Create a info log event.

Equivalent to log(info, StringOrReport, Metadata) if called as info(StringOrReport, Metadata).

Equivalent to info(FormatOrFun, Args, #{}) if called as info(FormatOrFun, Args).

info(FormatOrFun, Args, Metadata)

(since OTP 21.0)

-spec info(Format :: io:format(), Args :: [term()], Metadata :: metadata()) -> ok;
          (Fun :: msg_fun(), FunArgs :: term(), Metadata :: metadata()) -> ok.

Equivalent to log(info, FormatOrFun, Args, Metadata).

log(Level, StringOrReport)

(since OTP 21.0)

-spec log(Level :: level(), String :: unicode:chardata()) -> ok;
         (Level :: level(), Report :: report()) -> ok.

Equivalent to log(Level, StringOrReport, #{}).

log/3

(since OTP 21.0)

-spec log(Level :: level(), String :: unicode:chardata(), Metadata :: metadata()) -> ok;
         (Level :: level(), Report :: report(), Metadata :: metadata()) -> ok;
         (Level :: level(), Format :: io:format(), Args :: [term()]) -> ok;
         (Level :: level(), Fun :: msg_fun(), FunArgs :: term()) -> ok.

Create a log event at the given log level, with the given message to be logged and metadata.

Example:

%% A plain string
1> logger:log(info, "Hello World").
%% A plain string with metadata
2> logger:log(debug, "Hello World", #{ meta => data }).
%% A format string with arguments
3> logger:log(warning, "The roof is on ~ts",[Cause]).
%% A report
4> logger:log(warning, #{ what => roof, cause => Cause }).

Equivalent to log(Level, FormatOrFun, Args, #{}) if called as log(Level, FormatOrFun, Args).

log(Level, FunOrFormat, Args, Metadata)

(since OTP 21.0)

-spec log(Level :: level(), Format :: io:format(), Args :: [term()], Metadata :: metadata()) -> ok;
         (Level :: level(), Fun :: msg_fun(), FunArgs :: term(), Metadata :: metadata()) -> ok.

Create a log event at the given log level, with the given message to be logged and metadata.

The message and metadata can either be given directly in the arguments, or returned from a fun. Passing a fun instead of the message/metadata directly is useful in scenarios when the message/metadata is very expensive to compute. This is because the fun is only evaluated when the message/metadata is actually needed, which may be not at all if the log event is not to be logged. Examples:

%% A plain string with expensive metadata
1> logger:info(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[]).
%% An expensive report
2> logger:debug(fun(What) -> #{ what => What, cause => expensive() } end,roof).
%% A plain string with expensive metadata and normal metadata
3> logger:debug(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[],
               #{ meta => data }).

When metadata is given both as an argument and returned from the fun they are merged. If equal keys exists the values are taken from the metadata returned by the fun.

notice(StringOrReport)

(since OTP 21.0)

-spec notice(String :: unicode:chardata()) -> ok;
            (Report :: report()) -> ok.

Equivalent to notice(StringOrReport, #{}).

notice(FormatOrFun, Args)

(since OTP 21.0)

-spec notice(String :: unicode:chardata(), Metadata :: metadata()) -> ok;
            (Report :: report(), Metadata :: metadata()) -> ok;
            (Format :: io:format(), Args :: [term()]) -> ok;
            (Fun :: msg_fun(), FunArgs :: term()) -> ok.

Create a notice log event.

Equivalent to log(notice, StringOrReport, Metadata) if called as notice(StringOrReport, Metadata).

Equivalent to notice(FormatOrFun, Args, #{}) if called as notice(FormatOrFun, Args).

notice(FormatOrFun, Args, Metadata)

(since OTP 21.0)

-spec notice(Format :: io:format(), Args :: [term()], Metadata :: metadata()) -> ok;
            (Fun :: msg_fun(), FunArgs :: term(), Metadata :: metadata()) -> ok.

Equivalent to log(notice, FormatOrFun, Args, Metadata).

warning(StringOrReport)

(since OTP 21.0)

-spec warning(String :: unicode:chardata()) -> ok;
             (Report :: report()) -> ok.

Equivalent to warning(StringOrReport, #{}).

warning(FormatOrFun, Args)

(since OTP 21.0)

-spec warning(String :: unicode:chardata(), Metadata :: metadata()) -> ok;
             (Report :: report(), Metadata :: metadata()) -> ok;
             (Format :: io:format(), Args :: [term()]) -> ok;
             (Fun :: msg_fun(), FunArgs :: term()) -> ok.

Create a warning log event.

Equivalent to log(warning, StringOrReport, Metadata) if called as warning(StringOrReport, Metadata).

Equivalent to warning(FormatOrFun, Args, #{}) if called as warning(FormatOrFun, Args).

warning(FormatOrFun, Args, Metadata)

(since OTP 21.0)

-spec warning(Format :: io:format(), Args :: [term()], Metadata :: metadata()) -> ok;
             (Fun :: msg_fun(), FunArgs :: term(), Metadata :: metadata()) -> ok.

Equivalent to log(warning, FormatOrFun, Args, Metadata).

Functions

add_handler(HandlerId, Module, Config)

(since OTP 21.0)

-spec add_handler(HandlerId, Module, Config) -> ok | {error, term()}
                     when
                         HandlerId :: logger_handler:id(),
                         Module :: module(),
                         Config :: logger_handler:config().

Add a handler with the given configuration.

HandlerId is a unique identifier which must be used in all subsequent calls referring to this handler.

add_handler_filter(HandlerId, FilterId, Filter)

(since OTP 21.0)

-spec add_handler_filter(HandlerId, FilterId, Filter) -> ok | {error, term()}
                            when
                                HandlerId :: logger_handler:id(),
                                FilterId :: filter_id(),
                                Filter :: filter().

Add a filter to the specified handler.

The filter fun is called with the log event as the first parameter, and the specified filter_args() as the second parameter.

The return value of the fun specifies if a log event is to be discarded or forwarded to the handler callback:

log_event/0 - The filter passed. The next handler filter, if any, is applied. If no more filters exist for this handler, the log event is forwarded to the handler callback.

stop - The filter did not pass, and the log event is immediately discarded.

ignore - The filter has no knowledge of the log event. The next handler filter, if any, is applied. If no more filters exist for this handler, the value of the filter_default configuration parameter for the handler specifies if the log event shall be discarded or forwarded to the handler callback.

See section Filters in the User's Guide for more information about filters.

Some built-in filters exist. These are defined in logger_filters.

add_handlers/1

(since OTP 21.0)

-spec add_handlers(Application) -> ok | {error, term()} when Application :: atom();
                  (HandlerConfig) -> ok | {error, term()} when HandlerConfig :: [config_handler()].

Reads the application configuration parameter logger and calls add_handlers/1 with its contents.

This function should be used by custom Logger handlers to make configuration consistent no matter which handler the system uses. Normal usage is to add a call to logger:add_handlers/1 just after the processes that the handler needs are started, and pass the application's logger configuration as the argument. For example:

-behaviour(application).
start(_, []) ->
    case supervisor:start_link({local, my_sup}, my_sup, []) of
        {ok, Pid} ->
            ok = logger:add_handlers(my_app),
            {ok, Pid, []};
        Error -> Error
     end.

This reads the logger configuration parameter from the my_app application and starts the configured handlers. The contents of the configuration use the same rules as the logger handler configuration.

If the handler is meant to replace the default handler, the Kernel's default handler have to be disabled before the new handler is added. A sys.config file that disables the Kernel handler and adds a custom handler could look like this:

[{kernel,
  [{logger,
    %% Disable the default Kernel handler
    [{handler, default, undefined}]}]},
 {my_app,
  [{logger,
    %% Enable this handler as the default
    [{handler, default, my_handler, #{}}]}]}].

add_primary_filter(FilterId, Filter)

(since OTP 21.0)

-spec add_primary_filter(FilterId, Filter) -> ok | {error, term()}
                            when FilterId :: filter_id(), Filter :: filter().

Add a primary filter to Logger.

The filter fun is called with the log event as the first parameter, and the specified filter_args() as the second parameter.

The return value of the fun specifies if a log event is to be discarded or forwarded to the handlers:

log_event/0 - The filter passed. The next primary filter, if any, is applied. If no more primary filters exist, the log event is forwarded to the handler part of Logger, where handler filters are applied.

stop - The filter did not pass, and the log event is immediately discarded.

ignore - The filter has no knowledge of the log event. The next primary filter, if any, is applied. If no more primary filters exist, the value of the primary filter_default configuration parameter specifies if the log event shall be discarded or forwarded to the handler part.

See section Filters in the User's Guide for more information about filters.

Some built-in filters exist. These are defined in logger_filters.

compare_levels(Level1, Level2)

(since OTP 21.0)

-spec compare_levels(Level1, Level2) -> eq | gt | lt
                        when Level1 :: level() | all | none, Level2 :: level() | all | none.

Compare the severity of two log levels. Returns gt if Level1 is more severe than Level2, lt if Level1 is less severe, and eq if the levels are equal.

format_report(Report)

(since OTP 21.0)

-spec format_report(Report) -> FormatArgs when Report :: report(), FormatArgs :: {io:format(), [term()]}.

Convert a log message on report form to {Format, Args}. This is the default report callback used by logger_formatter when no custom report callback is found. See section Log Message in the Kernel User's Guide for information about report callbacks and valid forms of log messages.

The function produces lines of Key: Value from key-value lists. Strings are printed with ~ts and other terms with ~tp.

If Report is a map, it is converted to a key-value list before formatting as such.

get_config()

(since OTP 21.0)

-spec get_config() ->
                    #{primary => primary_config(),
                      handlers => [logger_handler:config()],
                      proxy => olp_config(),
                      module_levels => [{module(), level() | all | none}]}.

Look up all current Logger configuration, including primary, handler, and proxy configuration, and module level settings.

get_handler_config()

(since OTP 21.0)

-spec get_handler_config() -> [Config] when Config :: logger_handler:config().

Look up the current configuration for all handlers.

get_handler_config(HandlerId)

(since OTP 21.0)

-spec get_handler_config(HandlerId) -> {ok, Config} | {error, term()}
                            when HandlerId :: logger_handler:id(), Config :: logger_handler:config().

Look up the current configuration for the given handler.

get_handler_ids()

(since OTP 21.0)

-spec get_handler_ids() -> [HandlerId] when HandlerId :: logger_handler:id().

Look up the identities for all installed handlers.

get_module_level()

(since OTP 21.0)

-spec get_module_level() -> [{Module, Level}] when Module :: module(), Level :: level() | all | none.

Look up all current module levels. Returns a list containing one {Module,Level} element for each module for which the module level was previously set with set_module_level/2.

get_module_level(Modules)

(since OTP 21.0)

-spec get_module_level(Modules) -> [{Module, Level}]
                          when
                              Modules :: [Module] | Module,
                              Module :: module(),
                              Level :: level() | all | none.

Look up the current level for the given modules. Returns a list containing one {Module,Level} element for each of the given modules for which the module level was previously set with set_module_level/2.

get_primary_config()

(since OTP 21.0)

-spec get_primary_config() -> Config when Config :: primary_config().

Look up the current primary configuration for Logger.

get_process_metadata()

(since OTP 21.0)

-spec get_process_metadata() -> Meta | undefined when Meta :: metadata().

Retrieve data set with set_process_metadata/1 or update_process_metadata/1.

get_proxy_config()

(since OTP 21.3)

-spec get_proxy_config() -> Config when Config :: olp_config().

Look up the current configuration for the Logger proxy.

For more information about the proxy, see section Logger Proxy in the Kernel User's Guide.

i()

(since OTP 21.3)

-spec i() -> ok.

Pretty print all Logger configuration.

i(What)

(since OTP 21.3)

-spec i(What) -> ok when What :: primary | handlers | proxy | modules | logger_handler:id().

Pretty print the Logger configuration.

reconfigure()

(since OTP 24.2)

-spec reconfigure() -> ok | {error, term()}.

Reconfigure Logger using updated kernel configuration that was set after kernel application was loaded.

Beware, that this is meant to be run only by the build tools, not manually during application lifetime, as this may cause missing log entries.

Before reconfiguration, simple logger handler is added to capture log events before the logging infrastructure is started and prints them to standard output. After the default handler is added again, all log events captured by the simple handler are replayed to the default handler, and the simple handler is removed. Notice that if you don't add the default handler, simple handler will persist.

remove_handler(HandlerId)

(since OTP 21.0)

-spec remove_handler(HandlerId) -> ok | {error, term()} when HandlerId :: logger_handler:id().

Remove the handler identified by HandlerId.

remove_handler_filter(HandlerId, FilterId)

(since OTP 21.0)

-spec remove_handler_filter(HandlerId, FilterId) -> ok | {error, term()}
                               when HandlerId :: logger_handler:id(), FilterId :: filter_id().

Remove the filter identified by FilterId from the handler identified by HandlerId.

remove_primary_filter(FilterId)

(since OTP 21.0)

-spec remove_primary_filter(FilterId) -> ok | {error, term()} when FilterId :: filter_id().

Remove the primary filter identified by FilterId from Logger.

set_application_level(Application, Level)

(since OTP 21.1)

-spec set_application_level(Application, Level) -> ok | {error, not_loaded}
                               when Application :: atom(), Level :: level() | all | none.

Set the log level for all the modules of the specified application.

This function is a convenience function that calls logger:set_module_level/2 for each module associated with an application.

set_handler_config(HandlerId, Config)

(since OTP 21.0)

-spec set_handler_config(HandlerId, Config) -> ok | {error, term()}
                            when HandlerId :: logger_handler:id(), Config :: logger_handler:config().

Set configuration data for the specified handler. This overwrites the current handler configuration.

To modify the existing configuration, use update_handler_config/2, or, if a more complex merge is needed, read the current configuration with get_handler_config/1 , then do the merge before writing the new configuration back with this function.

If a key is removed compared to the current configuration, and the key is known by Logger, the default value is used. If it is a custom key, then it is up to the handler implementation if the value is removed or a default value is inserted.

set_handler_config(HandlerId, Key, Value)

(since OTP 21.0)

-spec set_handler_config(HandlerId, level, Level) -> Return
                            when
                                HandlerId :: logger_handler:id(),
                                Level :: level() | all | none,
                                Return :: ok | {error, term()};
                        (HandlerId, filter_default, FilterDefault) -> Return
                            when
                                HandlerId :: logger_handler:id(),
                                FilterDefault :: log | stop,
                                Return :: ok | {error, term()};
                        (HandlerId, filters, Filters) -> Return
                            when
                                HandlerId :: logger_handler:id(),
                                Filters :: [{filter_id(), filter()}],
                                Return :: ok | {error, term()};
                        (HandlerId, formatter, Formatter) -> Return
                            when
                                HandlerId :: logger_handler:id(),
                                Formatter :: {module(), formatter_config()},
                                Return :: ok | {error, term()};
                        (HandlerId, config, Config) -> Return
                            when
                                HandlerId :: logger_handler:id(),
                                Config :: term(),
                                Return :: ok | {error, term()}.

Add or update configuration data for the specified handler. If the given Key already exists, its associated value will be changed to the given value. If it does not exist, it will be added.

If the value is incomplete, which for example can be the case for the config key, it is up to the handler implementation how the unspecified parts are set. For all handlers in the Kernel application, unspecified data for the config key is set to default values. To update only specified data, and keep the existing configuration for the rest, use update_handler_config/3.

See the definition of the logger_handler:config/0 type for more information about the different parameters.

set_module_level(Modules, Level)

(since OTP 21.0)

-spec set_module_level(Modules, Level) -> ok | {error, term()}
                          when Modules :: [module()] | module(), Level :: level() | all | none.

Set the log level for the specified modules.

The log level for a module overrides the primary log level of Logger for log events originating from the module in question. Notice, however, that it does not override the level configuration for any handler.

For example: Assume that the primary log level for Logger is info, and there is one handler, h1, with level info and one handler, h2, with level debug.

With this configuration, no debug messages will be logged, since they are all stopped by the primary log level.

If the level for mymodule is now set to debug, then debug events from this module will be logged by the handler h2, but not by handler h1.

Debug events from other modules are still not logged.

To change the primary log level for Logger, use set_primary_config(level, Level).

To change the log level for a handler, use set_handler_config(HandlerId, level, Level) .

Note

The originating module for a log event is only detected if the key mfa exists in the metadata, and is associated with {Module, Function, Arity}. When log macros are used, this association is automatically added to all log events. If an API function is called directly, without using a macro, the logging client must explicitly add this information if module levels shall have any effect.

set_primary_config(Config)

(since OTP 21.0)

-spec set_primary_config(Config) -> ok | {error, term()} when Config :: primary_config().

Set primary configuration data for Logger. This overwrites the current configuration.

To modify the existing configuration, use update_primary_config/1, or, if a more complex merge is needed, read the current configuration with get_primary_config/0 , then do the merge before writing the new configuration back with this function.

If a key is removed compared to the current configuration, the default value is used.

set_primary_config(Key, Value)

(since OTP 21.0)

-spec set_primary_config(level, Level) -> ok | {error, term()} when Level :: level() | all | none;
                        (filter_default, FilterDefault) -> ok | {error, term()}
                            when FilterDefault :: log | stop;
                        (filters, Filters) -> ok | {error, term()}
                            when Filters :: [{filter_id(), filter()}];
                        (metadata, Meta) -> ok | {error, term()} when Meta :: metadata().

Add or update primary configuration data for Logger. If the given Key already exists, its associated value will be changed to the given value. If it does not exist, it will be added.

The metadata key was added in OTP 24.0.

set_process_metadata(Meta)

(since OTP 21.0)

-spec set_process_metadata(Meta) -> ok when Meta :: metadata().

Set metadata which Logger shall automatically insert in all log events produced on the current process.

Location data produced by the log macros, and/or metadata given as argument to the log call (API function or macro), are merged with the process metadata. If the same keys occur, values from the metadata argument to the log call overwrite values from the process metadata, which in turn overwrite values from the location data.

Subsequent calls to this function overwrites previous data set. To update existing data instead of overwriting it, see update_process_metadata/1.

set_proxy_config(Config)

(since OTP 21.3)

-spec set_proxy_config(Config) -> ok | {error, term()} when Config :: olp_config().

Set configuration data for the Logger proxy. This overwrites the current proxy configuration. Keys that are not specified in the Config map gets default values.

To modify the existing configuration, use update_proxy_config/1, or, if a more complex merge is needed, read the current configuration with get_proxy_config/0 , then do the merge before writing the new configuration back with this function.

For more information about the proxy, see section Logger Proxy in the Kernel User's Guide.

timestamp()

(since OTP 21.3)

-spec timestamp() -> timestamp().

Return a timestamp that can be inserted as the time field in the meta data for a log event. It is produced with os:system_time(microsecond).

Notice that Logger automatically inserts a timestamp in the meta data unless it already exists. This function is exported for the rare case when the timestamp must be taken at a different point in time than when the log event is issued.

unset_application_level(Application)

(since OTP 21.1)

-spec unset_application_level(Application) -> ok | {error, {not_loaded, Application}}
                                 when Application :: atom().

Unset the log level for all the modules of the specified application.

This function is a utility function that calls logger:unset_module_level/2 for each module associated with an application.

unset_module_level()

(since OTP 21.0)

-spec unset_module_level() -> ok.

Remove module specific log settings. After this, the primary log level is used for all modules.

unset_module_level(Modules)

(since OTP 21.0)

-spec unset_module_level(Modules) -> ok when Modules :: [module()] | module().

Remove module specific log settings. After this, the primary log level is used for the specified modules.

unset_process_metadata()

(since OTP 21.0)

-spec unset_process_metadata() -> ok.

Delete data set with set_process_metadata/1 or update_process_metadata/1.

update_formatter_config(HandlerId, FormatterConfig)

(since OTP 21.0)

-spec update_formatter_config(HandlerId, FormatterConfig) -> ok | {error, term()}
                                 when
                                     HandlerId :: logger_handler:id(),
                                     FormatterConfig :: formatter_config().

Update the formatter configuration for the specified handler.

The new configuration is merged with the existing formatter configuration.

To overwrite the existing configuration without any merge, use

set_handler_config(HandlerId, formatter,
	      {FormatterModule, FormatterConfig}).

update_formatter_config(HandlerId, Key, Value)

(since OTP 21.0)

-spec update_formatter_config(HandlerId, Key, Value) -> ok | {error, term()}
                                 when HandlerId :: logger_handler:id(), Key :: atom(), Value :: term().

Equivalent to update_formatter_config(HandlerId, #{Key => Value}).

update_handler_config(HandlerId, Config)

(since OTP 21.0)

-spec update_handler_config(HandlerId, Config) -> ok | {error, term()}
                               when HandlerId :: logger_handler:id(), Config :: logger_handler:config().

Update configuration data for the specified handler. This function behaves as if it was implemented as follows:

{ok, {_, Old}} = logger:get_handler_config(HandlerId),
logger:set_handler_config(HandlerId, maps:merge(Old, Config)).

To overwrite the existing configuration without any merge, use set_handler_config/2 .

update_handler_config(HandlerId, Key, Value)

(since OTP 21.2)

-spec update_handler_config(HandlerId, level, Level) -> Return
                               when
                                   HandlerId :: logger_handler:id(),
                                   Level :: level() | all | none,
                                   Return :: ok | {error, term()};
                           (HandlerId, filter_default, FilterDefault) -> Return
                               when
                                   HandlerId :: logger_handler:id(),
                                   FilterDefault :: log | stop,
                                   Return :: ok | {error, term()};
                           (HandlerId, filters, Filters) -> Return
                               when
                                   HandlerId :: logger_handler:id(),
                                   Filters :: [{filter_id(), filter()}],
                                   Return :: ok | {error, term()};
                           (HandlerId, formatter, Formatter) -> Return
                               when
                                   HandlerId :: logger_handler:id(),
                                   Formatter :: {module(), formatter_config()},
                                   Return :: ok | {error, term()};
                           (HandlerId, config, Config) -> Return
                               when
                                   HandlerId :: logger_handler:id(),
                                   Config :: term(),
                                   Return :: ok | {error, term()}.

Add or update configuration data for the specified handler. If the given Key already exists, its associated value will be changed to the given value. If it does not exist, it will be added.

If the value is incomplete, which for example can be the case for the config key, it is up to the handler implementation how the unspecified parts are set. For all handlers in the Kernel application, unspecified data for the config key is not changed. To reset unspecified data to default values, use set_handler_config/3.

See the definition of the logger_handler:config/0 type for more information about the different parameters.

update_primary_config(Config)

(since OTP 21.0)

-spec update_primary_config(Config) -> ok | {error, term()} when Config :: primary_config().

Update primary configuration data for Logger. This function behaves as if it was implemented as follows:

Old = logger:get_primary_config(),
logger:set_primary_config(maps:merge(Old, Config)).

To overwrite the existing configuration without any merge, use set_primary_config/1 .

update_process_metadata(Meta)

(since OTP 21.0)

-spec update_process_metadata(Meta) -> ok when Meta :: metadata().

Set or update metadata to use when logging from current process

If process metadata exists for the current process, this function behaves as if it was implemented as follows:

logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).

If no process metadata exists, the function behaves as set_process_metadata/1 .

update_proxy_config(Config)

(since OTP 21.3)

-spec update_proxy_config(Config) -> ok | {error, term()} when Config :: olp_config().

Update configuration data for the Logger proxy. This function behaves as if it was implemented as follows:

Old = logger:get_proxy_config(),
logger:set_proxy_config(maps:merge(Old, Config)).

To overwrite the existing configuration without any merge, use set_proxy_config/1 .

For more information about the proxy, see section Logger Proxy in the Kernel User's Guide.

logger_disk_log_h

A disk_log based handler for Logger

This is a handler for Logger that offers circular (wrapped) logs by using disk_log. Multiple instances of this handler can be added to Logger, and each instance prints to its own disk log file, created with the name and settings specified in the handler configuration.

The default standard handler, logger_std_h, can be replaced by a disk_log handler at startup of the Kernel application. See an example of this below.

The handler has an overload protection mechanism that keeps the handler process and the Kernel application alive during high loads of log events. How overload protection works, and how to configure it, is described in the User's Guide.

To add a new instance of the disk_log handler, use logger:add_handler/3. The handler configuration argument is a map which can contain general configuration parameters, as documented in the User's Guide, and handler specific parameters. The specific data is stored in a sub map with the key config, and can contain the following parameters:

file - This is the full name of the disk log file. The option corresponds to the name property in the dlog_option() datatype.

The value is set when the handler is added, and it cannot be changed in runtime.

Defaults to the same name as the handler identity, in the current directory.

type - This is the disk log type, wrap or halt. The option corresponds to the type property in the dlog_option() datatype.

The value is set when the handler is added, and it cannot be changed in runtime.

Defaults to wrap.

max_no_files - This is the maximum number of files that disk_log uses for its circular logging. The option corresponds to the MaxNoFiles element in the size property in the dlog_option() datatype.

The value is set when the handler is added, and it cannot be changed in runtime.

Defaults to 10.

The setting has no effect on a halt log.

max_no_bytes - This is the maximum number of bytes that is written to a log file before disk_log proceeds with the next file in order, or generates an error in case of a full halt log. The option corresponds to the MaxNoBytes element in the size property in the dlog_option() datatype.

The value is set when the handler is added, and it cannot be changed in runtime.

Defaults to 1048576 bytes for a wrap log, and infinity for a halt log.

filesync_repeat_interval - This value, in milliseconds, specifies how often the handler does a disk_log sync operation to write buffered data to disk. The handler attempts the operation repeatedly, but only performs a new sync if something has actually been logged.

Defaults to 5000 milliseconds.

If no_repeat is set as value, the repeated sync operation is disabled. The user can also call the filesync/1 function to perform a disk_log sync.

Other configuration parameters exist, to be used for customizing the overload protection behaviour. The same parameters are used both in the standard handler and the disk_log handler, and are documented in the User's Guide.

Notice that when changing the configuration of the handler in runtime, the disk_log options (file, type, max_no_files, max_no_bytes) must not be modified.

Example of adding a disk_log handler:

logger:add_handler(my_disk_log_h, logger_disk_log_h,
                   #{config => #{file => "./my_disk_log",
                                 type => wrap,
                                 max_no_files => 4,
                                 max_no_bytes => 10000,
                                 filesync_repeat_interval => 1000}}).

To use the disk_log handler instead of the default standard handler when starting an Erlang node, change the Kernel default logger to use logger_disk_log_h. Example:

erl -kernel logger '[{handler,default,logger_disk_log_h,
                      #{config => #{file => "./system_disk_log"}}}]'

See Also

logger, logger_std_h, disk_log

Summary

Functions

filesync(Name)

Write buffered data to disk.

Functions

filesync(Name)

(since OTP 21.0)

-spec filesync(Name) -> ok | {error, Reason}
                  when Name :: atom(), Reason :: handler_busy | {badarg, term()}.

Write buffered data to disk.

logger_filters

Filters to use with Logger.

All functions exported from this module can be used as primary or handler filters. See logger:add_primary_filter/2 and logger:add_handler_filter/3 for more information about how filters are added.

Filters are removed with logger:remove_primary_filter/1 and logger:remove_handler_filter/2.

See Also

logger

Summary

Functions

domain(LogEvent, Extra)

This filter provides a way of filtering log events based on a domain field in Metadata. This field is optional, and the purpose of using it is to group log events from, for example, a specific functional area. This allows filtering or other specialized treatment in a Logger handler.

level(LogEvent, Extra)

This filter provides a way of filtering log events based on the log level. It matches log events by comparing the log level with a specified MatchLevel

progress(LogEvent, Extra)

This filter matches all progress reports from supervisor and application_controller.

remote_gl(LogEvent, Extra)

This filter matches all events originating from a process that has its group leader on a remote node.

Functions

domain(LogEvent, Extra)

(since OTP 21.0)

-spec domain(LogEvent, Extra) -> logger:filter_return()
                when
                    LogEvent :: logger:log_event(),
                    Extra :: {Action, Compare, MatchDomain},
                    Action :: log | stop,
                    Compare :: super | sub | equal | not_equal | undefined,
                    MatchDomain :: [atom()].

This filter provides a way of filtering log events based on a domain field in Metadata. This field is optional, and the purpose of using it is to group log events from, for example, a specific functional area. This allows filtering or other specialized treatment in a Logger handler.

A domain field must be a list of atoms, creating smaller and more specialized domains as the list grows longer. The greatest domain is [], which comprises all possible domains.

For example, consider the following domains:

D1 = [otp]
D2 = [otp, sasl]

D1 is the greatest of the two, and is said to be a super-domain of D2. D2 is a sub-domain D1. Both D1 and D2 are sub-domains of [].

The above domains are used for logs originating from Erlang/OTP. D1 specifies that the log event comes from Erlang/OTP in general, and D2 indicates that the log event is a so called SASL report.

The Extra parameter to the domain/2 function is specified when adding the filter via logger:add_primary_filter/2 or logger:add_handler_filter/3.

The filter compares the value of the domain field in the log event's metadata (Domain) against MatchDomain. The filter matches if the value of Compare is:

sub - and Domain is equal to or a sub-domain of MatchDomain, that is, if MatchDomain is a prefix of Domain.

super - and Domain is equal to or a super-domain of MatchDomain, that is, if Domain is a prefix of MatchDomain.

equal - and Domain is equal to MatchDomain.

not_equal - and Domain differs from MatchDomain, or if there is no domain field in metadata.

undefined - and there is no domain field in metadata. In this case MatchDomain must be set to [].

If the filter matches and Action is log, the log event is allowed. If the filter matches and Action is stop, the log event is stopped.

If the filter does not match, it returns ignore, meaning that other filters, or the value of the configuration parameter filter_default, decide if the event is allowed or not.

Log events that do not contain any domain field, match only when Compare is equal to undefined or not_equal.

Example: stop all events with domain [otp, sasl | _]

1> logger:set_handler_config(h1, filter_default, log). % this is the default
ok
2> Filter = {fun logger_filters:domain/2, {stop, sub, [otp, sasl]}}.
...
3> logger:add_handler_filter(h1, no_sasl, Filter).
ok

level(LogEvent, Extra)

(since OTP 21.0)

-spec level(LogEvent, Extra) -> logger:filter_return()
               when
                   LogEvent :: logger:log_event(),
                   Extra :: {Action, Operator, MatchLevel},
                   Action :: log | stop,
                   Operator :: neq | eq | lt | gt | lteq | gteq,
                   MatchLevel :: logger:level().

This filter provides a way of filtering log events based on the log level. It matches log events by comparing the log level with a specified MatchLevel

The Extra parameter is specified when adding the filter via logger:add_primary_filter/2 or logger:add_handler_filter/3.

The filter compares the value of the event's log level (Level) to MatchLevel by calling logger:compare_levels(Level, MatchLevel). The filter matches if the value of Operator is:

neq - and the compare function returns lt or gt.

eq - and the compare function returns eq.

lt - and the compare function returns lt.

gt - and the compare function returns gt.

lteq - and the compare function returns lt or eq.

gteq - and the compare function returns gt or eq.

If the filter matches and Action is log, the log event is allowed. If the filter matches and Action is stop, the log event is stopped.

If the filter does not match, it returns ignore, meaning that other filters, or the value of the configuration parameter filter_default, will decide if the event is allowed or not.

Example: only allow debug level log events

logger:set_handler_config(h1, filter_default, stop).
Filter = {fun logger_filters:level/2, {log, eq, debug}}.
logger:add_handler_filter(h1, debug_only, Filter).
ok

progress(LogEvent, Extra)

(since OTP 21.0)

-spec progress(LogEvent, Extra) -> logger:filter_return()
                  when LogEvent :: logger:log_event(), Extra :: log | stop.

This filter matches all progress reports from supervisor and application_controller.

If Extra is log, the progress reports are allowed. If Extra is stop, the progress reports are stopped.

The filter returns ignore for all other log events.

remote_gl(LogEvent, Extra)

(since OTP 21.0)

-spec remote_gl(LogEvent, Extra) -> logger:filter_return()
                   when LogEvent :: logger:log_event(), Extra :: log | stop.

This filter matches all events originating from a process that has its group leader on a remote node.

If Extra is log, the matching events are allowed. If Extra is stop, the matching events are stopped.

The filter returns ignore for all other log events.

logger_formatter behaviour

Default formatter for Logger.

Each Logger handler has a configured formatter specified as a module and a configuration term. The purpose of the formatter is to translate the log events to a final printable string (unicode:chardata()) which can be written to the output device of the handler. See sections Handlers and Formatters in the Kernel User's Guide for more information.

logger_formatter is the default formatter used by Logger.

See Also

calendar, error_logger, io, io_lib, logger, maps, sasl(6), unicode

Summary

Types

config()

The configuration term for logger_formatter is a map, and the following keys can be set as configuration parameters

metakey()

template()

The template to be used by a logger formatter.

Callbacks: Formatter Callback Functions

check_config(Config)

The function is called by a Logger when formatter configuration is set or modified. The formatter must validate the given configuration and return ok if it is correct, and {error,Reason} if it is faulty.

format(LogEvent, Config)

The function can be called by a log handler to convert a log event term to a printable string. The returned value can, for example, be printed as a log entry to the console or a file using io:put_chars/1,2.

Functions

check_config(Config)

The function is called by Logger when the formatter configuration for a handler is set or modified. It returns ok if the configuration is valid, and {error,term()} if it is faulty.

format(LogEvent, Config)

This the formatter callback function to be called from handlers.

Types

config()

(not exported) (since OTP 21.0)

-type config() ::
          #{chars_limit => pos_integer() | unlimited,
            depth => pos_integer() | unlimited,
            legacy_header => boolean(),
            max_size => pos_integer() | unlimited,
            report_cb => logger:report_cb(),
            single_line => boolean(),
            template => template(),
            time_designator => byte(),
            time_offset => integer() | [byte()]}.

The configuration term for logger_formatter is a map, and the following keys can be set as configuration parameters:

chars_limit = integer() > 0 | unlimited - A positive integer representing the value of the option with the same name to be used when calling io_lib:format/3. This value limits the total number of characters printed for each log event. Notice that this is a soft limit. For a hard truncation limit, see option max_size.

Defaults to unlimited.

depth = integer() > 0 | unlimited - A positive integer representing the maximum depth to which terms shall be printed by this formatter. Format strings passed to this formatter are rewritten. The format controls ~p and ~w are replaced with ~P and ~W, respectively, and the value is used as the depth parameter. For details, see io:format/2,3 in STDLIB.

Defaults to unlimited.

legacy_header = boolean() - If set to true a header field is added to logger_formatter's part of Metadata. The value of this field is a string similar to the header created by the old error_logger event handlers. It can be included in the log event by adding the list [logger_formatter,header] to the template. See the description of the template/0 type for more information.

Defaults to false.

max_size = integer() > 0 | unlimited - A positive integer representing the absolute maximum size a string returned from this formatter can have. If the formatted string is longer, after possibly being limited by chars_limit or depth, it is truncated.

Defaults to unlimited.

report_cb = logger:report_cb/0 - A report callback is used by the formatter to transform log messages on report form to a format string and arguments. The report callback can be specified in the metadata for the log event. If no report callback exists in metadata, logger_formatter will use logger:format_report/1 as default callback.

If this configuration parameter is set, it replaces both the default report callback, and any report callback found in metadata. That is, all reports are converted by this configured function.

single_line = boolean() - If set to true, each log event is printed as a single line. To achieve this, logger_formatter sets the field width to 0 for all ~p and ~P control sequences in the format a string (see io:format/2), and replaces all newlines in the message with ", ". White spaces following directly after newlines are removed. Notice that newlines added by the template parameter are not replaced.

Defaults to true.

template =template/0 - The template describes how the formatted string is composed by combining different data values from the log event. See the description of the template/0 type for more information about this.

time_designator = byte() - Timestamps are formatted according to RFC3339, and the time designator is the character used as date and time separator.

Defaults to $T.

The value of this parameter is used as the time_designator option to calendar:system_time_to_rfc3339/2.

time_offset = integer() | [byte()] - The time offset, either a string or an integer, to be used when formatting the timestamp.

An empty string is interpreted as local time. The values "Z", "z" or 0 are interpreted as Universal Coordinated Time (UTC).

Strings, other than "Z", "z", or "", must be of the form ±[hh]:[mm], for example "-02:00" or "+00:00".

Integers must be in microseconds, meaning that the offset 7200000000 is equivalent to "+02:00".

Defaults to an empty string, meaning that timestamps are displayed in local time. However, for backwards compatibility, if the SASL configuration parameter utc_log=true, the default is changed to "Z", meaning that timestamps are displayed in UTC.

The value of this parameter is used as the offset option to calendar:system_time_to_rfc3339/2.

metakey()

(not exported) (since OTP 21.0)

-type metakey() :: atom() | [atom()].

template()

(not exported) (since OTP 21.0)

-type template() :: [metakey() | {metakey(), template(), template()} | unicode:chardata()].

The template to be used by a logger formatter.

The template is a list of atoms, atom lists, tuples and strings. The atoms level or msg, are treated as placeholders for the severity level and the log message, respectively. Other atoms or atom lists are interpreted as placeholders for metadata, where atoms are expected to match top level keys, and atom lists represent paths to sub keys when the metadata is a nested map. For example the list [key1,key2] is replaced by the value of the key2 field in the nested map below. The atom key1 on its own is replaced by the complete value of the key1 field. The values are converted to strings.

#{key1 => #{key2 => my_value,
            ...}
  ...}

Tuples in the template express if-exist tests for metadata keys. For example, the following tuple says that if key1 exists in the metadata map, print "key1=Value", where Value is the value that key1 is associated with in the metadata map. If key1 does not exist, print nothing.

{key1, ["key1=",key1], []}

Strings in the template are printed literally.

The default value for the template configuration parameter depends on the value of the single_line and legacy_header configuration parameters as follows.

The log event used in the examples is:

?LOG_ERROR("name: ~p~nexit_reason: ~p", [my_name, "It crashed"])

legacy_header = true, single_line = false - Default template: [[logger_formatter,header],"\n",msg,"\n"]

Example log entry:

=ERROR REPORT==== 17-May-2018::18:30:19.453447 ===
name: my_name
exit_reason: "It crashed"

Notice that all eight levels can occur in the heading, not only ERROR, WARNING or INFO as error_logger produces. And microseconds are added at the end of the timestamp.

legacy_header = true, single_line = true - Default template: [[logger_formatter,header],"\n",msg,"\n"]

Notice that the template is here the same as for single_line=false, but the resulting log entry differs in that there is only one line after the heading:

=ERROR REPORT==== 17-May-2018::18:31:06.952665 ===
name: my_name, exit_reason: "It crashed"

legacy_header = false, single_line = true - Default template: [time," ",level,": ",msg,"\n"]

Example log entry:

2018-05-17T18:31:31.152864+02:00 error: name: my_name, exit_reason: "It crashed"

legacy_header = false, single_line = false - Default template: [time," ",level,":\n",msg,"\n"]

Example log entry:

2018-05-17T18:32:20.105422+02:00 error:
name: my_name
exit_reason: "It crashed"

Callbacks: Formatter Callback Functions

check_config(Config)

(since OTP 21.0)

-callback check_config(FConfig) -> ok | {error, Reason}
                          when FConfig :: logger:formatter_config(), Reason :: term().

The function is called by a Logger when formatter configuration is set or modified. The formatter must validate the given configuration and return ok if it is correct, and {error,Reason} if it is faulty.

The following Logger API functions can trigger this callback:

logger:add_handler/3

logger:set_handler_config/2,3

logger:update_handler_config/2,3

logger:update_formatter_config/2

See logger_formatter for an example implementation. logger_formatter is the default formatter used by Logger.

format(LogEvent, Config)

(since OTP 21.0)

-callback format(LogEvent, FConfig) -> FormattedLogEntry
                    when
                        LogEvent :: logger:log_event(),
                        FConfig :: logger:formatter_config(),
                        FormattedLogEntry :: unicode:chardata().

The function can be called by a log handler to convert a log event term to a printable string. The returned value can, for example, be printed as a log entry to the console or a file using io:put_chars/1,2.

See logger_formatter for an example implementation. logger_formatter is the default formatter used by Logger.

Functions

check_config(Config)

(since OTP 21.0)

-spec check_config(Config) -> ok | {error, term()} when Config :: config().

The function is called by Logger when the formatter configuration for a handler is set or modified. It returns ok if the configuration is valid, and {error,term()} if it is faulty.

The following Logger API functions can trigger this callback:

logger:add_handler/3

logger:set_handler_config/2,3

logger:update_handler_config/2

logger:update_formatter_config/2

format(LogEvent, Config)

(since OTP 21.0)

-spec format(LogEvent, Config) -> unicode:chardata()
                when LogEvent :: logger:log_event(), Config :: config().

This the formatter callback function to be called from handlers.

The log event is processed as follows:

If the message is on report form, it is converted to {Format,Args} by calling the report callback. See section Log Message in the Kernel User's Guide for more information about report callbacks and valid forms of log messages.

The message size is limited according to the values of configuration parameters chars_limit and depth.

The full log entry is composed according to the template.

If the final string is too long, it is truncated according to the value of configuration parameter max_size.

logger_handler behaviour

logger_handler behavior module.

The behaviour module for logger handlers. A logger handler is a callback module that is called when a log event has passed all filters and is ready to be logged somewhere. For more information see Handlers in the Users Guide.

See Also

logger_filters, logger_formatter, logger

Summary

Types

config()

Handler configuration data for Logger. The following default values apply

id()

A unique identifier for a handler instance.

olp_config()

Overload protection configuration.

Callbacks

adding_handler(Config1)

The function is called on a temporary process when a new handler is about to be added. The purpose is to verify the configuration and initiate all resources needed by the handler.

changing_config(SetOrUpdate, OldConfig, NewConfig)

The function is called on a temporary process when the configuration for a handler is about to change. The purpose is to verify and act on the new configuration.

filter_config(Config)

The function is called when one of the Logger API functions for fetching the handler configuration is called, for example logger:get_handler_config/1.

log(LogEvent, Config)

The function is called when all primary filters and all handler filters for the handler in question have passed for the given log event. It is called on the client process, that is, the process that issued the log event.

removing_handler(Config)

The function is called on a temporary process when a handler is about to be removed. The purpose is to release all resources used by the handler.

Types

config()

(since OTP 27.0)

-type config() ::
          #{id => id(),
            config => term(),
            level => logger:level() | all | none,
            module => module(),
            filter_default => log | stop,
            filters => [{logger:filter_id(), logger:filter()}],
            formatter => {module(), logger:formatter_config()}}.

Handler configuration data for Logger. The following default values apply:

level => all

filter_default => log

filters => []

formatter => {logger_formatter, DefaultFormatterConfig}

In addition to these, the following fields are automatically inserted by Logger, values taken from the two first parameters to logger:add_handler/3:

id => HandlerId

module => Module

These are read-only and cannot be changed in runtime.

Handler specific configuration data is inserted by the handler callback itself, in a sub structure associated with the field named config. See the logger_std_h and logger_disk_log_h manual pages for information about the specific configuration for these handlers.

See the logger_formatter manual page for information about the default configuration for this formatter.

id()

(since OTP 27.0)

-type id() :: atom().

A unique identifier for a handler instance.

olp_config()

(since OTP 27.0)

-type olp_config() ::
          #{sync_mode_qlen => non_neg_integer(),
            drop_mode_qlen => pos_integer(),
            flush_qlen => pos_integer(),
            burst_limit_enable => boolean(),
            burst_limit_max_count => pos_integer(),
            burst_limit_window_time => pos_integer(),
            overload_kill_enable => boolean(),
            overload_kill_qlen => pos_integer(),
            overload_kill_mem_size => pos_integer(),
            overload_kill_restart_after => non_neg_integer() | infinity}.

Overload protection configuration.

See Protecting the Handler from Overload for more details.

Callbacks

adding_handler(Config1)

(since OTP 21.0) (optional)

-callback adding_handler(Config1) -> {ok, Config2} | {error, Reason}
                            when Config1 :: config(), Config2 :: config(), Reason :: term().

The function is called on a temporary process when a new handler is about to be added. The purpose is to verify the configuration and initiate all resources needed by the handler.

The handler identity is associated with the id key in Config1.

If everything succeeds, the callback function can add possible default values or internal state values to the configuration, and return the adjusted map in {ok,Config2}.

If the configuration is faulty, or if the initiation fails, the callback function must return {error,Reason}.

changing_config(SetOrUpdate, OldConfig, NewConfig)

(since OTP 21.2) (optional)

-callback changing_config(SetOrUpdate, OldConfig, NewConfig) -> {ok, Config} | {error, Reason}
                             when
                                 SetOrUpdate :: set | update,
                                 OldConfig :: config(),
                                 NewConfig :: config(),
                                 Config :: config(),
                                 Reason :: term().

The function is called on a temporary process when the configuration for a handler is about to change. The purpose is to verify and act on the new configuration.

OldConfig is the existing configuration and NewConfig is the new configuration.

The handler identity is associated with the id key in OldConfig.

SetOrUpdate has the value set if the configuration change originates from a call to logger:set_handler_config/2,3, and update if it originates from logger:update_handler_config/2,3. The handler can use this parameter to decide how to update the value of the config field, that is, the handler specific configuration data. Typically, if SetOrUpdate equals set, values that are not specified must be given their default values. If SetOrUpdate equals update, the values found in OldConfig must be used instead.

If everything succeeds, the callback function must return a possibly adjusted configuration in {ok,Config}.

If the configuration is faulty, the callback function must return {error,Reason}.

filter_config(Config)

(since OTP 21.2) (optional)

-callback filter_config(Config) -> FilteredConfig when Config :: config(), FilteredConfig :: config().

The function is called when one of the Logger API functions for fetching the handler configuration is called, for example logger:get_handler_config/1.

It allows the handler to remove internal data fields from its configuration data before it is returned to the caller.

log(LogEvent, Config)

(since OTP 21.0)

-callback log(LogEvent, Config) -> term() when LogEvent :: logger:log_event(), Config :: config().

The function is called when all primary filters and all handler filters for the handler in question have passed for the given log event. It is called on the client process, that is, the process that issued the log event.

The handler identity is associated with the id key in Config.

The handler must log the event.

The return value from this function is ignored by Logger.

removing_handler(Config)

(since OTP 21.0) (optional)

-callback removing_handler(Config) -> ok when Config :: config().

The function is called on a temporary process when a handler is about to be removed. The purpose is to release all resources used by the handler.

The handler identity is associated with the id key in Config.

The return value is ignored by Logger.

logger_std_h

Standard handler for Logger.

This is the standard handler for Logger. Multiple instances of this handler can be added to Logger, and each instance prints logs to standard_io, standard_error, or to file.

The handler has an overload protection mechanism that keeps the handler process and the Kernel application alive during high loads of log events. How overload protection works, and how to configure it, is described in the User's Guide.

To add a new instance of the standard handler, use logger:add_handler/3. The handler configuration argument is a map which can contain general configuration parameters, as documented in the User's Guide, and handler specific parameters. The specific data is stored in a sub map with the key config, and can contain the following parameters:

type = io:standard_io/0 | io:standard_error/0 | file | {device, io:device/0 } - Specifies the log destination.

The value is set when the handler is added, and it cannot be changed in runtime.

Defaults to standard_io, unless parameter file is given, in which case it defaults to file.

file = file:filename/0 - This specifies the name of the log file when the handler is of type file.

The value is set when the handler is added, and it cannot be changed in runtime.

Defaults to the same name as the handler identity, in the current directory.

modes = [ file:mode/0 ] - This specifies the file modes to use when opening the log file, see file:open/2. If modes are not specified, the default list used is [raw,append,delayed_write]. If modes are specified, the list replaces the default modes list with the following adjustments:

If raw is not found in the list, it is added.

If none of write, append or exclusive is found in the list, append is added.

If none of delayed_write or {delayed_write,Size,Delay} is found in the list, delayed_write is added.

Log files are always UTF-8 encoded. The encoding cannot be changed by setting the mode {encoding,Encoding}.

The value is set when the handler is added, and it cannot be changed in runtime.

Defaults to [raw,append,delayed_write].

max_no_bytes = pos_integer/0 | infinity - This parameter specifies if the log file should be rotated or not. The value infinity means the log file will grow indefinitely, while an integer value specifies at which file size (bytes) the file is rotated.

Defaults to infinity.

max_no_files = non_neg_integer/0 - This parameter specifies the number of rotated log file archives to keep. This has meaning only if max_no_bytes is set to an integer value.

The log archives are named FileName.0, FileName.1, ... FileName.N, where FileName is the name of the current log file. FileName.0 is the newest of the archives. The maximum value for N is the value of max_no_files minus 1.

Notice that setting this value to 0 does not turn off rotation. It only specifies that no archives are kept.

Defaults to 0.

compress_on_rotate = boolean/0 - This parameter specifies if the rotated log file archives shall be compressed or not. If set to true, all archives are compressed with gzip, and renamed to FileName.N.gz

compress_on_rotate has no meaning if max_no_bytes has the value infinity.

Defaults to false.

file_check = non_neg_integer/0 - When logger_std_h logs to a file, it reads the file information of the log file prior to each write operation. This is to make sure the file still exists and has the same inode as when it was opened. This implies some performance loss, but ensures that no log events are lost in the case when the file has been removed or renamed by an external actor.

In order to allow minimizing the performance loss, the file_check parameter can be set to a positive integer value, N. The handler will then skip reading the file information prior to writing, as long as no more than N milliseconds have passed since it was last read.

Notice that the risk of losing log events grows when the file_check value grows.

Defaults to 0.

filesync_repeat_interval = pos_integer/0 | no_repeat - This value, in milliseconds, specifies how often the handler does a file sync operation to write buffered data to disk. The handler attempts the operation repeatedly, but only performs a new sync if something has actually been logged.

If no_repeat is set as value, the repeated file sync operation is disabled, and it is the operating system settings that determine how quickly or slowly data is written to disk. The user can also call the filesync/1 function to perform a file sync.

Defaults to 5000 milliseconds.

Other configuration parameters exist, to be used for customizing the overload protection behaviour. The same parameters are used both in the standard handler and the disk_log handler, and are documented in the User's Guide.

Notice that if changing the configuration of the handler in runtime, the type, file, or modes parameters must not be modified.

Example of adding a standard handler:

logger:add_handler(my_standard_h, logger_std_h,
                   #{config => #{file => "./system_info.log",
                                 filesync_repeat_interval => 1000}}).

To set the default handler, that starts initially with the Kernel application, to log to file instead of standard_io, change the Kernel default logger configuration. Example:

erl -kernel logger '[{handler,default,logger_std_h,
                      #{config => #{file => "./log.log"}}}]'

An example of how to replace the standard handler with a disk_log handler at startup is found in the logger_disk_log_h manual.

See Also

logger, logger_disk_log_h

Summary

Functions

filesync(Name)

Write buffered data to disk.

Functions

filesync(Name)

(since OTP 21.0)

-spec filesync(Name) -> ok | {error, Reason}
                  when Name :: atom(), Reason :: handler_busy | {badarg, term()}.

Write buffered data to disk.

wrap_log_reader

A service to read internally formatted wrap disk logs.

This module makes it possible to read internally formatted wrap disk logs, see disk_log. wrap_log_reader does not interfere with disk_log activities; there is however a bug in this version of the wrap_log_reader, see section Known Limitations.

A wrap disk log file consists of many files, called index files. A log file can be opened and closed. Also, a single index file can be opened separately. If a non-existent or non-internally formatted file is opened, an error message is returned. If the file is corrupt, no attempt is made to repair it, but an error message is returned.

If a log is configured to be distributed, it is possible that all items are not logged on all nodes. wrap_log_reader only reads the log on the called node; it is up to the user to be sure that all items are read.

Known Limitations

This version of wrap_log_reader does not detect if disk_log wraps to a new index file between a call to wrap_log_reader:open/1 and the first call to wrap_log_reader:chunk/1. If this occurs, the call to chunk/1 reads the last logged items in the log file, as the opened index file was truncated by disk_log.

Summary

Types

chunk_ret()

continuation()

Continuation returned by open/1,2 or chunk/1,2.

open_ret()

Functions

chunk(Continuation)

Equivalent to chunk(Continuation, infinity).

chunk(Continuation, N)

Enables to efficiently read the terms that are appended to a log. Minimises disk I/O by reading 64 kilobyte chunks from the file.

close(Continuation)

Closes a log file properly.

open(Filename)

Equivalent to open(Filename, ...) except that the whole wrap log file is read.

open(Filename, N)

Filename specifies the name of the file to be read.

Types

chunk_ret()

(not exported)

-type chunk_ret() ::
          {Continuation2 :: term(), Terms :: [term()]} |
          {Continuation2 :: term(), Terms :: [term()], Badbytes :: non_neg_integer()} |
          {Continuation2 :: term(), eof} |
          {error, Reason :: term()}.

continuation()

-opaque continuation()

Continuation returned by open/1,2 or chunk/1,2.

open_ret()

(not exported)

-type open_ret() :: {ok, Continuation :: continuation()} | {error, Reason :: tuple()}.

Functions

chunk(Continuation)

-spec chunk(Continuation) -> chunk_ret() when Continuation :: continuation().

Equivalent to chunk(Continuation, infinity).

chunk(Continuation, N)

-spec chunk(Continuation, N) -> chunk_ret()
               when Continuation :: continuation(), N :: infinity | pos_integer().

Enables to efficiently read the terms that are appended to a log. Minimises disk I/O by reading 64 kilobyte chunks from the file.

The first time chunk/2 is called, an initial continuation returned from open/1 or open/2 must be provided.

When chunk/2 is called, N controls the maximum number of terms that are read from the log in each chunk. infinity means that all the terms contained in the 8K chunk are read. If less than N terms are returned, this does not necessarily mean that end of file is reached.

Returns a tuple {Continuation2, Terms}, where Terms is a list of terms found in the log. Continuation2 is yet another continuation that must be passed on to any subsequent calls to chunk(). With a series of calls to chunk(), it is then possible to extract all terms from a log.

Returns a tuple {Continuation2, Terms, Badbytes} if the log is opened in read only mode and the read chunk is corrupt. Badbytes indicates the number of non-Erlang terms found in the chunk. Notice that the log is not repaired.

Returns {Continuation2, eof} when the end of the log is reached, and {error, Reason} if an error occurs.

The returned continuation either is or is not valid in the next call to this function. This is because the log can wrap and delete the file into which the continuation points. To ensure this does not occur, the log can be blocked during the search.

close(Continuation)

-spec close(Continuation) -> ok | {error, Reason}
               when Continuation :: continuation(), Reason :: file:posix().

Closes a log file properly.

open(Filename)

-spec open(Filename) -> open_ret() when Filename :: string() | atom().

Equivalent to open(Filename, ...) except that the whole wrap log file is read.

open(Filename, N)

-spec open(Filename, N) -> open_ret() when Filename :: string() | atom(), N :: integer().

Filename specifies the name of the file to be read.

N specifies the index of the file to be read. Use open/1 to read the entire wrap log.

Returns {ok, Continuation} if the log/index file is opened successfully. Continuation is to be used when chunking or closing the file.

Returns {error, Reason} for all errors.

auth

This module is deprecated. See each function for what to use instead.

Erlang network authentication server.

For a description of the Magic Cookie system, refer to Distributed Erlang in the Erlang Reference Manual.

Summary

Types

cookie()

Functions

cookie() deprecated

Use erlang:get_cookie() in ERTS instead.

cookie(TheCookie) deprecated

Use erlang:set_cookie(node(), Cookie) in ERTS instead.

is_auth(Node) deprecated

Returns yes if communication with Node is authorized.

node_cookie([Node, Cookie]) deprecated

Equivalent to node_cookie(Node, Cookie).

node_cookie(Node, Cookie) deprecated

Sets the magic cookie of Node to Cookie and verifies the status of the authorization.

Types

cookie()

(not exported)

-type cookie() :: atom().

Functions

cookie()

This function is deprecated. auth:cookie/0 is deprecated; use erlang:get_cookie/0 instead.

-spec cookie() -> Cookie when Cookie :: cookie().

Use erlang:get_cookie() in ERTS instead.

cookie(TheCookie)

This function is deprecated. auth:cookie/1 is deprecated; use erlang:set_cookie/2 instead.

-spec cookie(TheCookie) -> true when TheCookie :: Cookie | [Cookie], Cookie :: cookie().

Use erlang:set_cookie(node(), Cookie) in ERTS instead.

is_auth(Node)

This function is deprecated. auth:is_auth/1 is deprecated; use net_adm:ping/1 instead.

-spec is_auth(Node) -> yes | no when Node :: node().

Returns yes if communication with Node is authorized.

Use net_adm:ping(Node) instead.

Notice that a connection to Node is established in this case. Returns no if Node does not exist or communication is not authorized (it has another cookie than auth thinks it has).

node_cookie([Node, Cookie])

This function is deprecated. auth:node_cookie/1 is deprecated; use erlang:set_cookie/2 and net_adm:ping/1 instead.

-spec node_cookie(Cookies :: [node() | cookie(), ...]) -> yes | no.

Equivalent to node_cookie(Node, Cookie).

node_cookie(Node, Cookie)

This function is deprecated. auth:node_cookie/2 is deprecated; use erlang:set_cookie/2 and net_adm:ping/1 instead.

-spec node_cookie(Node, Cookie) -> yes | no when Node :: node(), Cookie :: cookie().

Sets the magic cookie of Node to Cookie and verifies the status of the authorization.

Equivalent to calling erlang:set_cookie(Node, Cookie), followed by auth:is_auth(Node).

erl_boot_server

Boot server for other Erlang machines.

This server is used to assist diskless Erlang nodes that fetch all Erlang code from another machine.

This server is used to fetch all code, including the start script, if an Erlang runtime system is started with command-line flag -loader inet. All hosts specified with command-line flag -hosts Host must have one instance of this server running.

This server can be started with the Kernel configuration parameter start_boot_server.

The erl_boot_server can read regular files and files in archives. See code and erl_prim_loader in ERTS.

Warning

The support for loading code from archive files is experimental. It is released before it is ready to obtain early feedback. The file format, semantics, interfaces, and so on, can be changed in a future release.

SEE ALSO

erts:init, erts:erl_prim_loader

Summary

Functions

add_slave(Slave)

Adds a Slave node to the list of allowed slave hosts.

delete_slave(Slave)

Deletes a Slave node from the list of allowed slave hosts.

start(Slaves)

The same as start(Slaves, #{}).

start(Slaves, Options)

Starts the boot server. Slaves is a list of IP addresses for hosts, which are allowed to use this server as a boot server. Options is a map with configuration options.

start_link(Slaves)

The same as start_link(Slaves, #{}).

start_link(Slaves, Options)

The same as start(Slaves, Options), but it also links to the caller.

which_slaves()

Returns the current list of allowed slave hosts.

Functions

add_slave(Slave)

-spec add_slave(Slave) -> ok | {error, Reason}
                   when
                       Slave :: Host,
                       Host :: inet:ip_address() | inet:hostname(),
                       Reason :: {badarg, Slave}.

Adds a Slave node to the list of allowed slave hosts.

delete_slave(Slave)

-spec delete_slave(Slave) -> ok | {error, Reason}
                      when
                          Slave :: Host,
                          Host :: inet:ip_address() | inet:hostname(),
                          Reason :: {badarg, Slave}.

Deletes a Slave node from the list of allowed slave hosts.

start(Slaves)

-spec start(Slaves) -> {ok, Pid} | {error, Reason}
               when
                   Slaves :: [Host],
                   Host :: inet:ip_address() | inet:hostname(),
                   Pid :: pid(),
                   Reason :: any().

The same as start(Slaves, #{}).

start(Slaves, Options)

(since OTP 29.0)

-spec start(Slaves, Options) -> {ok, Pid} | {error, Reason}
               when
                   Slaves :: [Host],
                   Host :: inet:ip_address() | inet:hostname(),
                   Options :: #{listen_port => inet:port_number()},
                   Pid :: pid(),
                   Reason :: any().

Starts the boot server. Slaves is a list of IP addresses for hosts, which are allowed to use this server as a boot server. Options is a map with configuration options.

The boot server listening port can be configured with listen_port. If an empty map is provided, or listen_port is zero, then an ephemeral port is used.

start_link(Slaves)

-spec start_link(Slaves) -> {ok, Pid} | {error, Reason}
                    when
                        Slaves :: [Host],
                        Host :: inet:ip_address() | inet:hostname(),
                        Pid :: pid(),
                        Reason :: any().

The same as start_link(Slaves, #{}).

start_link(Slaves, Options)

(since OTP 29.0)

-spec start_link(Slaves, Options) -> {ok, Pid} | {error, Reason}
                    when
                        Slaves :: [Host],
                        Host :: inet:ip_address() | inet:hostname(),
                        Options :: #{listen_port => inet:port_number()},
                        Pid :: pid(),
                        Reason :: any().

The same as start(Slaves, Options), but it also links to the caller.

which_slaves()

-spec which_slaves() -> Slaves
                      when
                          Slaves :: [Slave],
                          Slave :: {Netmask :: inet:ip_address(), Address :: inet:ip_address()}.

Returns the current list of allowed slave hosts.

erl_epmd

Erlang interface towards epmd

This module communicates with the EPMD daemon, see epmd. To implement your own epmd module please see ERTS User's Guide: How to Implement an Alternative Node Discovery for Erlang Distribution

Summary

Functions

address_please(Name, Host, AddressFamily)

Called by the distribution module to resolves the Host to an IP address of a remote node.

listen_port_please(Name, Host)

Called by the distribution module to get which port the local node should listen to when accepting new distribution requests.

names(Host)

Called by net_adm:names/0. Host defaults to the localhost. Returns the names and associated port numbers of the Erlang nodes that epmd registered at the specified host. Returns {error, address} if epmd is not operational.

port_please(Name, Host)

Equivalent to port_please(Name, Host, infinity).

port_please(Name, Host, Timeout)

Requests the distribution port for the given node of an EPMD instance. Together with the port it returns a distribution protocol version which has been 5 since Erlang/OTP R6.

register_node(Name, Port)

Equivalent to register_node(Name, Port, inet).

register_node(Name, Port, Driver)

Registers the node with epmd and tells epmd what port will be used for the current node. It returns a creation number. This number is incremented on each register to help differentiate a new node instance connecting to epmd with the same name.

start_link()

This function is invoked as this module is added as a child of the erl_distribution supervisor.

Functions

address_please(Name, Host, AddressFamily)

(since OTP 21.0)

-spec address_please(Name, Host, AddressFamily) -> Success | {error, term()}
                        when
                            Name :: string(),
                            Host :: string() | inet:ip_address(),
                            AddressFamily :: inet | inet6,
                            Port :: non_neg_integer(),
                            Version :: non_neg_integer(),
                            Success :: {ok, inet:ip_address()} | {ok, inet:ip_address(), Port, Version}.

Called by the distribution module to resolves the Host to an IP address of a remote node.

As an optimization this function may also return the port and version of the remote node. If port and version are returned port_please/3 will not be called.

listen_port_please(Name, Host)

(since OTP 23.0)

-spec listen_port_please(Name, Host) -> {ok, Port}
                            when
                                Name :: atom() | string(),
                                Host :: atom() | string() | inet:ip_address(),
                                Port :: non_neg_integer().

Called by the distribution module to get which port the local node should listen to when accepting new distribution requests.

names(Host)

(since OTP 21.0)

-spec names(Host) -> {ok, [{Name, Port}]} | {error, Reason}
               when
                   Host :: atom() | string() | inet:ip_address(),
                   Name :: string(),
                   Port :: non_neg_integer(),
                   Reason :: address | file:posix().

Called by net_adm:names/0. Host defaults to the localhost. Returns the names and associated port numbers of the Erlang nodes that epmd registered at the specified host. Returns {error, address} if epmd is not operational.

Example:

(arne@dunn)1> erl_epmd:names(localhost).
{ok,[{"arne",40262}]}

port_please(Name, Host)

(since OTP 21.0)

-spec port_please(Name, Host) -> {port, Port, Version} | noport | closed | {error, term()}
                     when
                         Name :: atom() | string(),
                         Host :: atom() | string() | inet:ip_address(),
                         Port :: non_neg_integer(),
                         Version :: non_neg_integer().

Equivalent to port_please(Name, Host, infinity).

port_please(Name, Host, Timeout)

(since OTP 21.0)

-spec port_please(Name, Host, Timeout) -> {port, Port, Version} | noport | closed | {error, term()}
                     when
                         Name :: atom() | string(),
                         Host :: atom() | string() | inet:ip_address(),
                         Timeout :: non_neg_integer() | infinity,
                         Port :: non_neg_integer(),
                         Version :: non_neg_integer().

Requests the distribution port for the given node of an EPMD instance. Together with the port it returns a distribution protocol version which has been 5 since Erlang/OTP R6.

register_node(Name, Port)

(since OTP 21.0)

-spec register_node(Name, Port) -> Result
                       when
                           Name :: string(),
                           Port :: non_neg_integer(),
                           Creation :: non_neg_integer(),
                           Result :: {ok, Creation} | {error, already_registered} | term().

Equivalent to register_node(Name, Port, inet).

register_node(Name, Port, Driver)

(since OTP 21.0)

-spec register_node(Name, Port, Driver) -> Result
                       when
                           Name :: string(),
                           Port :: non_neg_integer(),
                           Driver :: inet_tcp | inet6_tcp | inet | inet6,
                           Creation :: non_neg_integer() | -1,
                           Result :: {ok, Creation} | {error, already_registered} | term().

Registers the node with epmd and tells epmd what port will be used for the current node. It returns a creation number. This number is incremented on each register to help differentiate a new node instance connecting to epmd with the same name.

After the node has successfully registered with epmd it will automatically attempt reconnect to the daemon if the connection is broken.

start_link()

(since OTP 21.0)

-spec start_link() -> {ok, pid()} | ignore | {error, term()}.

This function is invoked as this module is added as a child of the erl_distribution supervisor.

erpc

Enhanced Remote Procedure Call

This module provide services similar to Remote Procedure Calls. A remote procedure call is a method to call a function on a remote node and collect the answer. It is used for collecting information on a remote node, or for running a function with some specific side effects on the remote node.

This is an enhanced subset of the operations provided by the rpc module. Enhanced in the sense that it makes it possible to distinguish between returned value, raised exceptions, and other errors. erpc also has better performance and scalability than the original rpc implementation. However, current rpc module will utilize erpc in order to also provide these properties when possible.

In order for an erpc operation to succeed, the remote node also needs to support erpc. Typically only ordinary Erlang nodes as of OTP 23 have erpc support.

Note that it is up to the user to ensure that correct code to execute via erpc is available on the involved nodes.

Note

For some important information about distributed signals, see the Blocking Signaling Over Distribution section in the Processes chapter of the Erlang Reference Manual. Blocking signaling can, for example, cause timeouts in erpc to be significantly delayed.

Summary

Types

call_options()

Options to be used in call/3,5 and multicall/3,5 functions.

caught_call_exception()

request_id()

An opaque request identifier. For more information see send_request/4.

request_id_collection()

An opaque collection of request identifiers (request_id/0) where each request identifier can be associated with a label chosen by the user. For more information see reqids_new/0.

stack_item()

timeout_time()

The timeout time used by erpc functions.

Functions

call(Node, Fun)

Equivalent to call(Node, Fun, #{timeout => infinity}).

call(Node, Fun, TimeoutOrOptions)

Equivalent to erpc:call(Node, erlang, apply, [Fun,[]], #{timeout => Timeout}).

call(Node, Module, Function, Args)

Equivalent to call(Node, Module, Function, Args, #{timeout => infinity}).

call(Node, Module, Function, Args, TimeoutOrOptions)

Evaluates apply(Module, Function, Args) on node Node and returns the corresponding value Result.

cast(Node, Fun)

Equivalent to erpc:cast(Node,erlang,apply,[Fun,[]]).

cast(Node, Module, Function, Args)

Evaluates apply(Module, Function, Args) on node Node. No response is delivered to the calling process. cast() returns immediately after the cast request has been sent. Any failures beside bad arguments are silently ignored.

check_response(Message, RequestId)

Check if a message is a response to a call request previously made by the calling process using send_request/4.

check_response(Message, RequestIdCollection, Delete)

Check if a message is a response to a call request corresponding to a request identifier saved in RequestIdCollection. All request identifiers of RequestIdCollection must correspond to requests that have been made using send_request/4 or send_request/6, and all requests must have been made by the process calling this function.

multicall(Nodes, Fun)

Equivalent to multicall(Nodes, Fun, #{timeout => infinity}).

multicall(Nodes, Fun, TimeoutOrOptions)

Equivalent to erpc:multicall(Nodes, erlang, apply, [Fun,[]], #{timeout => Timeout}).

multicall(Nodes, Module, Function, Args)

Equivalent to multicall(Nodes, Module, Function, Args, #{timeout => infinity}).

multicall(Nodes, Module, Function, Args, TimeoutOrOptions)

Performs multiple call operations in parallel on multiple nodes.

multicast(Nodes, Fun)

Equivalent to erpc:multicast(Nodes,erlang,apply,[Fun,[]]).

multicast(Nodes, Module, Function, Args)

Evaluates apply(Module, Function, Args) on the nodes Nodes. No response is delivered to the calling process. multicast() returns immediately after the cast requests have been sent. Any failures beside bad arguments are silently ignored.

receive_response(RequestId)

Equivalent to receive_response(RequestId, infinity).

receive_response(RequestId, Timeout)

Receive a response to a call request previously made by the calling process using send_request/4.

receive_response(RequestIdCollection, Timeout, Delete)

Receive a response to a call request corresponding to a request identifier saved in RequestIdCollection. All request identifiers of RequestIdCollection must correspond to requests that have been made using send_request/4 or send_request/6, and all requests must have been made by the process calling this function.

reqids_add(RequestId, Label, RequestIdCollection)

Saves RequestId and associates a Label with the request identifier by adding this information to RequestIdCollection and returning the resulting request identifier collection.

reqids_new()

Returns a new empty request identifier collection. A request identifier collection can be utilized in order the handle multiple outstanding requests.

reqids_size(RequestIdCollection)

Returns the amount of request identifiers saved in RequestIdCollection.

reqids_to_list(RequestIdCollection)

Returns a list of {RequestId, Label} tuples which corresponds to all request identifiers with their associated labels present in the RequestIdCollection collection.

send_request(Node, Fun)

Equivalent to erpc:send_request(Node, erlang, apply, [Fun, []]).

send_request/4

Send an asynchronous call request to the node Node.

send_request(Node, Module, Function, Args, Label, RequestIdCollection)

Send an asynchronous call request to the node Node. The Label will be associated with the request identifier of the operation and added to the returned request identifier collection NewRequestIdCollection. The collection can later be used in order to get one response corresponding to a request in the collection by passing the collection as argument to receive_response/3, wait_response/3, or, check_response/3.

wait_response(RequestId)

Equivalent to erpc:wait_response(RequestId, 0). That is, poll for a response message to a call request previously made by the calling process.

wait_response(RequestId, WaitTime)

Wait or poll for a response message to a call request previously made by the calling process using send_request/4.

wait_response(RequestIdCollection, WaitTime, Delete)

Wait or poll for a response to a call request corresponding to a request identifier saved in RequestIdCollection. All request identifiers of RequestIdCollection must correspond to requests that have been made using send_request/4 or send_request/6, and all requests must have been made by the process calling this function.

Types

call_options()

(since OTP 28.0)

-type call_options() ::
          #{timeout => Timeout :: timeout_time(), always_spawn => AlwaysSpawn :: boolean()}.

Options to be used in call/3,5 and multicall/3,5 functions.

timeout - Upper time limit for call operations to complete, see timeout_time/0. Default: infinity.

always_spawn - If true, the apply() will always be performed in a freshly spawned process. If false, the calling process may be used instead, if possible. Default: false.

caught_call_exception()

(not exported) (since OTP 23.0)

-type caught_call_exception() ::
          {throw, Throw :: term()} |
          {exit, {exception, Reason :: term()}} |
          {error, {exception, Reason :: term(), StackTrace :: [stack_item()]}} |
          {exit, {signal, Reason :: term()}} |
          {error, {erpc, Reason :: term()}}.

request_id()

(since OTP 23.0)

-opaque request_id()

An opaque request identifier. For more information see send_request/4.

request_id_collection()

(since OTP 23.0)

-opaque request_id_collection()

An opaque collection of request identifiers (request_id/0) where each request identifier can be associated with a label chosen by the user. For more information see reqids_new/0.

stack_item()

(not exported) (since OTP 23.0)

-type stack_item() ::
          {Module :: atom(),
           Function :: atom(),
           Arity :: arity() | (Args :: [term()]),
           Location :: [{file, Filename :: string()} | {line, Line :: pos_integer()}]}.

timeout_time()

(since OTP 23.0)

-type timeout_time() :: 0..4294967295 | infinity | {abs, integer()}.

The timeout time used by erpc functions.

The value can be:

0..4294967295 - Timeout relative to current time in milliseconds.

infinity - Infinite timeout. That is, the operation will never time out.

{abs, Timeout} - An absolute Erlang monotonic time timeout in milliseconds. That is, the operation will time out when erlang:monotonic_time(millisecond) returns a value larger than or equal to Timeout. Timeout is not allowed to identify a time further into the future than 4294967295 milliseconds. Identifying the timeout using an absolute timeout value is especially handy when you have a deadline for responses corresponding to a complete collection of requests (request_id_collection/0), since you do not have to recalculate the relative time until the deadline over and over again.

Functions

call(Node, Fun)

(since OTP 23.0)

-spec call(Node, Fun) -> Result when Node :: node(), Fun :: function(), Result :: term().

Equivalent to call(Node, Fun, #{timeout => infinity}).

call(Node, Fun, TimeoutOrOptions)

(since OTP 23.0)

-spec call(Node, Fun, TimeoutOrOptions) -> Result
              when
                  Node :: node(),
                  Fun :: function(),
                  TimeoutOrOptions :: timeout_time() | call_options(),
                  Result :: term().

Equivalent to erpc:call(Node, erlang, apply, [Fun,[]], #{timeout => Timeout}).

May raise all the same exceptions as call/5 plus an {erpc, badarg} error exception if Fun is not a fun of zero arity.

call(Node, Module, Function, Args)

(since OTP 23.0)

-spec call(Node, Module, Function, Args) -> Result
              when
                  Node :: node(),
                  Module :: atom(),
                  Function :: atom(),
                  Args :: [term()],
                  Result :: term().

Equivalent to call(Node, Module, Function, Args, #{timeout => infinity}).

call(Node, Module, Function, Args, TimeoutOrOptions)

(since OTP 23.0)

-spec call(Node, Module, Function, Args, TimeoutOrOptions) -> Result
              when
                  Node :: node(),
                  Module :: atom(),
                  Function :: atom(),
                  Args :: [term()],
                  TimeoutOrOptions :: timeout_time() | call_options(),
                  Result :: term().

Evaluates apply(Module, Function, Args) on node Node and returns the corresponding value Result.

TimeoutOrOptions can be either a timeout time or a call options map (since OTP 28.0).

The call() function only returns if the applied function successfully returned without raising any uncaught exceptions, the operation did not time out, and no failures occurred. In all other cases an exception is raised. The following exceptions, listed by exception class, can currently be raised by call():

throw - The applied function called throw(Value) and did not catch this exception. The exception reason Value equals the argument passed to throw/1.

exit - Exception reason:

{exception, ExitReason} - The applied function called exit(ExitReason) and did not catch this exception. The exit reason ExitReason equals the argument passed to exit/1.

{signal, ExitReason} - The process that applied the function received an exit signal and terminated due to this signal. The process terminated with exit reason ExitReason.

error - Exception reason:

{exception, ErrorReason, StackTrace} - A runtime error occurred which raised an error exception while applying the function, and the applied function did not catch the exception. The error reason ErrorReason indicates the type of error that occurred. StackTrace is formatted as when caught in a try/catch construct. The StackTrace is limited to the applied function and functions called by it.

{erpc, ERpcErrorReason} - The erpc operation failed. The following ERpcErrorReasons are the most common ones:

badarg - If any one of these are true:

Node is not an atom.

Module is not an atom.

Function is not an atom.

Args is not a list. Note that the list is not verified to be a proper list at the client side.

Timeout is invalid.

noconnection - The connection to Node was lost or could not be established. The function may or may not be applied.

system_limit - The erpc operation failed due to some system limit being reached. This typically due to failure to create a process on the remote node Node, but can be other things as well.

timeout - The erpc operation timed out. The function may or may not be applied.

notsup - The remote node Node does not support this erpc operation.

If the erpc operation fails, but it is unknown if the function is/will be applied (that is, a timeout or a connection loss), the caller will not receive any further information about the result if/when the applied function completes. If the applied function explicitly communicates with the calling process, such communication may, of course, reach the calling process.

Note

If the always_spawn option is false (which is the default), you cannot make any assumptions about the process that will perform the apply(). It may be the calling process itself, or a freshly spawned process.

cast(Node, Fun)

(since OTP 23.0)

-spec cast(Node, Fun) -> ok when Node :: node(), Fun :: function().

Equivalent to erpc:cast(Node,erlang,apply,[Fun,[]]).

cast/2 fails with an {erpc, badarg} error exception if:

Node is not an atom.

Fun is not a a fun of zero arity.

cast(Node, Module, Function, Args)

(since OTP 23.0)

-spec cast(Node, Module, Function, Args) -> ok
              when Node :: node(), Module :: atom(), Function :: atom(), Args :: [term()].

Evaluates apply(Module, Function, Args) on node Node. No response is delivered to the calling process. cast() returns immediately after the cast request has been sent. Any failures beside bad arguments are silently ignored.

cast/4 fails with an {erpc, badarg} error exception if:

Node is not an atom.

Module is not an atom.

Function is not an atom.

Args is not a list. Note that the list is not verified to be a proper list at the client side.

check_response(Message, RequestId)

(since OTP 23.0)

-spec check_response(Message, RequestId) -> {response, Result} | no_response
                        when Message :: term(), RequestId :: request_id(), Result :: term().

Check if a message is a response to a call request previously made by the calling process using send_request/4.

RequestId should be the value returned from the previously made send_request/4 call, and the corresponding response should not already have been received and handled to completion by check_response/2, receive_response/2, or wait_response/2. Message is the message to check.

If Message does not correspond to the response, the atom no_response is returned. If Message corresponds to the response, the call operation is completed and either the result is returned as {response, Result} where Result corresponds to the value returned from the applied function or an exception is raised. The exceptions that can be raised corresponds to the same exceptions as can be raised by call/4. That is, no {erpc, timeout} error exception can be raised. check_response() will fail with an {erpc, badarg} exception if/when an invalid RequestId is detected.

If the erpc operation fails, but it is unknown if the function is/will be applied (that is, a connection loss), the caller will not receive any further information about the result if/when the applied function completes. If the applied function explicitly communicates with the calling process, such communication may, of course, reach the calling process.

check_response(Message, RequestIdCollection, Delete)

(since OTP 25.0)

-spec check_response(Message, RequestIdCollection, Delete) ->
                        {{response, Result}, Label, NewRequestIdCollection} | no_response | no_request
                        when
                            Message :: term(),
                            RequestIdCollection :: request_id_collection(),
                            Delete :: boolean(),
                            Result :: term(),
                            Label :: term(),
                            NewRequestIdCollection :: request_id_collection().

Check if a message is a response to a call request corresponding to a request identifier saved in RequestIdCollection. All request identifiers of RequestIdCollection must correspond to requests that have been made using send_request/4 or send_request/6, and all requests must have been made by the process calling this function.

Label is the label associated with the request identifier of the request that the response corresponds to. A request identifier is associated with a label when adding a request identifier in a request identifier collection, or when sending the request using send_request/6.

Compared to check_response/2, the returned result associated with a specific request identifier or an exception associated with a specific request identifier will be wrapped in a 3-tuple. The first element of this tuple equals the value that would have been produced by check_response/2, the second element equals the Label associated with the specific request identifier, and the third element NewRequestIdCollection is a possibly modified request identifier collection. The error exception {erpc, badarg} is not associated with any specific request identifier, and will hence not be wrapped.

If RequestIdCollection is empty, the atom no_request will be returned. If Message does not correspond to any of the request identifiers in RequestIdCollection, the atom no_response is returned.

If Delete equals true, the association with Label will have been deleted from RequestIdCollection in the resulting NewRequestIdCollection. If Delete equals false, NewRequestIdCollection will equal RequestIdCollection. Note that deleting an association is not for free and that a collection containing already handled requests can still be used by subsequent calls to check_response/3, receive_response/3, and wait_response/3. However, without deleting handled associations, the above calls will not be able to detect when there are no more outstanding requests to handle, so you will have to keep track of this some other way than relying on a no_request return. Note that if you pass a collection only containing associations of already handled or abandoned requests to check_response/3, it will always return no_response.

Note that a response might have been consumed uppon an {erpc, badarg} exception and if so, will be lost for ever.

multicall(Nodes, Fun)

(since OTP 23.0)

-spec multicall(Nodes, Fun) -> Result when Nodes :: [atom()], Fun :: function(), Result :: term().

Equivalent to multicall(Nodes, Fun, #{timeout => infinity}).

multicall(Nodes, Fun, TimeoutOrOptions)

(since OTP 23.0)

-spec multicall(Nodes, Fun, TimeoutOrOptions) -> Result
                   when
                       Nodes :: [atom()],
                       Fun :: function(),
                       TimeoutOrOptions :: timeout_time() | call_options(),
                       Result :: term().

Equivalent to erpc:multicall(Nodes, erlang, apply, [Fun,[]], #{timeout => Timeout}).

May raise all the same exceptions as multicall/5 plus an {erpc, badarg} error exception if Fun is not a fun of zero arity.

multicall(Nodes, Module, Function, Args)

(since OTP 23.0)

-spec multicall(Nodes, Module, Function, Args) -> Result
                   when
                       Nodes :: [atom()],
                       Module :: atom(),
                       Function :: atom(),
                       Args :: [term()],
                       Result :: [{ok, ReturnValue :: term()} | caught_call_exception()].

Equivalent to multicall(Nodes, Module, Function, Args, #{timeout => infinity}).

multicall(Nodes, Module, Function, Args, TimeoutOrOptions)

(since OTP 23.0)

-spec multicall(Nodes, Module, Function, Args, TimeoutOrOptions) -> Result
                   when
                       Nodes :: [atom()],
                       Module :: atom(),
                       Function :: atom(),
                       Args :: [term()],
                       TimeoutOrOptions :: timeout_time() | call_options(),
                       Result :: [{ok, ReturnValue :: term()} | caught_call_exception()].

Performs multiple call operations in parallel on multiple nodes.

That is, evaluates apply(Module, Function, Args) on the nodes Nodes in parallel.

TimeoutOrOptions can be either a timeout time or a call options map (since OTP 28.0).

The result is returned as a list where the result from each node is placed at the same position as the node name is placed in Nodes. Each item in the resulting list is formatted as either:

{ok, Result} - The call operation for this specific node returned Result.

{Class, ExceptionReason} - The call operation for this specific node raised an exception of class Class with exception reason ExceptionReason. These correspond to the exceptions that call/5 can raise.

multicall/5 fails with an {erpc, badarg} error exception if:

Nodes is not a proper list of atoms. Note that some requests may already have been sent when the failure occurs. That is, the function may or may not be applied on some nodes.

Module is not an atom.

Function is not an atom.

Args is not a list. Note that the list is not verified to be a proper list at the client side.

The call erpc:multicall(Nodes, Module, Function, Args) is equivalent to the call erpc:multicall(Nodes, Module, Function, Args, infinity). These calls are also equivalent to calling my_multicall(Nodes, Module, Function, Args) below if one disregard performance and failure behavior. multicall() can utilize a selective receive optimization which removes the need to scan the message queue from the beginning in order to find a matching message. The send_request()/receive_response() combination can, however, not utilize this optimization.

my_multicall(Nodes, Module, Function, Args) ->
  ReqIds = lists:map(fun (Node) ->
                       erpc:send_request(Node, Module, Function, Args)
                     end,
                     Nodes),
  lists:map(fun (ReqId) ->
              try
                {ok, erpc:receive_response(ReqId, infinity)}
              catch
                Class:Reason ->
                  {Class, Reason}
              end
            end,
            ReqIds).

If an erpc operation fails, but it is unknown if the function is/will be applied (that is, a timeout, connection loss, or an improper Nodes list), the caller will not receive any further information about the result if/when the applied function completes. If the applied function communicates with the calling process, such communication may, of course, reach the calling process.

Note

If the always_spawn option is false (which is the default), you cannot make any assumptions about the processes that will perform the apply()s. It may be the calling process itself, or freshly spawned processes, or a mix of both.

multicast(Nodes, Fun)

(since OTP 23.0)

-spec multicast(Nodes, Fun) -> ok when Nodes :: [node()], Fun :: function().

Equivalent to erpc:multicast(Nodes,erlang,apply,[Fun,[]]).

multicast/2 fails with an {erpc, badarg} error exception if:

Nodes is not a proper list of atoms.

Fun is not a a fun of zero arity.

multicast(Nodes, Module, Function, Args)

(since OTP 23.0)

-spec multicast(Nodes, Module, Function, Args) -> ok
                   when Nodes :: [node()], Module :: atom(), Function :: atom(), Args :: [term()].

Evaluates apply(Module, Function, Args) on the nodes Nodes. No response is delivered to the calling process. multicast() returns immediately after the cast requests have been sent. Any failures beside bad arguments are silently ignored.

multicast/4 fails with an {erpc, badarg} error exception if:

Nodes is not a proper list of atoms. Note that some requests may already have been sent when the failure occurs. That is, the function may or may not be applied on some nodes.

Module is not an atom.

Function is not an atom.

Args is not a list. Note that the list is not verified to be a proper list at the client side.

receive_response(RequestId)

(since OTP 23.0)

-spec receive_response(RequestId) -> Result when RequestId :: request_id(), Result :: term().

Equivalent to receive_response(RequestId, infinity).

receive_response(RequestId, Timeout)

(since OTP 23.0)

-spec receive_response(RequestId, Timeout) -> Result
                          when RequestId :: request_id(), Timeout :: timeout_time(), Result :: term().

Receive a response to a call request previously made by the calling process using send_request/4.

RequestId should be the value returned from the previously made send_request/4 call, and the corresponding response should not already have been received and handled to completion by receive_response(), check_response/4, or wait_response/4.

Timeout sets an upper time limit on how long to wait for a response. If the operation times out, the request identified by RequestId will be abandoned, then an {erpc, timeout} error exception will be raised. That is, no response corresponding to the request will ever be received after a timeout. If a response is received, the call operation is completed and either the result is returned or an exception is raised. The exceptions that can be raised corresponds to the same exceptions as can be raised by call/5. receive_response/2 will fail with an {erpc, badarg} exception if/when an invalid RequestId is detected or if an invalid Timeout is passed.

A call to the function my_call(Node, Module, Function, Args, Timeout) below is equivalent to the call erpc:call(Node, Module, Function, Args, Timeout) if one disregards performance. call() can utilize a selective receive optimization which removes the need to scan the message queue from the beginning in order to find a matching message. The send_request()/receive_response() combination can, however, not utilize this optimization.

my_call(Node, Module, Function, Args, Timeout) ->
  RequestId = erpc:send_request(Node, Module, Function, Args),
  erpc:receive_response(RequestId, Timeout).

If the erpc operation fails, but it is unknown if the function is/will be applied (that is, a timeout, or a connection loss), the caller will not receive any further information about the result if/when the applied function completes. If the applied function explicitly communicates with the calling process, such communication may, of course, reach the calling process.

receive_response(RequestIdCollection, Timeout, Delete)

(since OTP 25.0)

-spec receive_response(RequestIdCollection, Timeout, Delete) ->
                          {Result, Label, NewRequestIdCollection} | no_request
                          when
                              RequestIdCollection :: request_id_collection(),
                              Timeout :: timeout_time(),
                              Delete :: boolean(),
                              Result :: term(),
                              Label :: term(),
                              NewRequestIdCollection :: request_id_collection().

Receive a response to a call request corresponding to a request identifier saved in RequestIdCollection. All request identifiers of RequestIdCollection must correspond to requests that have been made using send_request/4 or send_request/6, and all requests must have been made by the process calling this function.

Label is the label associated with the request identifier of the request that the response corresponds to. A request identifier is associated with a label when adding a request identifier in a request identifier collection, or when sending the request using send_request/6.

Compared to receive_response/2, the returned result associated with a specific request identifier or an exception associated with a specific request identifier will be wrapped in a 3-tuple. The first element of this tuple equals the value that would have been produced by receive_response/2, the second element equals the Label associated with the specific request identifier, and the third element NewRequestIdCollection is a possibly modified request identifier collection. The error exceptions {erpc, badarg} and {erpc, timeout} are not associated with any specific request identifiers, and will hence not be wrapped.

If RequestIdCollection is empty, the atom no_request will be returned.

If the operation times out, all requests identified by RequestIdCollection will be abandoned, then an {erpc, timeout} error exception will be raised. That is, no responses corresponding to any of the request identifiers in RequestIdCollection will ever be received after a timeout. The difference between receive_response/3 and wait_response/3 is that receive_response/3 abandons the requests at timeout so that any potential future responses are ignored, while wait_response/3 does not.

If Delete equals true, the association with Label will have been deleted from RequestIdCollection in the resulting NewRequestIdCollection. If Delete equals false, NewRequestIdCollection will equal RequestIdCollection. Note that deleting an association is not for free and that a collection containing already handled requests can still be used by subsequent calls to receive_response/3, check_response/3, and wait_response/3. However, without deleting handled associations, the above calls will not be able to detect when there are no more outstanding requests to handle, so you will have to keep track of this some other way than relying on a no_request return. Note that if you pass a collection only containing associations of already handled or abandoned requests to receive_response/3, it will always block until a timeout determined by Timeout is triggered.

Note that a response might have been consumed uppon an {erpc, badarg} exception and if so, will be lost for ever.

reqids_add(RequestId, Label, RequestIdCollection)

(since OTP 25.0)

-spec reqids_add(RequestId :: request_id(),
                 Label :: term(),
                 RequestIdCollection :: request_id_collection()) ->
                    NewRequestIdCollection :: request_id_collection().

Saves RequestId and associates a Label with the request identifier by adding this information to RequestIdCollection and returning the resulting request identifier collection.

reqids_new()

(since OTP 25.0)

-spec reqids_new() -> NewRequestIdCollection :: request_id_collection().

Returns a new empty request identifier collection. A request identifier collection can be utilized in order the handle multiple outstanding requests.

Request identifiers of requests made by send_request/4 can be saved in a request identifier collection using reqids_add/3. Such a collection of request identifiers can later be used in order to get one response corresponding to a request in the collection by passing the collection as argument to check_response/3, receive_response/3, and wait_response/3.

reqids_size/1 can be used to determine the amount of request identifiers in a request identifier collection.

reqids_size(RequestIdCollection)

(since OTP 25.0)

-spec reqids_size(RequestIdCollection :: request_id_collection()) -> non_neg_integer().

Returns the amount of request identifiers saved in RequestIdCollection.

reqids_to_list(RequestIdCollection)

(since OTP 25.0)

-spec reqids_to_list(RequestIdCollection :: request_id_collection()) ->
                        [{RequestId :: request_id(), Label :: term()}].

Returns a list of {RequestId, Label} tuples which corresponds to all request identifiers with their associated labels present in the RequestIdCollection collection.

send_request(Node, Fun)

(since OTP 23.0)

-spec send_request(Node, Fun) -> RequestId
                      when Node :: node(), Fun :: function(), RequestId :: request_id().

Equivalent to erpc:send_request(Node, erlang, apply, [Fun, []]).

Fails with an {erpc, badarg} error exception if:

Node is not an atom.

Fun is not a fun of zero arity.

send_request/4

(since OTP 23.0)

-spec send_request(Node, Module, Function, Args) -> RequestId
                      when
                          Node :: node(),
                          Module :: atom(),
                          Function :: atom(),
                          Args :: [term()],
                          RequestId :: request_id();
                  (Node, Fun, Label, RequestIdCollection) -> NewRequestIdCollection
                      when
                          Node :: node(),
                          Fun :: function(),
                          Label :: term(),
                          RequestIdCollection :: request_id_collection(),
                          NewRequestIdCollection :: request_id_collection().

Send an asynchronous call request to the node Node.

send_request/4 returns a request identifier that later is to be passed to either receive_response/2, wait_response/2, or, check_response/2 in order to get the response of the call request. Besides passing the request identifier directly to these functions, it can also be added in a request identifier collection using reqids_add/3. Such a collection of request identifiers can later be used in order to get one response corresponding to a request in the collection by passing the collection as argument to receive_response/3, wait_response/3, or, check_response/3. If you are about to save the request identifier in a request identifier collection, you may want to consider using send_request/6 instead.

A call to the function my_call(Node, Module, Function, Args, Timeout) below is equivalent to the call erpc:call(Node, Module, Function, Args, Timeout) if one disregards performance. call() can utilize a selective receive optimization which removes the need to scan the message queue from the beginning in order to find a matching message. The send_request()/receive_response() combination can, however, not utilize this optimization.

my_call(Node, Module, Function, Args, Timeout) ->
  RequestId = erpc:send_request(Node, Module, Function, Args),
  erpc:receive_response(RequestId, Timeout).

Fails with an {erpc, badarg} error exception if:

Node is not an atom.

Module is not an atom.

Function is not an atom.

Args is not a list. Note that the list is not verified to be a proper list at the client side.

Equivalent to erpc:send_request(Node, erlang, apply, [Fun,[]]), Label, RequestIdCollection).

Fails with an {erpc, badarg} error exception if:

Node is not an atom.

Fun is not a fun of zero arity.

RequestIdCollection is detected not to be request identifier collection.

send_request(Node, Module, Function, Args, Label, RequestIdCollection)

(since OTP 25.0)

-spec send_request(Node, Module, Function, Args, Label, RequestIdCollection) -> NewRequestIdCollection
                      when
                          Node :: node(),
                          Module :: atom(),
                          Function :: atom(),
                          Args :: [term()],
                          Label :: term(),
                          RequestIdCollection :: request_id_collection(),
                          NewRequestIdCollection :: request_id_collection().

Send an asynchronous call request to the node Node. The Label will be associated with the request identifier of the operation and added to the returned request identifier collection NewRequestIdCollection. The collection can later be used in order to get one response corresponding to a request in the collection by passing the collection as argument to receive_response/3, wait_response/3, or, check_response/3.

Equivalent to erpc:reqids_add(erpc:send_request(Node, Module, Function, Args), Label, RequestIdCollection), but calling send_request/6 is slightly more efficient.

Fails with an {erpc, badarg} error exception if:

Node is not an atom.

Module is not an atom.

Function is not an atom.

Args is not a list. Note that the list is not verified to be a proper list at the client side.

RequestIdCollection is detected not to be request identifier collection.

wait_response(RequestId)

(since OTP 23.0)

-spec wait_response(RequestId) -> {response, Result} | no_response
                       when RequestId :: request_id(), Result :: term().

Equivalent to erpc:wait_response(RequestId, 0). That is, poll for a response message to a call request previously made by the calling process.

wait_response(RequestId, WaitTime)

(since OTP 23.0)

-spec wait_response(RequestId, WaitTime) -> {response, Result} | no_response
                       when RequestId :: request_id(), WaitTime :: timeout_time(), Result :: term().

Wait or poll for a response message to a call request previously made by the calling process using send_request/4.

RequestId should be the value returned from the previously made send_request() call, and the corresponding response should not already have been received and handled to completion by check_response/2, receive_response/2, or wait_response().

WaitTime sets an upper time limit on how long to wait for a response. If no response is received before the WaitTime timeout has triggered, the atom no_response is returned. It is valid to continue waiting for a response as many times as needed up until a response has been received and completed by check_response(), receive_response(), or wait_response(). If a response is received, the call operation is completed and either the result is returned as {response, Result} where Result corresponds to the value returned from the applied function or an exception is raised. The exceptions that can be raised corresponds to the same exceptions as can be raised by call/4. That is, no {erpc, timeout} error exception can be raised. wait_response/2 will fail with an {erpc, badarg} exception if/when an invalid RequestId is detected or if an invalid WaitTime is passed.

If the erpc operation fails, but it is unknown if the function is/will be applied (that is, a too large wait time value, or a connection loss), the caller will not receive any further information about the result if/when the applied function completes. If the applied function explicitly communicates with the calling process, such communication may, of course, reach the calling process.

wait_response(RequestIdCollection, WaitTime, Delete)

(since OTP 25.0)

-spec wait_response(RequestIdCollection, WaitTime, Delete) ->
                       {{response, Result}, Label, NewRequestIdCollection} | no_response | no_request
                       when
                           RequestIdCollection :: request_id_collection(),
                           WaitTime :: timeout_time(),
                           Delete :: boolean(),
                           Label :: term(),
                           NewRequestIdCollection :: request_id_collection(),
                           Result :: term().

Wait or poll for a response to a call request corresponding to a request identifier saved in RequestIdCollection. All request identifiers of RequestIdCollection must correspond to requests that have been made using send_request/4 or send_request/6, and all requests must have been made by the process calling this function.

Label is the label associated with the request identifier of the request that the response corresponds to. A request identifier is associated with a label when adding a request identifier in a request identifier collection, or when sending the request using send_request/6.

Compared to wait_response/2, the returned result associated with a specific request identifier or an exception associated with a specific request identifier will be wrapped in a 3-tuple. The first element of this tuple equals the value that would have been produced by wait_response/2, the second element equals the Label associated with the specific request identifier, and the third element NewRequestIdCollection is a possibly modified request identifier collection. The error exception {erpc, badarg} is not associated with any specific request identifier, and will hence not be wrapped.

If RequestIdCollection is empty, no_request will be returned. If no response is received before the WaitTime timeout has triggered, the atom no_response is returned. It is valid to continue waiting for a response as many times as needed up until a response has been received and completed by check_response(), receive_response(), or wait_response(). The difference between receive_response/3 and wait_response/3 is that receive_response/3 abandons requests at timeout so that any potential future responses are ignored, while wait_response/3 does not.

If Delete equals true, the association with Label will have been deleted from RequestIdCollection in the resulting NewRequestIdCollection. If Delete equals false, NewRequestIdCollection will equal RequestIdCollection. Note that deleting an association is not for free and that a collection containing already handled requests can still be used by subsequent calls to wait_response/3, check_response/3, and receive_response/3. However, without deleting handled associations, the above calls will not be able to detect when there are no more outstanding requests to handle, so you will have to keep track of this some other way than relying on a no_request return. Note that if you pass a collection only containing associations of already handled or abandoned requests to wait_response/3, it will always block until a timeout determined by WaitTime is triggered and then return no_response.

Note that a response might have been consumed uppon an {erpc, badarg} exception and if so, will be lost for ever.

global

A global name registration facility.

This module consists of the following services:

Registration of global names

Global locks

Maintenance of the fully connected network

As of OTP 25, global will by default prevent overlapping partitions due to network issues by actively disconnecting from nodes that reports that they have lost connections to other nodes. This will cause fully connected partitions to form instead of leaving the network in a state with overlapping partitions.

Warning

Prevention of overlapping partitions can be disabled using the prevent_overlapping_partitions Kernel parameter, making global behave like it used to do. This is, however, problematic for all applications expecting a fully connected network to be provided, such as for example mnesia, but also for global itself. A network of overlapping partitions might cause the internal state of global to become inconsistent. Such an inconsistency can remain even after such partitions have been brought together to form a fully connected network again. The effect on other applications that expects that a fully connected network is maintained may vary, but they might misbehave in very subtle hard to detect ways during such a partitioning. Since you might get hard to detect issues without this fix, you are strongly advised not to disable this fix. Also note that this fix has to be enabled on all nodes in the network in order to work properly.

Note

None of the above services will be reliably delivered unless both of the kernel parameters connect_all and prevent_overlapping_partitions are enabled. Calls to the global API will, however, not fail even though one or both of them are disabled. You will just get unreliable results.

These services are controlled through the process global_name_server that exists on every node. The global name server starts automatically when a node is started. With the term global is meant over a system consisting of many Erlang nodes.

The ability to globally register names is a central concept in the programming of distributed Erlang systems. In this module, the equivalent of the register/2 and whereis/1 BIFs (for local name registration) are provided, but for a network of Erlang nodes. A registered name is an alias for a process identifier (pid). The global name server monitors globally registered pids. If a process terminates, the name is also globally unregistered.

The registered names are stored in replica global name tables on every node. There is no central storage point. Thus, the translation of a name to a pid is fast, as it is always done locally. For any action resulting in a change to the global name table, all tables on other nodes are automatically updated.

Global locks have lock identities and are set on a specific resource. For example, the specified resource can be a pid. When a global lock is set, access to the locked resource is denied for all resources other than the lock requester.

Both the registration and lock services are atomic. All nodes involved in these actions have the same view of the information.

The global name server also performs the critical task of continuously monitoring changes in node configuration. If a node that runs a globally registered process goes down, the name is globally unregistered. To this end, the global name server subscribes to nodeup and nodedown messages sent from module net_kernel. Relevant Kernel application variables in this context are net_setuptime, net_ticktime, and dist_auto_connect.

The name server also maintains a fully connected network. For example, if node N1 connects to node N2 (which is already connected to N3), the global name servers on the nodes N1 and N3 ensure that also N1 and N3 are connected. In this case, the name registration service cannot be used, but the lock mechanism still works.

If the global name server fails to connect nodes (N1 and N3 in the example), a warning event is sent to the error logger. The presence of such an event does not exclude the nodes to connect later (you can, for example, try command rpc:call(N1, net_adm, ping, [N2]) in the Erlang shell), but it indicates a network problem.

Note

If the fully connected network is not set up properly, try first to increase the value of net_setuptime.

See Also

global_group, net_kernel

Summary

Types

id()

A lock id used to set or delete lock ResourceId on behalf of LockRequesterId.

method()

retries()

trans_fun()

Functions

del_lock(Id)

Equivalent to del_lock(Id, [node() | nodes()]).

del_lock(Id, Nodes)

Deletes the lock Id synchronously.

disconnect()

Disconnect from all other nodes known to global.

notify_all_name(Name, Pid1, Pid2)

The function unregisters both pids and sends the message {global_name_conflict, Name, OtherPid} to both processes.

random_exit_name(Name, Pid1, Pid2)

The function randomly selects one of the pids for registration and kills the other one.

random_notify_name(Name, Pid1, Pid2)

The function randomly selects one of the pids for registration, and sends the message {global_name_conflict, Name} to the other pid.

re_register_name(Name, Pid)

Equivalent to re_register_name(Name, Pid, fun random_exit_name/3).

re_register_name(Name, Pid, Resolve)

Atomically changes the registered name Name on all nodes to refer to Pid.

register_name(Name, Pid)

Equivalent to register_name(Name, Pid, fun random_exit_name/3).

register_name(Name, Pid, Resolve)

Globally associates name Name with a pid, that is, globally notifies all nodes of a new global name in a network of Erlang nodes.

registered_names()

Returns a list of all globally registered names.

send(Name, Msg)

Sends message Msg to the pid globally registered as Name.

set_lock(Id)

Equivalent to set_lock(Id, [node() | nodes()], infinity).

set_lock(Id, Nodes)

Equivalent to set_lock(Id, Nodes, infinity).

set_lock(Id, Nodes, Retries)

Sets a lock on the specified nodes on using id/0.

sync()

Synchronizes the global name server with all nodes known to this node.

trans(Id, Fun)

Equivalent to trans(Id, Fun, [node() | nodes()], infinity).

trans(Id, Fun, Nodes)

Equivalent to trans(Id, Fun, Nodes, infinity).

trans(Id, Fun, Nodes, Retries)

Sets a lock on Id (using set_lock/3).

unregister_name(Name)

Removes the globally registered name Name from the network of Erlang nodes.

whereis_name(Name)

Returns the pid with the globally registered name Name. Returns undefined if the name is not globally registered.

Types

id()

(not exported)

-type id() :: {ResourceId :: term(), LockRequesterId :: term()}.

A lock id used to set or delete lock ResourceId on behalf of LockRequesterId.

method()

(not exported)

-type method() :: fun((Name :: term(), Pid :: pid(), Pid2 :: pid()) -> pid() | none).

retries()

(not exported)

-type retries() :: non_neg_integer() | infinity.

trans_fun()

(not exported)

-type trans_fun() :: function() | {module(), atom()}.

Functions

del_lock(Id)

-spec del_lock(Id) -> true when Id :: id().

Equivalent to del_lock(Id, [node() | nodes()]).

del_lock(Id, Nodes)

-spec del_lock(Id, Nodes) -> true when Id :: id(), Nodes :: [node()].

Deletes the lock Id synchronously.

disconnect()

(since OTP 25.1)

-spec disconnect() -> [node()].

Disconnect from all other nodes known to global.

A list of node names (in an unspecified order) is returned which corresponds to the nodes that were disconnected. All disconnect operations performed have completed when global:disconnect/0 returns.

The disconnects will be made in such a way that only the current node will be removed from the cluster of global nodes. If prevent_overlapping_partitions is enabled and you disconnect, from other nodes in the cluster of global nodes, by other means, global on the other nodes may partition the remaining nodes in order to ensure that no overlapping partitions appear. Even if prevent_overlapping_partitions is disabled, you should preferably use global:disconnect/0 in order to remove current node from a cluster of global nodes, since you otherwise likely will create overlapping partitions which might cause problems.

Note that if the node is going to be halted, there is no need to remove it from a cluster of global nodes explicitly by calling global:disconnect/0 before halting it. The removal from the cluster is taken care of automatically when the node halts regardless of whether prevent_overlapping_partitions is enabled or not.

If current node has been configured to be part of a global group, only connected and/or synchronized nodes in that group are known to global, so global:disconnect/0 will only disconnect from those nodes. If current node is not part of a global group, all connected visible nodes will be known to global, so global:disconnect/0 will disconnect from all those nodes.

Note that information about connected nodes does not instantaneously reach global, so the caller might see a node part of the result returned by nodes() while it still is not known to global. The disconnect operation will, however, still not cause any overlapping partitions when prevent_overlapping_partitions is enabled. If prevent_overlapping_partitions is disabled, overlapping partitions might form in this case.

Note that when prevent_overlapping_partitions is enabled, you may see warning reports on other nodes when they detect that current node has disconnected. These are in this case completely harmless and can be ignored.

notify_all_name(Name, Pid1, Pid2)

-spec notify_all_name(Name, Pid1, Pid2) -> none when Name :: term(), Pid1 :: pid(), Pid2 :: pid().

The function unregisters both pids and sends the message {global_name_conflict, Name, OtherPid} to both processes.

Can be used as a name resolving function for register_name/3 and re_register_name/3.

random_exit_name(Name, Pid1, Pid2)

-spec random_exit_name(Name, Pid1, Pid2) -> pid() when Name :: term(), Pid1 :: pid(), Pid2 :: pid().

The function randomly selects one of the pids for registration and kills the other one.

Can be used as a name resolving function for register_name/3 and re_register_name/3.

random_notify_name(Name, Pid1, Pid2)

-spec random_notify_name(Name, Pid1, Pid2) -> pid() when Name :: term(), Pid1 :: pid(), Pid2 :: pid().

The function randomly selects one of the pids for registration, and sends the message {global_name_conflict, Name} to the other pid.

Can be used as a name resolving function for register_name/3 and re_register_name/3.

re_register_name(Name, Pid)

-spec re_register_name(Name, Pid) -> yes when Name :: term(), Pid :: pid().

Equivalent to re_register_name(Name, Pid, fun random_exit_name/3).

re_register_name(Name, Pid, Resolve)

-spec re_register_name(Name, Pid, Resolve) -> yes when Name :: term(), Pid :: pid(), Resolve :: method().

Atomically changes the registered name Name on all nodes to refer to Pid.

Function Resolve has the same behavior as in register_name/2,3.

register_name(Name, Pid)

-spec register_name(Name, Pid) -> yes | no when Name :: term(), Pid :: pid().

Equivalent to register_name(Name, Pid, fun random_exit_name/3).

register_name(Name, Pid, Resolve)

-spec register_name(Name, Pid, Resolve) -> yes | no
                       when Name :: term(), Pid :: pid(), Resolve :: method().

Globally associates name Name with a pid, that is, globally notifies all nodes of a new global name in a network of Erlang nodes.

When new nodes are added to the network, they are informed of the globally registered names that already exist. The network is also informed of any global names in newly connected nodes. If any name clashes are discovered, function Resolve is called. Its purpose is to decide which pid is correct. If the function crashes, or returns anything other than one of the pids, the name is unregistered. This function is called once for each name clash.

Warning

If you plan to change code without restarting your system, you must use an external fun (fun Module:Function/Arity) as function Resolve. If you use a local fun, you can never replace the code for the module that the fun belongs to.

Three predefined resolve functions exist: random_exit_name/3, random_notify_name/3, and notify_all_name/3.

This function is completely synchronous, that is, when this function returns, the name is either registered on all nodes or none.

The function returns yes if successful, no if it fails. For example, no is returned if an attempt is made to register an already registered process or to register a process with a name that is already in use.

Note

Releases up to and including Erlang/OTP R10 did not check if the process was already registered. The global name table could therefore become inconsistent. The old (buggy) behavior can be chosen by giving the Kernel application variable global_multi_name_action the value allow.

If a process with a registered name dies, or the node goes down, the name is unregistered on all nodes.

registered_names()

-spec registered_names() -> [Name] when Name :: term().

Returns a list of all globally registered names.

send(Name, Msg)

-spec send(Name, Msg) -> Pid when Name :: term(), Msg :: term(), Pid :: pid().

Sends message Msg to the pid globally registered as Name.

If Name is not a globally registered name, the calling function exits with reason {badarg, {Name, Msg}}.

set_lock(Id)

-spec set_lock(Id) -> boolean() when Id :: id().

Equivalent to set_lock(Id, [node() | nodes()], infinity).

set_lock(Id, Nodes)

-spec set_lock(Id, Nodes) -> boolean() when Id :: id(), Nodes :: [node()].

Equivalent to set_lock(Id, Nodes, infinity).

set_lock(Id, Nodes, Retries)

-spec set_lock(Id, Nodes, Retries) -> boolean() when Id :: id(), Nodes :: [node()], Retries :: retries().

Sets a lock on the specified nodes on using id/0.

If a lock already exists on ResourceId for another requester than LockRequesterId, and Retries is not equal to 0, the process sleeps for a while and tries to execute the action later. When Retries attempts have been made, false is returned, otherwise true. If Retries is infinity, true is eventually returned (unless the lock is never released).

This function is completely synchronous.

If a process that holds a lock dies, or the node goes down, the locks held by the process are deleted.

The global name server keeps track of all processes sharing the same lock, that is, if two processes set the same lock, both processes must delete the lock.

This function does not address the problem of a deadlock. A deadlock can never occur as long as processes only lock one resource at a time. A deadlock can occur if some processes try to lock two or more resources. It is up to the application to detect and rectify a deadlock.

Note

Avoid the following values of ResourceId, otherwise Erlang/OTP does not work properly:

dist_ac

global

mnesia_adjust_log_writes

mnesia_table_lock

sync()

-spec sync() -> ok | {error, Reason :: term()}.

Synchronizes the global name server with all nodes known to this node.

These are the nodes that are returned from nodes(). When this function returns, the global name server receives global information from all nodes. This function can be called when new nodes are added to the network.

The only possible error reason Reason is {"global_groups definition error", Error}.

trans(Id, Fun)

-spec trans(Id, Fun) -> Res | aborted when Id :: id(), Fun :: trans_fun(), Res :: term().

Equivalent to trans(Id, Fun, [node() | nodes()], infinity).

trans(Id, Fun, Nodes)

-spec trans(Id, Fun, Nodes) -> Res | aborted
               when Id :: id(), Fun :: trans_fun(), Nodes :: [node()], Res :: term().

Equivalent to trans(Id, Fun, Nodes, infinity).

trans(Id, Fun, Nodes, Retries)

-spec trans(Id, Fun, Nodes, Retries) -> Res | aborted
               when
                   Id :: id(),
                   Fun :: trans_fun(),
                   Nodes :: [node()],
                   Retries :: retries(),
                   Res :: term().

Sets a lock on Id (using set_lock/3).

If this succeeds, Fun() is evaluated and the result Res is returned. Returns aborted if the lock attempt fails. If Retries is set to infinity, the transaction does not abort.

infinity is the default setting and is used if no value is specified for Retries.

unregister_name(Name)

-spec unregister_name(Name) -> _ when Name :: term().

Removes the globally registered name Name from the network of Erlang nodes.

whereis_name(Name)

-spec whereis_name(Name) -> pid() | undefined when Name :: term().

Returns the pid with the globally registered name Name. Returns undefined if the name is not globally registered.

global_group

Grouping nodes to global name registration groups.

This module makes it possible to partition the nodes of a system into global groups. Each global group has its own global namespace, see global.

The main advantage of dividing systems into global groups is that the background load decreases while the number of nodes to be updated is reduced when manipulating globally registered names.

The Kernel configuration parameter global_groups defines the global groups:

{global_groups, [GroupTuple :: group_tuple()]}

For the processes and nodes to run smoothly using the global group functionality, the following criteria must be met:

An instance of the global group server, global_group, must be running on each node. The processes are automatically started and synchronized when a node is started.

All involved nodes must agree on the global group definition, otherwise the behavior of the system is undefined.

All nodes in the system must belong to exactly one global group.

In the following descriptions, a group node is a node belonging to the same global group as the local node.

Notes

In the situation where a node has lost its connections to other nodes in its global group, but has connections to nodes in other global groups, a request from another global group can produce an incorrect or misleading result. For example, the isolated node can have inaccurate information about registered names in its global group.

Function send/2,3 is not secure.

Distribution of applications is highly dependent of the global group definitions. It is not recommended that an application is distributed over many global groups, as the registered names can be moved to another global group at failover/takeover. Nothing prevents this to be done, but the application code must then handle the situation.

See Also

global, erl

Summary

Types

group_name()

group_tuple()

A GroupTuple without PublishType is the same as a GroupTuple with PublishType equal to normal.

info_item()

name()

A registered name.

publish_type()

A node started with command-line flag -hidden (see erl) is said to be a hidden node. A hidden node establishes hidden connections to nodes not part of the same global group, but normal (visible) connections to nodes part of the same global group.

sync_state()

where()

Functions

global_groups()

Returns a tuple containing the name of the global group that the local node belongs to, and the list of all other known group names.

info()

Returns a list containing information about the global groups. Each list element is a tuple. The order of the tuples is undefined.

monitor_nodes(Flag)

Alter the calling process' subscription of node status change messages.

own_nodes()

Returns the names of all group nodes, regardless of their current status.

registered_names(Where)

Returns a list of all names that are globally registered on the specified node or in the specified global group.

send(Name, Msg)

Sends Msg to the pid represented by the globally registered name Name.

send(Where, Name, Msg)

Equivalent to send(Name, Msg) except that he search is limited to the node or global group specified by Where.

sync()

Synchronizes the group nodes, that is, the global name servers on the group nodes. Also checks the names globally registered in the current global group and unregisters them on any known node not part of the group.

whereis_name(Name)

Searched for Name in any global group.

whereis_name(Where, Name)

Equivalent to whereis_name(Name) except that he search is limited to the node or global group specified by Where.

Types

group_name()

(not exported)

-type group_name() :: atom().

group_tuple()

(not exported)

-type group_tuple() ::
          {GroupName :: group_name(), [node()]} |
          {GroupName :: group_name(), PublishType :: publish_type(), [node()]}.

A GroupTuple without PublishType is the same as a GroupTuple with PublishType equal to normal.

info_item()

(not exported)

-type info_item() ::
          {state, State :: sync_state()} |
          {own_group_name, GroupName :: group_name()} |
          {own_group_nodes, Nodes :: [node()]} |
          {synched_nodes, Nodes :: [node()]} |
          {sync_error, Nodes :: [node()]} |
          {no_contact, Nodes :: [node()]} |
          {other_groups, Groups :: [group_tuple()]} |
          {monitoring, Pids :: [pid()]}.

name()

(not exported)

-type name() :: atom().

A registered name.

publish_type()

(not exported)

-type publish_type() :: hidden | normal.

A node started with command-line flag -hidden (see erl) is said to be a hidden node. A hidden node establishes hidden connections to nodes not part of the same global group, but normal (visible) connections to nodes part of the same global group.

A global group defined with PublishType equal to hidden is said to be a hidden global group. All nodes in a hidden global group are hidden nodes, whether they are started with command-line flag -hidden or not.

sync_state()

(not exported)

-type sync_state() :: no_conf | synced.

where()

(not exported)

-type where() :: {node, node()} | {group, group_name()}.

Functions

global_groups()

-spec global_groups() -> {GroupName, GroupNames} | undefined
                       when GroupName :: group_name(), GroupNames :: [GroupName].

Returns a tuple containing the name of the global group that the local node belongs to, and the list of all other known group names.

Returns undefined if no global groups are defined.

info()

-spec info() -> [info_item()].

Returns a list containing information about the global groups. Each list element is a tuple. The order of the tuples is undefined.

{state, State} - If the local node is part of a global group, State is equal to synced. If no global groups are defined, State is equal to no_conf.

{own_group_name, GroupName} - The name (atom) of the group that the local node belongs to.

{own_group_nodes, Nodes} - A list of node names (atoms), the group nodes.

{synced_nodes, Nodes} - A list of node names, the group nodes currently synchronized with the local node.

{sync_error, Nodes} - A list of node names, the group nodes with which the local node has failed to synchronize.

{no_contact, Nodes} - A list of node names, the group nodes to which there are currently no connections.

{other_groups, Groups} - Groups is a list of tuples {GroupName, Nodes}, specifying the name and nodes of the other global groups.

{monitoring, Pids} - A list of pids, specifying the processes that have subscribed to nodeup and nodedown messages.

monitor_nodes(Flag)

-spec monitor_nodes(Flag) -> ok when Flag :: boolean().

Alter the calling process' subscription of node status change messages.

If Flag is equal to true the calling process starts subscribing to node status change messages. If equal to false it stops subscribing.

A process that has subscribed receives the messages {nodeup, Node} and {nodedown, Node} when a group node connects or disconnects, respectively.

own_nodes()

-spec own_nodes() -> Nodes when Nodes :: [Node :: node()].

Returns the names of all group nodes, regardless of their current status.

registered_names(Where)

-spec registered_names(Where) -> Names when Where :: where(), Names :: [Name :: name()].

Returns a list of all names that are globally registered on the specified node or in the specified global group.

send(Name, Msg)

-spec send(Name, Msg) -> pid() | {badarg, {Name, Msg}} when Name :: name(), Msg :: term().

Sends Msg to the pid represented by the globally registered name Name.

send/2 searches for Name any any global group. The global groups are searched in the order that they appear in the value of configuration parameter global_groups.

If Name is found, message Msg is sent to the corresponding pid. The pid is also the return value of the function. If the name is not found, the function returns {badarg, {Name, Msg}}.

send(Where, Name, Msg)

-spec send(Where, Name, Msg) -> pid() | {badarg, {Name, Msg}}
              when Where :: where(), Name :: name(), Msg :: term().

Equivalent to send(Name, Msg) except that he search is limited to the node or global group specified by Where.

sync()

-spec sync() -> ok.

Synchronizes the group nodes, that is, the global name servers on the group nodes. Also checks the names globally registered in the current global group and unregisters them on any known node not part of the group.

If synchronization is not possible, an error report is sent to the error logger (see also error_logger.

Returns {error, {'invalid global_groups definition', Bad}} if configuration parameter global_groups has an invalid value Bad.

whereis_name(Name)

-spec whereis_name(Name) -> pid() | undefined when Name :: name().

Searched for Name in any global group.

The global groups are searched in the order that they appear in the value of configuration parameter global_groups.

If Name is found, the corresponding pid is returned. If the name is not found, the function returns undefined.

whereis_name(Where, Name)

-spec whereis_name(Where, Name) -> pid() | undefined when Where :: where(), Name :: name().

Equivalent to whereis_name(Name) except that he search is limited to the node or global group specified by Where.

net_adm

Various Erlang net administration routines.

This module contains various network utility functions.

Files

File .hosts.erlang consists of a number of host names written as Erlang terms. It is looked for in the current work directory, the user's home directory, and $OTPROOT (the root directory of Erlang/OTP), in that order.

The format of file .hosts.erlang must be one host name per line. The host names must be within quotes.

Example:

'super.eua.ericsson.se'.
'renat.eua.ericsson.se'.
'grouse.eua.ericsson.se'.
'gauffin1.eua.ericsson.se'.
^ (new line)

Summary

Types

verbosity()

Functions

dns_hostname(Host)

Returns the official name of Host, or {error, Host} if no such name is found. See also inet.

host_file()

Reads file .hosts.erlang, see section Files. Returns the hosts in this file as a list. Returns {error, Reason} if the file cannot be read or the Erlang terms on the file cannot be interpreted.

localhost()

Returns the name of the local host. If Erlang was started with command-line flag -name, Name is the fully qualified name.

names()

Equivalent to names(net_adm:localhost()).

names(Host)

Returns the names and associated port numbers of the Erlang nodes that epmd registered at the specified host.

ping(Node)

Sets up a connection to Node. Returns pong if it is successful, otherwise pang.

world()

Equivalent to world(silent).

world(Arg)

Calls names(Host) for all hosts that are specified in the Erlang host file .hosts.erlang, collects the replies, and then evaluates ping(Node) on all those nodes. Returns the list of all nodes that are successfully pinged.

world_list(Hosts)

Equivalent to world_list(Hosts, silent).

world_list(Hosts, Arg)

Same as world/0,1, but the hosts are specified as argument instead of being read from .hosts.erlang.

Types

verbosity()

(not exported)

-type verbosity() :: silent | verbose.

Functions

dns_hostname(Host)

-spec dns_hostname(Host) -> {ok, Name} | {error, Host} when Host :: atom() | string(), Name :: string().

Returns the official name of Host, or {error, Host} if no such name is found. See also inet.

host_file()

-spec host_file() -> Hosts | {error, Reason}
                   when
                       Hosts :: [Host :: atom()],
                       Reason ::
                           file:posix() |
                           badarg | terminated | system_limit |
                           {Line :: integer(), Mod :: module(), Term :: term()}.

Reads file .hosts.erlang, see section Files. Returns the hosts in this file as a list. Returns {error, Reason} if the file cannot be read or the Erlang terms on the file cannot be interpreted.

localhost()

-spec localhost() -> Name when Name :: string().

Returns the name of the local host. If Erlang was started with command-line flag -name, Name is the fully qualified name.

names()

-spec names() -> {ok, [{Name, Port}]} | {error, Reason}
               when Name :: string(), Port :: non_neg_integer(), Reason :: address | file:posix().

Equivalent to names(net_adm:localhost()).

names(Host)

-spec names(Host) -> {ok, [{Name, Port}]} | {error, Reason}
               when
                   Host :: atom() | string() | inet:ip_address(),
                   Name :: string(),
                   Port :: non_neg_integer(),
                   Reason :: address | file:posix().

Returns the names and associated port numbers of the Erlang nodes that epmd registered at the specified host.

Similar to epmd -names, see erts:epmd.

Returns {error, address} if epmd is not operational.

Example:

(arne@dunn)1> net_adm:names().
{ok,[{"arne",40262}]}

ping(Node)

-spec ping(Node) -> pong | pang when Node :: atom().

Sets up a connection to Node. Returns pong if it is successful, otherwise pang.

world()

-spec world() -> [node()].

Equivalent to world(silent).

world(Arg)

-spec world(Arg) -> [node()] when Arg :: verbosity().

Calls names(Host) for all hosts that are specified in the Erlang host file .hosts.erlang, collects the replies, and then evaluates ping(Node) on all those nodes. Returns the list of all nodes that are successfully pinged.

If Arg == verbose, the function writes information about which nodes it is pinging to stdout.

This function can be useful when a node is started, and the names of the other network nodes are not initially known.

Returns {error, Reason} if host_file/0 returns {error, Reason}.

world_list(Hosts)

-spec world_list(Hosts) -> [node()] when Hosts :: [atom()].

Equivalent to world_list(Hosts, silent).

world_list(Hosts, Arg)

-spec world_list(Hosts, Arg) -> [node()] when Hosts :: [atom()], Arg :: verbosity().

Same as world/0,1, but the hosts are specified as argument instead of being read from .hosts.erlang.

net_kernel

Erlang networking kernel.

The net kernel is a system process, registered as net_kernel, which must be operational for distributed Erlang to work. The purpose of this process is to implement parts of the BIFs spawn/4 and spawn_link/4, and to provide monitoring of the network.

An Erlang node is started using command-line flag -name or -sname:

$ erl -sname foobar

It is also possible to call net_kernel:start(foobar, #{}) directly from the normal Erlang shell prompt:

1> net_kernel:start(foobar, #{name_domain => shortnames}).
{ok,<0.64.0>}
(foobar@gringotts)2>

If the node is started with command-line flag -sname, the node name is foobar@Host, where Host is the short name of the host (not the fully qualified domain name). If started with flag -name, the node name is foobar@Host, where Host is the fully qualified domain name. For more information, see erl.

Normally, connections are established automatically when another node is referenced. This functionality can be disabled by setting Kernel configuration parameter dist_auto_connect to never, see kernel(6). In this case, connections must be established explicitly by calling connect_node/1.

Which nodes that are allowed to communicate with each other is handled by the magic cookie system, see section Distributed Erlang in the Erlang Reference Manual.

Warning

Starting a distributed node without also specifying -proto_dist inet_tls 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. See the Using SSL for Erlang Distribution User's Guide for details on how to setup a secure distributed node.

Summary

Types

connection_state()

connection_type()

Functions

allow(Nodes)

Permits access to the specified set of nodes.

allowed()

Returns a list of nodes that are explicitly allowed to connect to the node by calling allow/1. If empty list is returned, it means that any node using the same cookie will be able to connect.

connect_node(Node)

Establishes a connection to Node.

get_net_ticktime()

Returns currently used net tick time in seconds.

get_state()

Get the current state of the distribution for the local node.

getopts(Node, Options)

Get one or more options for the distribution socket connected to Node.

monitor_nodes(Flag)

Equivalent to monitor_nodes(Flag, []).

monitor_nodes(Flag, Options)

The calling process subscribes or unsubscribes to node status change messages. A nodeup message is delivered to all subscribing processes when a new node is connected, and a nodedown message is delivered when a node is disconnected.

set_net_ticktime(NetTicktime)

Equivalent to set_net_ticktime(NetTicktime, 60).

set_net_ticktime(NetTicktime, TransitionPeriod)

Sets net_ticktime (see kernel(6)) to NetTicktime seconds. TransitionPeriod defaults to 60.

setopts(Node, Options)

Set one or more options for distribution sockets. Argument Node can be either one node name or the atom new to affect the distribution sockets of all future connected nodes.

start(Options) deprecated

Turns a non-distributed node into a distributed node by starting net_kernel and other necessary processes.

start(Name, Options)

Turns a non-distributed node into a distributed node by starting net_kernel and other necessary processes.

stop()

Turns a distributed node into a non-distributed node.

Types

connection_state()

(not exported)

-type connection_state() :: check_pending | pending | up | up_pending.

connection_type()

(not exported)

-type connection_type() :: normal | hidden.

Functions

allow(Nodes)

-spec allow(Nodes) -> ok | error | ignored when Nodes :: [node()].

Permits access to the specified set of nodes.

Before the first call to allow/1, any node with the correct cookie can be connected. When allow/1 is called, a list of allowed nodes is established. Any access attempts made from (or to) nodes not in that list will be rejected.

Subsequent calls to allow/1 will add the specified nodes to the list of allowed nodes. It is not possible to remove nodes from the list.

Disallowing an already connected node will not cause it to be disconnected. It will, however, prevent any future reconnection attempts.

Passing Nodes as an empty list has never any affect at all.

Returns error if any element in Nodes is not an atom, and ignored if the local node is not alive.

allowed()

(since OTP 28.0)

-spec allowed() -> {ok, Nodes} | ignored when Nodes :: [node()].

Returns a list of nodes that are explicitly allowed to connect to the node by calling allow/1. If empty list is returned, it means that any node using the same cookie will be able to connect.

connect_node(Node)

-spec connect_node(Node) -> boolean() | ignored when Node :: node().

Establishes a connection to Node.

Returns true if a connection was established or was already established or if Node is the local node itself. Returns false if the connection attempt failed, and ignored if the local node is not alive.

get_net_ticktime()

-spec get_net_ticktime() -> Res
                          when
                              Res :: NetTicktime | {ongoing_change_to, NetTicktime} | ignored,
                              NetTicktime :: pos_integer().

Returns currently used net tick time in seconds.

For more information see the net_ticktime Kernel parameter.

Defined return values (Res):

NetTicktime - net_ticktime is NetTicktime seconds.

{ongoing_change_to, NetTicktime} - net_kernel is currently changing net_ticktime to NetTicktime seconds.

ignored - The local node is not alive.

get_state()

(since OTP 25.0)

-spec get_state() ->
                   #{started => no | static | dynamic,
                     name => atom(),
                     name_type => static | dynamic,
                     name_domain => shortnames | longnames}.

Get the current state of the distribution for the local node.

Returns a map with (at least) the following key-value pairs:

started => Started - Valid values for Started:

no - The distribution is not started. In this state none of the other keys below are present in the map.

static - The distribution was started with command line arguments -name or -sname.

dynamic - The distribution was started with net_kernel:start/1 and can be stopped with net_kernel:stop/0.

name => Name - The name of the node. Same as returned by erlang:node/0 except when name_type is dynamic in which case Name may be undefined (instead of nonode@nohost).

name_type => NameType - Valid values for NameType:

static - The node has a static node name set by the node itself.

dynamic - The distribution was started in dynamic node name mode, and will get its node name assigned from the first node it connects to. If key name has value undefined that has not happened yet.

name_domain => NameDomain - Valid values for NameDomain:

shortnames - The distribution was started to use node names with a short host portion (not fully qualified).

longnames - The distribution was started to use node names with a long fully qualified host portion.

getopts(Node, Options)

(since OTP 19.1)

-spec getopts(Node, Options) -> {ok, OptionValues} | {error, Reason} | ignored
                 when
                     Node :: node(),
                     Options :: [inet:socket_getopt()],
                     OptionValues :: [inet:socket_setopt()],
                     Reason :: inet:posix() | noconnection.

Get one or more options for the distribution socket connected to Node.

If Node is a connected node the return value is the same as from inet:getopts(Sock, Options) where Sock is the distribution socket for Node.

Returns ignored if the local node is not alive or {error, noconnection} if Node is not connected.

monitor_nodes(Flag)

-spec monitor_nodes(Flag) -> ok | Error when Flag :: boolean(), Error :: error | {error, term()}.

Equivalent to monitor_nodes(Flag, []).

monitor_nodes(Flag, Options)

-spec monitor_nodes(Flag, Options) -> ok | Error
                       when
                           Flag :: boolean(),
                           Options :: OptionsList | OptionsMap,
                           OptionsList :: [ListOption],
                           ListOption :: connection_id | {node_type, NodeType} | nodedown_reason,
                           OptionsMap ::
                               #{connection_id => boolean(),
                                 node_type => NodeType,
                                 nodedown_reason => boolean()},
                           NodeType :: visible | hidden | all,
                           Error :: error | {error, term()}.

The calling process subscribes or unsubscribes to node status change messages. A nodeup message is delivered to all subscribing processes when a new node is connected, and a nodedown message is delivered when a node is disconnected.

If Flag is true, a new subscription is started. If Flag is false, all previous subscriptions started with the same Options are stopped. Two option lists are considered the same if they contain the same set of options.

Delivery guarantees of nodeup/nodedown messages:

nodeup messages are delivered before delivery of any signals from the remote node through the newly established connection.

nodedown messages are delivered after all the signals from the remote node over the connection have been delivered.

nodeup messages are delivered after the corresponding node appears in results from erlang:nodes().

nodedown messages are delivered after the corresponding node has disappeared in results from erlang:nodes().

As of OTP 23.0, a nodedown message for a connection being taken down will be delivered before a nodeup message due to a new connection to the same node. Prior to OTP 23.0, this was not guaranteed to be the case.

The format of the node status change messages depends on Options. If Options is the empty list or if net_kernel:monitor_nodes/1 is called, the format is as follows:

{nodeup, Node} | {nodedown, Node}
  Node = node()

When Options is the empty map or empty list, the caller will only subscribe for status change messages for visible nodes. That is, only nodes that appear in the result of erlang:nodes/0.

If Options equals anything other than the empty list, the format of the status change messages is as follows:

{nodeup, Node, Info} | {nodedown, Node, Info}
  Node = node()
  Info = #{Tag => Val} | [{Tag, Val}]

Info is either a map or a list of 2-tuples. Its content depends on Options. If Options is a map, Info will also be a map. If Options is a list, Info will also be a list.

When Options is a map, currently the following associations are allowed:

connection_id => boolean() - If the value of the association equals true, a connection_id => ConnectionId association will be included in the Info map where ConnectionId is the connection identifier of the connection coming up or going down. For more info about this connection identifier see the documentation of erlang:nodes/2.

node_type => NodeType - Valid values for NodeType:

visible - Subscribe to node status change messages for visible nodes only. The association node_type => visible will be included in the Info map.

hidden - Subscribe to node status change messages for hidden nodes only. The association node_type => hidden will be included in the Info map.

all - Subscribe to node status change messages for both visible and hidden nodes. The association node_type => visible | hidden will be included in the Info map.

If no node_type => NodeType association is included in the Options map, the caller will subscribe for status change messages for visible nodes only, but no node_type => visible association will be included in the Info map.

nodedown_reason => boolean() - If the value of the association equals true, a nodedown_reason => Reason association will be included in the Info map for nodedown messages.

Reason can, depending on which distribution module or process that is used, be any term, but for the standard TCP distribution module it is one of the following:

connection_setup_failed - The connection setup failed (after nodeup messages were sent).

no_network - No network is available.

net_kernel_terminated - The net_kernel process terminated.

shutdown - Unspecified connection shutdown.

connection_closed - The connection was closed.

disconnect - The connection was disconnected (forced from the current node).

net_tick_timeout - Net tick time-out.

send_net_tick_failed - Failed to send net tick over the connection.

get_status_failed - Status information retrieval from the Port holding the connection failed.

When Options is a list, currently ListOption can be one of the following:

connection_id - A {connection_id, ConnectionId} tuple will be included in Info where ConnectionId is the connection identifier of the connection coming up or going down. For more info about this connection identifier see the documentation of erlang:nodes/2.

{node_type, NodeType} - Valid values for NodeType:

visible - Subscribe to node status change messages for visible nodes only. The tuple {node_type, visible} will be included in the Info list.

hidden - Subscribe to node status change messages for hidden nodes only. The tuple {node_type, hidden} will be included in the Info list.

all - Subscribe to node status change messages for both visible and hidden nodes. The tuple {node_type, visible | hidden} will be included in the Info list.

If no {node_type, NodeType} option has been given. The caller will subscribe for status change messages for visible nodes only, but no {node_type, visible} tuple will be included in the Info list.

nodedown_reason - The tuple {nodedown_reason, Reason} will be included in the Info list for nodedown messages.

See the documentation of the nodedown_reason => boolean() association above for information about possible Reason values.

Example:

(a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).
ok
(a@localhost)2> flush().
Shell got {nodeup,b@localhost,
                  #{connection_id => 3067552,node_type => visible}}
Shell got {nodeup,c@localhost,
                  #{connection_id => 13892107,node_type => hidden}}
Shell got {nodedown,b@localhost,
                    #{connection_id => 3067552,node_type => visible,
                      nodedown_reason => connection_closed}}
Shell got {nodedown,c@localhost,
                    #{connection_id => 13892107,node_type => hidden,
                      nodedown_reason => net_tick_timeout}}
Shell got {nodeup,b@localhost,
                  #{connection_id => 3067553,node_type => visible}}
ok
(a@localhost)3>

set_net_ticktime(NetTicktime)

-spec set_net_ticktime(NetTicktime) -> Res
                          when
                              NetTicktime :: pos_integer(),
                              Res :: unchanged | change_initiated | {ongoing_change_to, NewNetTicktime},
                              NewNetTicktime :: pos_integer().

Equivalent to set_net_ticktime(NetTicktime, 60).

set_net_ticktime(NetTicktime, TransitionPeriod)

-spec set_net_ticktime(NetTicktime, TransitionPeriod) -> Res
                          when
                              NetTicktime :: pos_integer(),
                              TransitionPeriod :: non_neg_integer(),
                              Res :: unchanged | change_initiated | {ongoing_change_to, NewNetTicktime},
                              NewNetTicktime :: pos_integer().

Sets net_ticktime (see kernel(6)) to NetTicktime seconds. TransitionPeriod defaults to 60.

Some definitions:

Minimum transition traffic interval (MTTI) - minimum(NetTicktime, PreviousNetTicktime)*1000 div 4 milliseconds.

Transition period - The time of the least number of consecutive MTTIs to cover TransitionPeriod seconds following the call to set_net_ticktime/2 (that is, ((TransitionPeriod*1000 - 1) div MTTI + 1)*MTTI milliseconds).

If NetTicktime < PreviousNetTicktime, the net_ticktime change is done at the end of the transition period; otherwise at the beginning. During the transition period, net_kernel ensures that there is outgoing traffic on all connections at least every MTTI millisecond.

Note

The net_ticktime changes must be initiated on all nodes in the network (with the same NetTicktime) before the end of any transition period on any node; otherwise connections can erroneously be disconnected.

Returns one of the following:

unchanged - net_ticktime already has the value of NetTicktime and is left unchanged.

change_initiated - net_kernel initiated the change of net_ticktime to NetTicktime seconds.

{ongoing_change_to, NewNetTicktime} - The request is ignored because net_kernel is busy changing net_ticktime to NewNetTicktime seconds.

setopts(Node, Options)

(since OTP 19.1)

-spec setopts(Node, Options) -> ok | {error, Reason} | ignored
                 when
                     Node :: node() | new,
                     Options :: [inet:socket_setopt()],
                     Reason :: inet:posix() | noconnection.

Set one or more options for distribution sockets. Argument Node can be either one node name or the atom new to affect the distribution sockets of all future connected nodes.

The return value is the same as from inet:setopts/2 or {error, noconnection} if Node is not a connected node or new.

If Node is new the Options will then also be added to kernel configuration parameters inet_dist_listen_options and inet_dist_connect_options.

Returns ignored if the local node is not alive.

start(Options)

This function is deprecated. Use start/2 instead.

-spec start(Options) -> {ok, pid()} | {error, Reason}
               when
                   Options :: [Name | NameDomain | TickTime, ...],
                   Name :: atom(),
                   NameDomain :: shortnames | longnames,
                   TickTime :: pos_integer(),
                   Reason :: {already_started, pid()} | term().

Turns a non-distributed node into a distributed node by starting net_kernel and other necessary processes.

Options list can only be exactly one of the following lists (order is imporant):

[Name] - The same as net_kernel:start([Name, longnames, 15000]).

[Name, NameDomain] - The same as net_kernel:start([Name, NameDomain, 15000]).

[Name, NameDomain, TickTime] - The same as net_kernel:start(Name, #{name_domain => NameDomain, net_ticktime => ((TickTime*4-1) div 1000) + 1, net_tickintensity => 4}). Note that TickTime is not the same as net tick time expressed in milliseconds. TickTime is the time between ticks when net tick intensity equals 4.

start(Name, Options)

(since OTP 24.3)

-spec start(Name, Options) -> {ok, pid()} | {error, Reason}
               when
                   Options ::
                       #{name_domain => NameDomain,
                         net_ticktime => NetTickTime,
                         net_tickintensity => NetTickIntensity,
                         dist_listen => boolean(),
                         hidden => boolean()},
                   Name :: atom(),
                   NameDomain :: shortnames | longnames,
                   NetTickTime :: pos_integer(),
                   NetTickIntensity :: 4..1000,
                   Reason :: {already_started, pid()} | term().

Turns a non-distributed node into a distributed node by starting net_kernel and other necessary processes.

If Name is set to undefined the distribution will be started to request a dynamic node name from the first node it connects to. See Dynamic Node Name. Setting Name to undefined implies options dist_listen => false and hidden => true.

Currently supported options:

name_domain => NameDomain - Determines the host name part of the node name. If NameDomain equals longnames, fully qualified domain names will be used which also is the default. If NameDomain equals shortnames, only the short name of the host will be used.

net_ticktime => NetTickTime - Net tick time to use in seconds. Defaults to the value of the net_ticktime kernel(6) parameter. For more information about net tick time, see the kernel parameter. However, note that if the value of the kernel parameter is invalid, it will silently be replaced by a valid value, but if an invalid NetTickTime value is passed as option value to this function, the call will fail.

net_tickintensity => NetTickIntensity - Net tick intensity to use. Defaults to the value of the net_tickintensity kernel(6) parameter. For more information about net tick intensity, see the kernel parameter. However, note that if the value of the kernel parameter is invalid, it will silently be replaced by a valid value, but if an invalid NetTickIntensity value is passed as option value to this function, the call will fail.

dist_listen => boolean() - Enable or disable listening for incoming connections. Defaults to the value of the -dist_listen erl command line argument. Note that dist_listen => false implies hidden => true.

If undefined has been passed as Name, the dist_listen option will be overridden with dist_listen => false.

hidden => boolean() - Enable or disable hidden node. Defaults to true if the -hidden erl command line argument has been passed; otherwise false.

If undefined has been passed as Name, or the option dist_listen equals false, the hidden option will be overridden with hidden => true.

stop()

-spec stop() -> ok | {error, Reason} when Reason :: not_allowed | not_found.

Turns a distributed node into a non-distributed node.

For other nodes in the network, this is the same as the node going down. Only possible when the net kernel was started using start/2, otherwise {error, not_allowed} is returned. Returns {error, not_found} if the local node is not alive.

pg

Distributed named process groups.

This module implements process groups. A message can be sent to one, some, or all group members.

Up until OTP 17 there used to exist an experimental pg module in stdlib. This pg module is not the same module as that experimental pg module, and only share the same module name.

A group of processes can be accessed by a common name. For example, if there is a group named foobar, there can be a set of processes (which can be located on different nodes) that are all members of the group foobar. There are no special functions for sending a message to the group. Instead, client functions are to be written with the functions get_members/1 and get_local_members/1 to determine which processes are members of the group. Then the message can be sent to one or more group members.

If a member terminates, it is automatically removed from the group.

A process may join multiple groups. It may join the same group multiple times. It is only allowed to join processes running on local node.

Process Groups implement strong eventual consistency. Process Groups membership view may temporarily diverge. For example, when processes on node1 and node2 join concurrently, node3 and node4 may receive updates in a different order.

Membership view is not transitive. If node1 is not directly connected to node2, they will not see each other's groups. But if both are connected to node3, node3 will have the full view.

Groups are automatically created when any process joins, and are removed when all processes leave the group. Non-existing group is considered empty (containing no processes).

Process groups can be organised into multiple scopes. Scopes are completely independent of each other. A process may join any number of groups in any number of scopes. Scopes are designed to decouple single mesh into a set of overlay networks, reducing amount of traffic required to propagate group membership information. Default scope pg is started automatically when Kernel is configured to do so.

Note

Scope name is used to register process locally, and to name an ETS table. If there is another process registered under this name, or another ETS table exists, scope fails to start.

Local membership is not preserved if scope process exits and restarts.

A scope can be kept local-only by using a scope name that is unique cluster-wide, e.g. the node name: pg:start_link(node()).

See Also

Kernel

Summary

Types

global_view()

group()

The identifier of a process group.

local_data()

options()

scope()

subscribe_result()

subscription()

subscriptions()

update()

version()

Functions

data_diff(Old, New)

demonitor(Ref)

Equivalent to demonitor(pg, Ref).

demonitor(Scope, Ref)

Unsubscribes the caller from updates (scope or group). Flushes all outstanding updates that were already in the message queue of the calling process.

get_local_members(Group)

Equivalent to get_local_members(pg, Group).

get_local_members(Scope, Group)

Returns all processes running on the local node in the group Group. Processes are returned in no specific order. This function is optimised for speed.

get_members(Group)

Equivalent to get_members(pg, Group).

get_members(Scope, Group)

Returns all processes in the group Group. Processes are returned in no specific order. This function is optimised for speed.

init_global_view(Scope, Options)

init_local_data(Options)

join(Group, PidOrPids)

Equivalent to join(pg, Group, PidOrPids).

join(Scope, Group, PidOrPids)

Joins single process or multiple processes to the group Group. A process can join a group many times and must then leave the group the same number of times.

leave(Group, PidOrPids)

Equivalent to leave(pg, Group, PidOrPids).

leave(Scope, Group, PidOrPids)

Makes the process PidOrPids leave the group Group. If the process is not a member of the group, not_joined is returned.

monitor(Group)

Equivalent to monitor(pg, Group).

monitor(Scope, Group)

Subscribes the caller to updates for the specified group.

monitor_scope()

Equivalent to monitor_scope(pg).

monitor_scope(Scope)

Subscribes the caller to updates from the specified scope.

new_subscription/2

start(Scope)

Starts additional scope.

start_link()

Starts the default pg scope within supervision tree.

start_link(Scope)

Equivalent to start(Scope), except that it also creates a link/1 with the calling process.

stop_global_view/1

translate_local_data/3

translate_message/2

translate_update/3

update_global_view_and_notify/4

update_local_data/2

version()

which_groups()

Equivalent to which_groups(pg).

which_groups(Scope)

Returns a list of all known groups.

Types

global_view()

(not exported) (since OTP 23.0)

-type global_view() :: {atom(), #{pid() => {reference(), [group()]}}}.

group()

(not exported) (since OTP 23.0)

-type group() :: term().

The identifier of a process group.

local_data()

(not exported) (since OTP 23.0)

-type local_data() :: #{group() => [pid()]}.

options()

(not exported) (since OTP 23.0)

-type options() :: map().

scope()

(not exported) (since OTP 23.0)

-type scope() :: atom().

subscribe_result()

(not exported) (since OTP 23.0)

-type subscribe_result() :: #{group() => [pid()]} | [pid()].

subscription()

(not exported) (since OTP 23.0)

-type subscription() :: scope | {group, group()}.

subscriptions()

(not exported) (since OTP 23.0)

-type subscriptions() :: #{subscription() => #{reference() => pid()}}.

update()

(not exported) (since OTP 23.0)

-type update() :: [{group(), Add :: [pid()], Remove :: [pid()]}].

version()

(not exported) (since OTP 23.0)

-type version() :: 0 | 1.

Functions

data_diff(Old, New)

(since OTP 29.0)

-spec data_diff(Old :: local_data(), New :: local_data()) -> update().

demonitor(Ref)

(since OTP 25.1)

-spec demonitor(Ref :: reference()) -> ok | false.

Equivalent to demonitor(pg, Ref).

demonitor(Scope, Ref)

(since OTP 25.1)

-spec demonitor(Scope :: atom(), Ref :: reference()) -> ok | false.

Unsubscribes the caller from updates (scope or group). Flushes all outstanding updates that were already in the message queue of the calling process.

get_local_members(Group)

(since OTP 23.0)

-spec get_local_members(Group :: group()) -> [pid()].

Equivalent to get_local_members(pg, Group).

get_local_members(Scope, Group)

(since OTP 23.0)

-spec get_local_members(Scope :: atom(), Group :: group()) -> [pid()].

Returns all processes running on the local node in the group Group. Processes are returned in no specific order. This function is optimised for speed.

get_members(Group)

(since OTP 23.0)

-spec get_members(Group :: group()) -> [pid()].

Equivalent to get_members(pg, Group).

get_members(Scope, Group)

(since OTP 23.0)

-spec get_members(Scope :: atom(), Group :: group()) -> [pid()].

Returns all processes in the group Group. Processes are returned in no specific order. This function is optimised for speed.

init_global_view(Scope, Options)

(since OTP 29.0)

-spec init_global_view(scope(), options()) -> global_view().

init_local_data(Options)

(since OTP 29.0)

-spec init_local_data(options()) -> local_data().

join(Group, PidOrPids)

(since OTP 23.0)

-spec join(Group :: group(), PidOrPids :: pid() | [pid()]) -> ok.

Equivalent to join(pg, Group, PidOrPids).

join(Scope, Group, PidOrPids)

(since OTP 23.0)

-spec join(Scope :: atom(), Group :: group(), PidOrPids :: pid() | [pid()]) -> ok.

Joins single process or multiple processes to the group Group. A process can join a group many times and must then leave the group the same number of times.

PidOrPids may contain the same process multiple times.

leave(Group, PidOrPids)

(since OTP 23.0)

-spec leave(Group :: group(), PidOrPids :: pid() | [pid()]) -> ok | not_joined.

Equivalent to leave(pg, Group, PidOrPids).

leave(Scope, Group, PidOrPids)

(since OTP 23.0)

-spec leave(Scope :: atom(), Group :: group(), PidOrPids :: pid() | [pid()]) -> ok | not_joined.

Makes the process PidOrPids leave the group Group. If the process is not a member of the group, not_joined is returned.

When list of processes is passed as PidOrPids, function returns not_joined only when all processes of the list are not joined.

monitor(Group)

(since OTP 25.1)

-spec monitor(Group :: group()) -> {reference(), [pid()]}.

Equivalent to monitor(pg, Group).

monitor(Scope, Group)

(since OTP 25.1)

-spec monitor(Scope :: atom(), Group :: group()) -> {reference(), [pid()]}.

Subscribes the caller to updates for the specified group.

Returns list of processes currently in the group, and a reference to match the upcoming notifications.

See monitor_scope/0 for the update message structure.

monitor_scope()

(since OTP 25.1)

-spec monitor_scope() -> {reference(), #{group() => [pid()]}}.

Equivalent to monitor_scope(pg).

monitor_scope(Scope)

(since OTP 25.1)

-spec monitor_scope(Scope :: atom()) -> {reference(), #{group() => [pid()]}}.

Subscribes the caller to updates from the specified scope.

Returns content of the entire scope and a reference to match the upcoming notifications.

Whenever any group membership changes, an update message is sent to the subscriber:

{Ref, join, Group, [JoinPid1, JoinPid2]}

{Ref, leave, Group, [LeavePid1]}

new_subscription/2

(since OTP 29.0)

-spec new_subscription(subscription(), global_view()) -> subscribe_result().

start(Scope)

(since OTP 23.0)

-spec start(Scope :: atom()) -> {ok, pid()} | {error, term()}.

Starts additional scope.

start_link()

(since OTP 23.0)

-spec start_link() -> {ok, pid()} | {error, term()}.

Starts the default pg scope within supervision tree.

Kernel may be configured to do it automatically by setting the Kernel configuration parameter start_pg.

start_link(Scope)

(since OTP 23.0)

-spec start_link(Scope :: atom()) -> {ok, pid()} | {error, term()}.

Equivalent to start(Scope), except that it also creates a link/1 with the calling process.

stop_global_view/1

(since OTP 29.0)

-spec stop_global_view(global_view()) -> term().

translate_local_data/3

(since OTP 29.0)

-spec translate_local_data(MyVersion :: version(), PeerVersion :: version(), local_data()) ->
                              local_data() | {'$plain_message', dynamic()}.

translate_message/2

(since OTP 29.0)

-spec translate_message({join, pid(), group(), pid() | [pid()]}, global_view()) ->
                           {update, pid(), update(), global_view()};
                       ({leave, pid(), pid() | [pid()], [group()]}, global_view()) ->
                           {update, pid(), update(), global_view()};
                       ({{'DOWN', pg}, reference(), process, pid(), dynamic()}, global_view()) ->
                           {update, update(), global_view()} | {drop, global_view()};
                       ({sync, pid(), [{group(), [pid()]}]}, global_view()) ->
                           {local_data, pid(), version(), local_data(), global_view()};
                       ({discover, pid()}, global_view()) -> {discover, pid(), version(), global_view()}.

translate_update/3

(since OTP 29.0)

-spec translate_update(MyVersion :: version(), PeerVersion :: version(), update()) ->
                          update() | {'$plain_messages', [dynamic()]}.

update_global_view_and_notify/4

(since OTP 29.0)

-spec update_global_view_and_notify(node(), update(), subscriptions(), global_view()) -> global_view().

update_local_data/2

(since OTP 29.0)

-spec update_local_data(update(), local_data()) -> local_data().

version()

(since OTP 29.0)

-spec version() -> version().

which_groups()

(since OTP 23.0)

-spec which_groups() -> [Group :: group()].

Equivalent to which_groups(pg).

which_groups(Scope)

(since OTP 23.0)

-spec which_groups(Scope :: atom()) -> [Group :: group()].

Returns a list of all known groups.

rpc

Remote Procedure Call services.

This module contains services similar to Remote Procedure Calls. It also contains broadcast facilities and parallel evaluators. A remote procedure call is a method to call a function on a remote node and collect the answer. It is used for collecting information on a remote node, or for running a function with some specific side effects on the remote node.

Note

rpc:call/4 and related functions make it difficult to distinguish between successful results, raised exceptions, and other errors. This behavior cannot be changed for compatibility reasons.

The erpc module was introduced in Erlang/OTP 23 to provide an API that allows clear distinction between these different outcomes. The erpc module offers the core subset of the functionality provided by the rpc module. It also features a more scalable and higher-performance implementation compared to the original rpc module.

Since the introduction of erpc, the rpc module has been updated to use erpc internally for most of its core functionality. As a result, the rpc module does not fall short in scalability or performance compared to erpc.

Note

For some important information about distributed signals, see the Blocking Signaling Over Distribution section in the Processes chapter of the Erlang Reference Manual. Blocking signaling can, for example, cause timeouts in rpc to be significantly delayed.

Summary

Types

key()

Opaque value returned by async_call/4.

Functions

abcast(Name, Msg)

Equivalent to abcast([node()|nodes()], Name, Msg).

abcast(Nodes, Name, Msg)

Broadcasts the message Msg asynchronously to the registered process Name on the specified nodes.

async_call(Node, Module, Function, Args)

Implements call streams with promises, a type of RPC that does not suspend the caller until the result is finished. Instead, a key is returned, which can be used later to collect the value. The key can be viewed as a promise to deliver the answer.

block_call(Node, Module, Function, Args)

The same as calling rpc:block_call(Node, Module, Function, Args, infinity).

block_call(Node, Module, Function, Args, Timeout)

The same as calling rpc:call(Node, Module, Function, Args, Timeout) with the exception that it also blocks other rpc:block_call/5 operations from executing concurrently on the node Node.

call(Node, Module, Function, Args)

Evaluates apply(Module, Function, Args) on node Node and returns the corresponding value Res, or {badrpc, Reason} if the call fails. The same as calling rpc:call(Node, Module, Function, Args, infinity).

call(Node, Module, Function, Args, Timeout)

Evaluates apply(Module, Function, Args) on node Node and returns the corresponding value Res, or {badrpc, Reason} if the call fails. Timeout is a time-out value in milliseconds. If the call times out, Reason is timeout.

cast(Node, Module, Function, Args)

Evaluates apply(Module, Function, Args) on node Node. No response is delivered and the calling process is not suspended until the evaluation is complete, as is the case with call/4,5.

eval_everywhere(Module, Function, Args)

Equivalent to eval_everywhere([node()|nodes()], Module, Function, Args).

eval_everywhere(Nodes, Module, Function, Args)

Evaluates apply(Module, Function, Args) on the specified nodes. No answers are collected.

multi_server_call(Name, Msg)

Equivalent to multi_server_call([node()|nodes()], Name, Msg).

multi_server_call(Nodes, Name, Msg)

Can be used when interacting with servers called Name on the specified nodes. It is assumed that the servers receive messages in the format {From, Msg} and reply using From ! {Name, Node, Reply}, where Node is the name of the node where the server is located. The function returns {Replies, BadNodes}, where Replies is a list of all Reply values, and BadNodes is one of the following

multicall(Module, Function, Args)

Equivalent to multicall([node()|nodes()], Module, Function, Args, infinity).

multicall/4

Equivalent to multicall(Nodes, Module, Function, Args, infinity).

multicall(Nodes, Module, Function, Args, Timeout)

In contrast to an RPC, a multicall is an RPC that is sent concurrently from one client to multiple servers. This is useful for collecting information from a set of nodes, or for calling a function on a set of nodes to achieve some side effects. It is semantically the same as iteratively making a series of RPCs on all the nodes, but the multicall is faster, as all the requests are sent at the same time and are collected one by one as they come back.

nb_yield(Key)

Equivalent to nb_yield(Key, 0).

nb_yield(Key, Timeout)

Non-blocking version of yield/1. It returns the tuple {value, Val} when the computation is finished, or timeout when Timeout milliseconds has elapsed.

parallel_eval(FuncCalls)

Evaluates, for every tuple in FuncCalls, apply(Module, Function, Args) on some node in the network. Returns the list of return values, in the same order as in FuncCalls.

pinfo(Pid)

Location transparent version of the BIF erlang:process_info/1 in ERTS.

pinfo/2

Location transparent version of the BIF erlang:process_info/2 in ERTS.

pmap(FuncSpec, ExtraArgs, List1)

Evaluates apply(Module, Function, [Elem|ExtraArgs]) for every element Elem in List1, in parallel. Returns the list of return values, in the same order as in List1.

sbcast(Name, Msg)

Equivalent to sbcast([node()|nodes()], Name, Msg).

sbcast(Nodes, Name, Msg)

Broadcasts the message Msg synchronously to the registered process Name on the specified nodes.

server_call(Node, Name, ReplyWrapper, Msg)

Can be used when interacting with a server called Name on node Node. It is assumed that the server receives messages in the format {From, Msg} and replies using From ! {ReplyWrapper, Node, Reply}. This function makes such a server call and ensures that the entire call is packed into an atomic transaction, which either succeeds or fails. It never hangs, unless the server itself hangs.

yield(Key)

Returns the promised answer from a previous async_call/4. If the answer is available, it is returned immediately. Otherwise, the calling process is suspended until the answer arrives from Node.

Types

key()

-opaque key()

Opaque value returned by async_call/4.

Functions

abcast(Name, Msg)

-spec abcast(Name, Msg) -> abcast when Name :: atom(), Msg :: term().

Equivalent to abcast([node()|nodes()], Name, Msg).

abcast(Nodes, Name, Msg)

-spec abcast(Nodes, Name, Msg) -> abcast when Nodes :: [node()], Name :: atom(), Msg :: term().

Broadcasts the message Msg asynchronously to the registered process Name on the specified nodes.

async_call(Node, Module, Function, Args)

-spec async_call(Node, Module, Function, Args) -> Key
                    when
                        Node :: node(),
                        Module :: module(),
                        Function :: atom(),
                        Args :: [term()],
                        Key :: key().

Implements call streams with promises, a type of RPC that does not suspend the caller until the result is finished. Instead, a key is returned, which can be used later to collect the value. The key can be viewed as a promise to deliver the answer.

In this case, the key Key is returned, which can be used in a subsequent call to yield/1 or nb_yield/1,2 to retrieve the value of evaluating apply(Module, Function, Args) on node Node.

Note

If you want the ability to distinguish between results, you may want to consider using the erpc:send_request() function from the erpc module instead. This also gives you the ability retrieve the results in other useful ways.

Note

yield/1 and nb_yield/1,2 must be called by the same process from which this function was made otherwise they will never yield correctly.

Note

You cannot make any assumptions about the process that will perform the apply(). It may be an rpc server, another server, or a freshly spawned process.

block_call(Node, Module, Function, Args)

-spec block_call(Node, Module, Function, Args) -> Res | {badrpc, Reason}
                    when
                        Node :: node(),
                        Module :: module(),
                        Function :: atom(),
                        Args :: [term()],
                        Res :: term(),
                        Reason :: term().

The same as calling rpc:block_call(Node, Module, Function, Args, infinity).

block_call(Node, Module, Function, Args, Timeout)

-spec block_call(Node, Module, Function, Args, Timeout) -> Res | {badrpc, Reason}
                    when
                        Node :: node(),
                        Module :: module(),
                        Function :: atom(),
                        Args :: [term()],
                        Res :: term(),
                        Reason :: term(),
                        Timeout :: 0..4294967295 | infinity.

The same as calling rpc:call(Node, Module, Function, Args, Timeout) with the exception that it also blocks other rpc:block_call/5 operations from executing concurrently on the node Node.

Warning

Note that it also blocks other operations than just rpc:block_call/5 operations, so use it with care.

call(Node, Module, Function, Args)

-spec call(Node, Module, Function, Args) -> Res | {badrpc, Reason}
              when
                  Node :: node(),
                  Module :: module(),
                  Function :: atom(),
                  Args :: [term()],
                  Res :: term(),
                  Reason :: term().

Evaluates apply(Module, Function, Args) on node Node and returns the corresponding value Res, or {badrpc, Reason} if the call fails. The same as calling rpc:call(Node, Module, Function, Args, infinity).

call(Node, Module, Function, Args, Timeout)

-spec call(Node, Module, Function, Args, Timeout) -> Res | {badrpc, Reason}
              when
                  Node :: node(),
                  Module :: module(),
                  Function :: atom(),
                  Args :: [term()],
                  Res :: term(),
                  Reason :: term(),
                  Timeout :: 0..4294967295 | infinity.

Evaluates apply(Module, Function, Args) on node Node and returns the corresponding value Res, or {badrpc, Reason} if the call fails. Timeout is a time-out value in milliseconds. If the call times out, Reason is timeout.

If the reply arrives after the call times out, no message contaminates the caller's message queue.

Note

If you want the ability to distinguish between results, you may want to consider using the erpc:call() function from the erpc module instead.

Note

Here follows the details of what exactly is returned.

{badrpc, Reason} will be returned in the following circumstances:

The called function fails with an exit exception.

The called function fails with an error exception.

The called function returns a term that matches {'EXIT', _}.

The called function throws a term that matches {'EXIT', _}.

Res is returned in the following circumstances:

The called function returns normally with a term that does not match {'EXIT',_}.

The called function throws a term that does not match {'EXIT',_}.

Note

You cannot make any assumptions about the process that will perform the apply(). It may be the calling process itself, an rpc server, another server, or a freshly spawned process.

cast(Node, Module, Function, Args)

-spec cast(Node, Module, Function, Args) -> true
              when Node :: node(), Module :: module(), Function :: atom(), Args :: [term()].

Evaluates apply(Module, Function, Args) on node Node. No response is delivered and the calling process is not suspended until the evaluation is complete, as is the case with call/4,5.

Note

You cannot make any assumptions about the process that will perform the apply(). It may be an rpc server, another server, or a freshly spawned process.

eval_everywhere(Module, Function, Args)

-spec eval_everywhere(Module, Function, Args) -> abcast
                         when Module :: module(), Function :: atom(), Args :: [term()].

Equivalent to eval_everywhere([node()|nodes()], Module, Function, Args).

eval_everywhere(Nodes, Module, Function, Args)

-spec eval_everywhere(Nodes, Module, Function, Args) -> abcast
                         when
                             Nodes :: [node()], Module :: module(), Function :: atom(), Args :: [term()].

Evaluates apply(Module, Function, Args) on the specified nodes. No answers are collected.

multi_server_call(Name, Msg)

-spec multi_server_call(Name, Msg) -> {Replies, BadNodes}
                           when
                               Name :: atom(),
                               Msg :: term(),
                               Replies :: [Reply :: term()],
                               BadNodes :: [node()].

Equivalent to multi_server_call([node()|nodes()], Name, Msg).

multi_server_call(Nodes, Name, Msg)

-spec multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes}
                           when
                               Nodes :: [node()],
                               Name :: atom(),
                               Msg :: term(),
                               Replies :: [Reply :: term()],
                               BadNodes :: [node()].

Can be used when interacting with servers called Name on the specified nodes. It is assumed that the servers receive messages in the format {From, Msg} and reply using From ! {Name, Node, Reply}, where Node is the name of the node where the server is located. The function returns {Replies, BadNodes}, where Replies is a list of all Reply values, and BadNodes is one of the following:

A list of the nodes that do not exist

A list of the nodes where the server does not exist

A list of the nodes where the server terminated before sending any reply.

multicall(Module, Function, Args)

-spec multicall(Module, Function, Args) -> {ResL, BadNodes}
                   when
                       Module :: module(),
                       Function :: atom(),
                       Args :: [term()],
                       ResL :: [Res :: term() | {badrpc, Reason :: term()}],
                       BadNodes :: [node()].

Equivalent to multicall([node()|nodes()], Module, Function, Args, infinity).

multicall/4

-spec multicall(Nodes, Module, Function, Args) -> {ResL, BadNodes}
                   when
                       Nodes :: [node()],
                       Module :: module(),
                       Function :: atom(),
                       Args :: [term()],
                       ResL :: [Res :: term() | {badrpc, Reason :: term()}],
                       BadNodes :: [node()];
               (Module, Function, Args, Timeout) -> {ResL, BadNodes}
                   when
                       Module :: module(),
                       Function :: atom(),
                       Args :: [term()],
                       Timeout :: 0..4294967295 | infinity,
                       ResL :: [Res :: term() | {badrpc, Reason :: term()}],
                       BadNodes :: [node()].

Equivalent to multicall(Nodes, Module, Function, Args, infinity).

Equivalent to multicall([node()|nodes()], Module, Function, Args, Timeout).

multicall(Nodes, Module, Function, Args, Timeout)

-spec multicall(Nodes, Module, Function, Args, Timeout) -> {ResL, BadNodes}
                   when
                       Nodes :: [node()],
                       Module :: module(),
                       Function :: atom(),
                       Args :: [term()],
                       Timeout :: 0..4294967295 | infinity,
                       ResL :: [Res :: term() | {badrpc, Reason :: term()}],
                       BadNodes :: [node()].

In contrast to an RPC, a multicall is an RPC that is sent concurrently from one client to multiple servers. This is useful for collecting information from a set of nodes, or for calling a function on a set of nodes to achieve some side effects. It is semantically the same as iteratively making a series of RPCs on all the nodes, but the multicall is faster, as all the requests are sent at the same time and are collected one by one as they come back.

The function evaluates apply(Module, Function, Args) on the specified nodes and collects the answers. It returns {ResL, BadNodes}, where BadNodes is a list of the nodes that do not exist, and ResL is a list of the return values, or {badrpc, Reason} for failing calls. Timeout is a time (integer) in milliseconds, or infinity.

The following example is useful when new object code is to be loaded on all nodes in the network, and indicates some side effects that RPCs can produce:

%% Find object code for module Mod
{Mod, Bin, File} = code:get_object_code(Mod),

%% and load it on all nodes including this one
{ResL, _} = rpc:multicall(code, load_binary, [Mod, File, Bin]),

%% and then maybe check the ResL list.

Note

If you want the ability to distinguish between results, you may want to consider using the erpc:multicall() function from the erpc module instead.

Note

You cannot make any assumptions about the process that will perform the apply(). It may be the calling process itself, an rpc server, another server, or a freshly spawned process.

nb_yield(Key)

-spec nb_yield(Key) -> {value, Val} | timeout
                  when Key :: key(), Val :: (Res :: term()) | {badrpc, Reason :: term()}.

Equivalent to nb_yield(Key, 0).

nb_yield(Key, Timeout)

-spec nb_yield(Key, Timeout) -> {value, Val} | timeout
                  when
                      Key :: key(),
                      Timeout :: 0..4294967295 | infinity,
                      Val :: (Res :: term()) | {badrpc, Reason :: term()}.

Non-blocking version of yield/1. It returns the tuple {value, Val} when the computation is finished, or timeout when Timeout milliseconds has elapsed.

See the note in call/4 for more details of Val.

Note

This function must be called by the same process from which async_call/4 was made otherwise it will only return timeout.

parallel_eval(FuncCalls)

-spec parallel_eval(FuncCalls) -> ResL
                       when
                           FuncCalls :: [{Module, Function, Args}],
                           Module :: module(),
                           Function :: atom(),
                           Args :: [term()],
                           ResL :: [term()].

Evaluates, for every tuple in FuncCalls, apply(Module, Function, Args) on some node in the network. Returns the list of return values, in the same order as in FuncCalls.

pinfo(Pid)

-spec pinfo(Pid) -> [{Item, Info}] | undefined when Pid :: pid(), Item :: atom(), Info :: term().

Location transparent version of the BIF erlang:process_info/1 in ERTS.

pinfo/2

-spec pinfo(Pid, Item) -> {Item, Info} | undefined | []
               when Pid :: pid(), Item :: atom(), Info :: term();
           (Pid, ItemList) -> [{Item, Info}] | undefined | []
               when Pid :: pid(), Item :: atom(), ItemList :: [Item], Info :: term().

Location transparent version of the BIF erlang:process_info/2 in ERTS.

pmap(FuncSpec, ExtraArgs, List1)

-spec pmap(FuncSpec, ExtraArgs, List1) -> List2
              when
                  FuncSpec :: {Module, Function},
                  Module :: module(),
                  Function :: atom(),
                  ExtraArgs :: [term()],
                  List1 :: [Elem :: term()],
                  List2 :: [term()].

Evaluates apply(Module, Function, [Elem|ExtraArgs]) for every element Elem in List1, in parallel. Returns the list of return values, in the same order as in List1.

sbcast(Name, Msg)

-spec sbcast(Name, Msg) -> {GoodNodes, BadNodes}
                when Name :: atom(), Msg :: term(), GoodNodes :: [node()], BadNodes :: [node()].

Equivalent to sbcast([node()|nodes()], Name, Msg).

sbcast(Nodes, Name, Msg)

-spec sbcast(Nodes, Name, Msg) -> {GoodNodes, BadNodes}
                when
                    Name :: atom(),
                    Msg :: term(),
                    Nodes :: [node()],
                    GoodNodes :: [node()],
                    BadNodes :: [node()].

Broadcasts the message Msg synchronously to the registered process Name on the specified nodes.

Returns {GoodNodes, BadNodes}, where GoodNodes is the list of nodes that have Name as a registered process.

The function is synchronous in the sense that it is known that all servers have received the message when the call returns. It is not possible to know that the servers have processed the message.

Any further messages sent to the servers, after this function has returned, are received by all servers after this message.

server_call(Node, Name, ReplyWrapper, Msg)

-spec server_call(Node, Name, ReplyWrapper, Msg) -> Reply | {error, Reason}
                     when
                         Node :: node(),
                         Name :: atom(),
                         ReplyWrapper :: term(),
                         Msg :: term(),
                         Reply :: term(),
                         Reason :: nodedown.

Can be used when interacting with a server called Name on node Node. It is assumed that the server receives messages in the format {From, Msg} and replies using From ! {ReplyWrapper, Node, Reply}. This function makes such a server call and ensures that the entire call is packed into an atomic transaction, which either succeeds or fails. It never hangs, unless the server itself hangs.

The function returns the answer Reply as produced by the server Name, or {error, Reason}.

yield(Key)

-spec yield(Key) -> Res | {badrpc, Reason} when Key :: key(), Res :: term(), Reason :: term().

Returns the promised answer from a previous async_call/4. If the answer is available, it is returned immediately. Otherwise, the calling process is suspended until the answer arrives from Node.

Note

This function must be called by the same process from which async_call/4 was made otherwise it will never return.

See the note in call/4 for more details of the return value.

code

Interface to the Erlang code server process.

This module contains the interface to the Erlang code server, which deals with the loading of compiled code into a running Erlang runtime system.

The runtime system can be started in interactive or embedded mode. Which one is decided by the command-line flag -mode:

% erl -mode embedded

The modes are as follows:

In interactive mode, which is default, only the modules needed by the runtime system are loaded during system startup. Other code is dynamically loaded when first referenced. When a call to a function in a certain module is made, and that module is not loaded, the code server searches for and tries to load that module.

In embedded mode, modules are not auto-loaded. Trying to use a module that has not been loaded results in an error. This mode is recommended when the boot script loads all modules, as it is typically done in OTP releases. (Code can still be loaded later by explicitly ordering the code server to do so).

To prevent accidentally reloading of modules affecting the Erlang runtime system, directories kernel, stdlib, and compiler are considered sticky. This means that the system issues a warning and rejects the request if a user tries to reload a module residing in any of them. The feature can be disabled by using command-line flag -nostick.

Code Path

In interactive mode, the code server maintains a code path, consisting of a list of directories, which it searches sequentially when trying to load a module.

Initially, the code path consists of the current working directory and all Erlang object code directories under library directory $OTPROOT/lib, where $OTPROOT is the installation directory of Erlang/OTP, code:root_dir(). Directories can be named Name[-Vsn] and the code server, by default, chooses the directory with the highest version number among those having the same Name. Suffix -Vsn is optional. If an ebin directory exists under Name[-Vsn], this directory is added to the code path.

Environment variable ERL_LIBS (defined in the operating system) can be used to define more library directories to be handled in the same way as the standard OTP library directory described above, except that directories without an ebin directory are ignored.

All application directories found in the additional directories appear before the standard OTP applications, except for the Kernel and STDLIB applications, which are placed before any additional applications. In other words, modules found in any of the additional library directories override modules with the same name in OTP, except for modules in Kernel and STDLIB.

Environment variable ERL_LIBS (if defined) is to contain a colon-separated (for Unix-like systems) or semicolon-separated (for Windows) list of additional libraries.

Example:

On a Unix-like system, ERL_LIBS can be set to the following:

/usr/local/jungerl:/home/some_user/my_erlang_lib

The code paths specified by $OTPROOT, ERL_LIBS, and boot scripts have their listings cached by default (except for ".") The code server will lookup the contents in their directories once and avoid future file system traversals. Therefore, modules added to such directories after the Erlang VM boots will not be picked up. This behaviour can be disabled by setting -cache_boot_paths false or by calling code:set_path(code:get_path()).

Change

The support for caching directories in the code path was added in Erlang/OTP 26.

Directories given by the command line options -pa and -pz are not cached by default. Many of the functions that manipulate the code path accept the cache atom as an optional argument to enable caching selectively.

Loading of Code From Archive Files

Change

The existing experimental support for archive files will be changed in a future release. As of Erlang/OTP 27, the function code:lib_dir/2, the -code_path_choice flag, and using erl_prim_loader for reading files from an archive are deprecated.

escript scripts that use archive files should use escript:extract/2 to read data files from its archive instead of using code:lib_dir/2 and erl_prim_loader.

The Erlang archives are ZIP files with extension .ez. Erlang archives can also be enclosed in escript files whose file extension is arbitrary.

Erlang archive files can contain entire Erlang applications or parts of applications. The structure in an archive file is the same as the directory structure for an application. If you, for example, create an archive of mnesia-4.4.7, the archive file must be named mnesia-4.4.7.ez and it must contain a top directory named mnesia-4.4.7. If the version part of the name is omitted, it must also be omitted in the archive. That is, a mnesia.ez archive must contain a mnesia top directory.

An archive file for an application can, for example, be created like this:

zip:create("mnesia-4.4.7.ez",
	["mnesia-4.4.7"],
	[{cwd, code:lib_dir()},
	 {compress, all},
	 {uncompress,[".beam",".app"]}]).

Any file in the archive can be compressed, but to speed up the access of frequently read files, it can be a good idea to store beam and app files uncompressed in the archive.

Normally the top directory of an application is located in library directory $OTPROOT/lib or in a directory referred to by environment variable ERL_LIBS. At startup, when the initial code path is computed, the code server also looks for archive files in these directories and possibly adds ebin directories in archives to the code path. The code path then contains paths to directories that look like $OTPROOT/lib/mnesia.ez/mnesia/ebin or $OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin.

The code server uses module erl_prim_loader in ERTS (possibly through erl_boot_server) to read code files from archives. However, the functions in erl_prim_loader can also be used by other applications to read files from archives. For example, the call erl_prim_loader:list_dir( "/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)" would list the contents of a directory inside an archive. See erl_prim_loader.

An application archive file and a regular application directory can coexist. This can be useful when it is needed to have parts of the application as regular files. A typical case is the priv directory, which must reside as a regular directory to link in drivers dynamically and start port programs. For other applications that do not need this, directory priv can reside in the archive and the files under the directory priv can be read through erl_prim_loader.

When a directory is added to the code path and when the entire code path is (re)set, the code server decides which subdirectories in an application that are to be read from the archive and which that are to be read as regular files. If directories are added or removed afterwards, the file access can fail if the code path is not updated (possibly to the same path as before, to trigger the directory resolution update).

For each directory on the second level in the application archive (ebin, priv, src, and so on), the code server first chooses the regular directory if it exists and second from the archive. Function code:lib_dir/2 returns the path to the subdirectory. For example, code:lib_dir(megaco, ebin) can return /otp/root/lib/megaco-3.9.1.1.ez/megaco-3.9.1.1/ebin while code:lib_dir(megaco, priv) can return /otp/root/lib/megaco-3.9.1.1/priv.

When an escript file contains an archive, there are no restrictions on the name of the escript and no restrictions on how many applications that can be stored in the embedded archive. Single Beam files can also reside on the top level in the archive. At startup, the top directory in the embedded archive and all (second level) ebin directories in the embedded archive are added to the code path. See escript.

A future-proof way for escript scripts to read data files from the archive is to use the escript:extract/2 function.

When the choice of directories in the code path is strict (which is the default as of Erlang/OTP 27), the directory that ends up in the code path is exactly the stated one. This means that if, for example, the directory $OTPROOT/lib/mnesia-4.4.7/ebin is explicitly added to the code path, the code server does not load files from $OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin.

This behavior can be controlled through command-line flag -code_path_choice Choice. If the flag is set to relaxed, the code server instead chooses a suitable directory depending on the actual file structure. If a regular application ebin directory exists, it is chosen. Otherwise, the directory ebin in the archive is chosen if it exists. If neither of them exists, the original directory is chosen.

Command-line flag -code_path_choice Choice also affects how module init interprets the boot script. The interpretation of the explicit code paths in the boot script can be strict or relaxed. It is particularly useful to set the flag to relaxed when elaborating with code loading from archives without editing the boot script. The default has changed to strict in OTP 27 and the option is scheduled for removal in OTP 28. See module init in the Erts application.

Current and Old Code

The code for a module can exist in two variants in a system: current code and old code. When a module is loaded into the system for the first time, the module code becomes current and the global export table is updated with references to all functions exported from the module.

When a new instance of the module is loaded, the code of the previous instance becomes old, and all export entries referring to the previous instance are removed. After that, the new instance is loaded as for the first time, and becomes current.

Both old and current code for a module are valid, and can even be executed concurrently. The difference is that exported functions in old code are unavailable. Hence, a global call cannot be made to an exported function in old code, but old code can still be executed because of processes lingering in it.

If a third instance of the module is loaded, the code server removes (purges) the old code and any processes lingering in it are terminated. Then the third instance becomes current and the previously current code becomes old.

For more information about old and current code, and how to make a process switch from old to current code, see section Compilation and Code Loading in the Erlang Reference Manual.

Native Coverage Support

In runtime systems that use the JIT, native coverage is a light-weight way to find out which functions or lines that have been executed, or how many times each function or line has been executed.

Change

The support for native coverage was added in Erlang/OTP 27.

Native coverage works by instrumenting code at load-time. When a module has been instrumented for native coverage collection it is not possible to later disable the coverage collection, except by reloading the module. However, the overhead for keeping coverage collection running is often neligible, especially for coverage mode function that only keeps track of which functions that have been executed.

The cover tool in the Tools application will automatically use the native coverage support if the runtime system supports it.

It is only necessary to use the functionality described next if cover is not sufficient, for example:

If one wants to collect coverage information for the code that runs when the runtime system is starting (module init and so on). cover can only be used when the Erlang system has started, and it will reload every module that is to be analyzed.

If it is necessary to collect coverage information with the absolute minimum disturbance of the test system. cover always counts how many times each line is executed (coverage mode line_counters), but by using native coverage one can use a less expensive coverage mode such as function, which has almost negligible overhead.

Short summary of using native coverage

If the line or line_counters coverage mode is to be used, the code to be tested must be compiled with option line_coverage.

Use set_coverage_mode(Mode) to set a coverage mode for all code subsequently loaded, or set it with option +JPcover for erl.

Optionally reset coverage information for all modules that are to be tested by calling reset_coverage(Module).

Run the code whose coverage information is to be collected.

Read out the counters for all interesting modules by calling get_coverage(Level, Module), where Level is either function or line.

The other native coverage BIFs

The following BIFs are sometimes useful, for example to fail gracefully if the runtime system does not support native coverage:

coverage_support() - check whether the runtime system supports native coverage

get_coverage_mode() - get the current coverage mode

get_coverage_mode(Module) - get the coverage mode for module Module

Argument Types and Invalid Arguments

Module and application names are atoms, while file and directory names are strings. For backward compatibility reasons, some functions accept both strings and atoms, but a future release will probably only allow the arguments that are documented.

Functions in this module generally fail with an exception if they are passed an incorrect type (for example, an integer or a tuple where an atom is expected). An error tuple is returned if the argument type is correct, but there are some other errors (for example, a non-existing directory is specified to set_path/1).

Error Reasons for Code-Loading Functions

Functions that load code (such as load_file/1) will return {error,Reason} if the load operation fails. Here follows a description of the common reasons.

badfile - The object code has an incorrect format or the module name in the object code is not the expected module name.

nofile - No file with object code was found.

not_purged - The object code could not be loaded because an old version of the code already existed.

on_load_failure - The module has an -on_load function that failed when it was called.

sticky_directory - The object code resides in a sticky directory.

Summary

Types

add_path_ret()

cache()

coverage_mode()

debug_atom_or_var()

debug_call()

debug_frame()

debug_info()

debug_line()

debug_name()

debug_source()

debug_value()

debug_var()

load_error_rsn()

load_ret()

loaded_filename()

loaded_ret_atoms()

module_status()

prepared_code()

An opaque term holding prepared code.

replace_path_ret()

set_path_ret()

Functions

add_path(Dir)

Equivalent to add_pathz(Dir, nocache).

add_path(Dir, Cache)

Equivalent to add_pathz(Dir, Cache).

add_patha(Dir)

Equivalent to add_patha(Dir, nocache).

add_patha(Dir, Cache)

Adds Dir to the beginning of the code path.

add_paths(Dirs)

Equivalent to add_pathsz(Dirs, nocache).

add_paths(Dirs, Cache)

Equivalent to add_pathsz(Dirs, Cache).

add_pathsa(Dirs)

Equivalent to add_pathsa(Dirs, nocache).

add_pathsa(Dirs, Cache)

Traverses Dirs and adds each Dir to the beginning of the code path.

add_pathsz(Dirs)

Equivalent to add_pathsz(Dirs, nocache).

add_pathsz(Dirs, Cache)

Adds the directories in Dirs to the end of the code path.

add_pathz(Dir)

Equivalent to add_pathz(Dir, nocache).

add_pathz(Dir, Cache)

Adds Dir as the directory last in the code path.

all_available()

Returns a list of tuples {Module, Filename, Loaded} for all available modules.

all_loaded()

Returns a list of tuples {Module, Loaded} for all loaded modules.

atomic_load(Modules)

Tries to load all of the modules in the list Modules atomically.

clash()

Searches all directories in the code path for module names with identical names and writes a report to stdout.

clear_cache()

Clears the code path cache.

compiler_dir()

Returns the compiler library directory.

coverage_support()

Returns true if the system supports coverage and false otherwise.

del_path(NameOrDir)

Deletes a directory from the code path.

del_paths(NamesOrDirs)

Deletes directories from the code path.

delete(Module)

Removes the current code for Module, that is, the current code for Module is made old.

ensure_loaded(Module)

Tries to load a module in the same way as load_file/1, unless the module is already loaded.

ensure_modules_loaded(Modules)

Tries to load any modules not already loaded in the list Modules in the same way as load_file/1.

finish_loading(Prepared)

Tries to load code for all modules that have been previously prepared by prepare_loading/1.

get_coverage(Level, Module)

Return either function or line coverage data for module Module.

get_coverage_mode()

Returns the coverage mode as set by option +JPcover for erl or set_coverage_mode/1.

get_coverage_mode(Module)

Get coverage mode for the given module.

get_debug_info(Module)

get_doc(Module)

Returns EEP 48 style documentation for Module if available.

get_mode()

Returns an atom describing the mode of the code server: interactive or embedded.

get_object_code(Module)

Returns the object code for module Module if found in the code path.

get_path()

Returns the code path.

is_loaded(Module)

Checks whether Module is loaded.

is_sticky(Module)

Returns true if Module is the name of a module that has been loaded from a sticky directory (in other words: an attempt to reload the module will fail), or false if Module is not a loaded module or is not sticky.

lib_dir()

Returns the library directory, $OTPROOT/lib, where $OTPROOT is the root directory of Erlang/OTP.

lib_dir(Name)

Returns the path for the library directory, the top directory, for an application Name located under $OTPROOT/lib or in a directory referred to with environment variable ERL_LIBS.

lib_dir(Name, SubDir) deprecated

Returns the path to a subdirectory directly under the top directory of an application.

load_abs(Filename)

Equivalent to load_file(Module), except that Filename is an absolute or relative filename.

load_binary(Module, Filename, Binary)

Loads object code from a binary.

load_file(Module)

Tries to load the Erlang module Module using the code path.

modified_modules()

Returns the list of all currently loaded modules for which module_status/1 returns modified.

module_status()

See module_status/1 and all_loaded/0 for details.

module_status(Module)

Returns the status of Module in relation to object file on disk.

objfile_extension()

Returns the object code file extension corresponding to the Erlang machine used.

prepare_loading(Modules)

Prepares to load the modules in the list Modules.

priv_dir(Name)

Returns the path to the priv directory in an application.

purge(Module)

Purges the code for Module, that is, removes code marked as old.

replace_path(Name, Dir)

Equivalent to replace_path(Name, Dir, nocache).

replace_path(Name, Dir, Cache)

Replaces an old occurrence of a directory named .../Name[-Vsn][/ebin] in the code path, with Dir.

reset_coverage(Module)

Resets coverage information for module Module.

root_dir()

Returns the root directory of Erlang/OTP, which is the directory where it is installed.

set_coverage_mode(Mode)

Sets the coverage mode for modules that are subsequently loaded, similar to option +JPcover for erl.

set_path(Path)

Equivalent to set_path(PathList, nocache).

set_path(PathList, Cache)

Sets the code path to the list of directories Path.

soft_purge(Module)

Purges the code for Module, that is, removes code marked as old, but only if no processes linger in it.

stick_dir(Dir)

Marks Dir as sticky.

unstick_dir(Dir)

Unsticks a directory that is marked as sticky.

where_is_file(Filename)

Searches the code path for Filename, which is a file of arbitrary type.

which(Module)

If the module is not loaded, this function searches the code path for the first file containing object code for Module and returns the absolute filename.

Types

add_path_ret()

(not exported)

-type add_path_ret() :: true | {error, bad_directory}.

cache()

(not exported)

-type cache() :: cache | nocache.

coverage_mode()

-type coverage_mode() :: none | function | function_counters | line | line_counters.

debug_atom_or_var()

-nominal debug_atom_or_var() :: atom() | debug_var().

debug_call()

-nominal debug_call() ::
             MFA ::
                 {debug_atom_or_var(), debug_atom_or_var(), arity()} |
                 (FA :: {debug_atom_or_var(), arity()} | debug_var()).

debug_frame()

-nominal debug_frame() :: non_neg_integer() | entry | none.

debug_info()

-nominal debug_info() ::
             [{debug_line(),
               #{frame_size => debug_frame(), vars => [debug_value()], calls => [debug_call()]}}].

debug_line()

-nominal debug_line() :: pos_integer().

debug_name()

-nominal debug_name() :: debug_var() | 1..255.

debug_source()

-nominal debug_source() :: {x, non_neg_integer()} | {y, non_neg_integer()} | {value, _}.

debug_value()

-nominal debug_value() :: {debug_name(), debug_source()}.

debug_var()

-nominal debug_var() :: binary().

load_error_rsn()

-type load_error_rsn() :: badfile | nofile | not_purged | on_load_failure | sticky_directory.

load_ret()

-type load_ret() :: {error, What :: load_error_rsn()} | {module, Module :: module()}.

loaded_filename()

(not exported)

-type loaded_filename() :: (Filename :: file:filename()) | loaded_ret_atoms().

loaded_ret_atoms()

(not exported)

-type loaded_ret_atoms() :: cover_compiled | preloaded.

module_status()

-type module_status() :: not_loaded | loaded | modified | removed.

prepared_code()

-opaque prepared_code()

An opaque term holding prepared code.

replace_path_ret()

(not exported)

-type replace_path_ret() :: true | {error, bad_directory | bad_name | {badarg, _}}.

set_path_ret()

(not exported)

-type set_path_ret() :: true | {error, bad_directory}.

Functions

add_path(Dir)

-spec add_path(Dir) -> add_path_ret() when Dir :: file:filename().

Equivalent to add_pathz(Dir, nocache).

add_path(Dir, Cache)

(since OTP 26.0)

-spec add_path(Dir, cache()) -> add_path_ret() when Dir :: file:filename().

Equivalent to add_pathz(Dir, Cache).

add_patha(Dir)

-spec add_patha(Dir) -> add_path_ret() when Dir :: file:filename().

Equivalent to add_patha(Dir, nocache).

add_patha(Dir, Cache)

(since OTP 26.0)

-spec add_patha(Dir, cache()) -> add_path_ret() when Dir :: file:filename().

Adds Dir to the beginning of the code path.

If Dir exists, it is removed from the old position in the code path.

Argument Cache controls whether the content of the directory should be cached on first traversal. If Cache is cache the directory contents will be cached; if Cache is nocache it will not be cached.

Returns true if successful, or {error, bad_directory} if Dir is not the name of a directory.

add_paths(Dirs)

-spec add_paths(Dirs) -> ok when Dirs :: [Dir :: file:filename()].

Equivalent to add_pathsz(Dirs, nocache).

add_paths(Dirs, Cache)

(since OTP 26.0)

-spec add_paths(Dirs, cache()) -> ok when Dirs :: [Dir :: file:filename()].

Equivalent to add_pathsz(Dirs, Cache).

add_pathsa(Dirs)

-spec add_pathsa(Dirs) -> ok when Dirs :: [Dir :: file:filename()].

Equivalent to add_pathsa(Dirs, nocache).

add_pathsa(Dirs, Cache)

(since OTP 26.0)

-spec add_pathsa(Dirs, cache()) -> ok when Dirs :: [Dir :: file:filename()].

Traverses Dirs and adds each Dir to the beginning of the code path.

This means that the order of Dirs is reversed in the resulting code path. For example, if Dirs is [Dir1,Dir2], the resulting path will be [Dir2,Dir1|OldCodePath].

If a Dir already exists in the code path, it is removed from the old position.

Argument Cache controls whether the content of the directory should be cached on first traversal. If Cache is cache the directory contents will be cached; if Cache is nocache it will not be cached.

Always returns ok, regardless of the validity of each individual Dir.

add_pathsz(Dirs)

-spec add_pathsz(Dirs) -> ok when Dirs :: [Dir :: file:filename()].

Equivalent to add_pathsz(Dirs, nocache).

add_pathsz(Dirs, Cache)

(since OTP 26.0)

-spec add_pathsz(Dirs, cache()) -> ok when Dirs :: [Dir :: file:filename()].

Adds the directories in Dirs to the end of the code path.

Directories that are already present in the path will not be added.

Argument Cache controls whether the content of the directory should be cached on first traversal. If Cache is cache the directory contents will be cached; if Cache is nocache it will not be cached.

Always returns ok, regardless of the validity of each individual Dir.

add_pathz(Dir)

-spec add_pathz(Dir) -> add_path_ret() when Dir :: file:filename().

Equivalent to add_pathz(Dir, nocache).

add_pathz(Dir, Cache)

(since OTP 26.0)

-spec add_pathz(Dir, cache()) -> add_path_ret() when Dir :: file:filename().

Adds Dir as the directory last in the code path.

If Dir already exists in the path, it is not added.

Argument Cache controls whether the content of the directory should be cached on first traversal. If Cache is cache the directory contents will be cached; if Cache is nocache it will not be cached.

Returns true if successful, or {error, bad_directory} if Dir is not the name of a directory.

all_available()

(since OTP 23.0)

-spec all_available() -> [{Module, Filename, Loaded}]
                       when Module :: string(), Filename :: loaded_filename(), Loaded :: boolean().

Returns a list of tuples {Module, Filename, Loaded} for all available modules.

A module is considered to be available if it either is loaded or would be loaded if called. Filename is normally the absolute filename, as described for is_loaded/1.

all_loaded()

-spec all_loaded() -> [{Module, Loaded}] when Module :: module(), Loaded :: loaded_filename().

Returns a list of tuples {Module, Loaded} for all loaded modules.

Loaded is normally the absolute filename, as described for is_loaded/1.

atomic_load(Modules)

(since OTP 19.0)

-spec atomic_load(Modules) -> ok | {error, [{Module, What}]}
                     when
                         Modules :: [Module | {Module, Filename, Binary}],
                         Module :: module(),
                         Filename :: file:filename(),
                         Binary :: binary(),
                         What ::
                             badfile | nofile | on_load_not_allowed | duplicated | not_purged |
                             sticky_directory | pending_on_load.

Tries to load all of the modules in the list Modules atomically.

That means that either all modules are loaded at the same time, or none of the modules are loaded if there is a problem with any of the modules.

Loading can fail for one the following reasons:

badfile - The object code has an incorrect format or the module name in the object code is not the expected module name.

nofile - No file with object code exists.

on_load_not_allowed - A module contains an -on_load function.

duplicated - A module is included more than once in Modules.

not_purged - The object code cannot be loaded because an old version of the code already exists.

sticky_directory - The object code resides in a sticky directory.

pending_on_load - A previously loaded module contains an -on_load function that never finished.

If it is important to minimize the time that an application is inactive while changing code, use prepare_loading/1 and finish_loading/1 instead of atomic_load/1. Here is an example:

{ok,Prepared} = code:prepare_loading(Modules),
%% Put the application into an inactive state or do any
%% other preparation needed before changing the code.
ok = code:finish_loading(Prepared),
%% Resume the application.

clash()

-spec clash() -> ok.

Searches all directories in the code path for module names with identical names and writes a report to stdout.

clear_cache()

(since OTP 26.0)

-spec clear_cache() -> ok.

Clears the code path cache.

If a directory is cached, its cache is cleared once and then it will be recalculated and cached once more in a future traversal.

To clear the cache for a single path, either re-add it to the code path (with add_path/2) or replace it (with replace_path/3). To disable all caching, reset the code path with code:set_path(code:get_path()).

Always returns ok.

compiler_dir()

-spec compiler_dir() -> file:filename().

Returns the compiler library directory.

Equivalent to code:lib_dir(compiler).

coverage_support()

(since OTP 27.0)

-spec coverage_support() -> Supported when Supported :: boolean().

Returns true if the system supports coverage and false otherwise.

See also: Native Coverage Support

del_path(NameOrDir)

-spec del_path(NameOrDir) -> boolean() | {error, What}
                  when NameOrDir :: Name | Dir, Name :: atom(), Dir :: file:filename(), What :: bad_name.

Deletes a directory from the code path.

The argument can be an atom Name, in which case the directory with the name .../Name[-Vsn][/ebin] is deleted from the code path. Also, the complete directory name Dir can be specified as argument.

Returns:

true - If successful

false - If the directory is not found

{error, bad_name} - If the argument is invalid

del_paths(NamesOrDirs)

(since OTP 26.0)

-spec del_paths(NamesOrDirs) -> ok
                   when NamesOrDirs :: [Name | Dir], Name :: atom(), Dir :: file:filename().

Deletes directories from the code path.

The argument is a list of either atoms or complete directory names. If Name is an atom, the directory with the name .../Name[-Vsn][/ebin] is deleted from the code path.

Always returns ok, regardless of the validity of each individual NamesOrDirs.

delete(Module)

-spec delete(Module) -> boolean() when Module :: module().

Removes the current code for Module, that is, the current code for Module is made old.

This means that processes can continue to execute the code in the module, but no external function calls can be made to it.

Returns true if successful, or false if there is old code for Module that must be purged first, or if Module is not a (loaded) module.

ensure_loaded(Module)

-spec ensure_loaded(Module) -> {module, Module} | {error, What}
                       when Module :: module(), What :: embedded | badfile | nofile | on_load_failure.

Tries to load a module in the same way as load_file/1, unless the module is already loaded.

If called concurrently, this function ensures that only one process attempts to load said module at a given time.

In embedded mode, it does not load a module that is not already loaded, but returns {error, embedded} instead. See Error Reasons for Code-Loading Functions for a description of other possible error reasons.

ensure_modules_loaded(Modules)

(since OTP 19.0)

-spec ensure_modules_loaded([Module]) -> ok | {error, [{Module, What}]}
                               when Module :: module(), What :: badfile | nofile | on_load_failure.

Tries to load any modules not already loaded in the list Modules in the same way as load_file/1.

Unlike ensure_loaded/1, modules are loaded even in embedded mode.

Returns ok if successful, or {error,[{Module,Reason}]} if loading of some modules fails. See Error Reasons for Code-Loading Functions for a description of other possible error reasons.

finish_loading(Prepared)

(since OTP 19.0)

-spec finish_loading(Prepared) -> ok | {error, [{Module, What}]}
                        when
                            Prepared :: prepared_code(),
                            Module :: module(),
                            What :: not_purged | sticky_directory | pending_on_load.

Tries to load code for all modules that have been previously prepared by prepare_loading/1.

The loading occurs atomically, meaning that either all modules are loaded at the same time, or none of the modules are loaded.

This function can fail with one of the following error reasons:

not_purged - The object code cannot be loaded because an old version of the code already exists.

sticky_directory - The object code resides in a sticky directory.

pending_on_load - A previously loaded module contains an -on_load function that never finished.

get_coverage(Level, Module)

(since OTP 27.0)

-spec get_coverage(Level, module()) -> Result
                      when
                          Level :: function | line | cover_id_line,
                          Result :: [{Entity, CoverageInfo}],
                          Entity :: {Function, Arity} | Line | CoverId,
                          CoverageInfo :: Covered | Counter,
                          Function :: atom(),
                          Arity :: arity(),
                          Line :: non_neg_integer(),
                          CoverId :: pos_integer(),
                          Covered :: boolean(),
                          Counter :: non_neg_integer().

Return either function or line coverage data for module Module.

If Level is function, returns function coverage for the given module according to its coverage mode:

function - For each function in module Module, a boolean indicating whether that function has been executed at least once is returned.

function_counters - For each function in module Module, an integer giving the number of times that line has been executed is returned.

line - For each function in module Module, a boolean indicating whether that function has been executed at least once is returned.

line_counters - For each function in module Module, a boolean indicating whether that function has been executed at least once is returned (note that in this mode, counters for the number of times each function has been executed cannot be retrieved).

If Level is line, returns line coverage for the given module according to its coverage mode:

line - For each executable line in the module, a boolean indicating whether that line has been executed at least once is returned.

line_counters - For each executable line in the module, an integer giving the number of times that line was executed is returned.

Level cover_id_line is used by the cover tool.

Failures:

badarg - If Level is not function or line.

badarg - If Module is not an atom.

badarg - If Module does not refer to a loaded module.

badarg - If Module was not loaded in another coverage mode than none.

badarg - If Level is line and Module has not been loaded with either line or line_counters enabled.

badarg - If the runtime system does not support coverage.

See also: Native Coverage Support

get_coverage_mode()

(since OTP 27.0)

-spec get_coverage_mode() -> Mode when Mode :: coverage_mode().

Returns the coverage mode as set by option +JPcover for erl or set_coverage_mode/1.

Failure:

badarg - If the runtime system does not support coverage.

See also: Native Coverage Support

get_coverage_mode(Module)

(since OTP 27.0)

-spec get_coverage_mode(Module) -> Mode when Module :: module(), Mode :: coverage_mode().

Get coverage mode for the given module.

Failures:

badarg - If Module is not an atom.

badarg - If Module does not refer to a loaded module.

badarg - If the runtime system does not support coverage.

See also: Native Coverage Support

get_debug_info(Module)

(since OTP 28.0)

-spec get_debug_info(Module) -> DebugInfo when Module :: module(), DebugInfo :: debug_info().

get_doc(Module)

(since OTP 23.0)

-spec get_doc(Mod) -> {ok, Res} | {error, Reason}
                 when
                     Mod :: module(),
                     Res ::
                         #docs_v1{anno :: term(),
                                  beam_language :: term(),
                                  format :: term(),
                                  module_doc :: term(),
                                  metadata :: term(),
                                  docs :: term()},
                     Reason :: non_existing | missing | file:posix().

Returns EEP 48 style documentation for Module if available.

If Module is not found in the code path, this function returns {error,non_existing}.

If no documentation can be found this function attempts to generate documentation from the debug information in the module. If no debug information is available, this function returns {error,missing}.

For more information about the documentation chunk see Documentation Storage and Format in Kernel's User's Guide.

get_mode()

(since OTP R16B)

-spec get_mode() -> embedded | interactive.

Returns an atom describing the mode of the code server: interactive or embedded.

This information is useful when an external entity (for example, an IDE) provides additional code for a running node. If the code server is in interactive mode, it only has to add the path to the code. If the code server is in embedded mode, the code must be loaded with load_binary/3.

get_object_code(Module)

-spec get_object_code(Module) -> {Module, Binary, Filename} | error
                         when Module :: module(), Binary :: binary(), Filename :: file:filename().

Returns the object code for module Module if found in the code path.

Returns {Module, Binary, Filename} if successful, otherwise error. Binary is a binary data object, which contains the object code for the module. This is useful if code is to be loaded on a remote node in a distributed system. For example, loading module Module on a node Node is done as follows:

...
{_Module, Binary, Filename} = code:get_object_code(Module),
erpc:call(Node, code, load_binary, [Module, Filename, Binary]),
...

get_path()

-spec get_path() -> Path when Path :: [Dir :: file:filename()].

Returns the code path.

is_loaded(Module)

-spec is_loaded(Module) -> {file, Loaded} | false when Module :: module(), Loaded :: loaded_filename().

Checks whether Module is loaded.

If it is, {file, Loaded} is returned, otherwise false.

Normally, Loaded is the absolute filename Filename from which the code is obtained. If the module is preloaded (see script(4)), Loaded =:= preloaded. If the module is Cover-compiled (see cover), Loaded =:= cover_compiled.

is_sticky(Module)

-spec is_sticky(Module) -> boolean() when Module :: module().

Returns true if Module is the name of a module that has been loaded from a sticky directory (in other words: an attempt to reload the module will fail), or false if Module is not a loaded module or is not sticky.

lib_dir()

-spec lib_dir() -> file:filename().

Returns the library directory, $OTPROOT/lib, where $OTPROOT is the root directory of Erlang/OTP.

Example:

1> code:lib_dir().
"/usr/local/otp/lib"

lib_dir(Name)

-spec lib_dir(Name) -> file:filename() | {error, bad_name} when Name :: atom().

Returns the path for the library directory, the top directory, for an application Name located under $OTPROOT/lib or in a directory referred to with environment variable ERL_LIBS.

If a regular directory called Name or Name-Vsn exists in the code path with an ebin subdirectory, the path to this directory is returned (not the ebin directory).

If the directory refers to a directory in an archive, the archive name is stripped away before the path is returned. For example, if directory /usr/local/otp/lib/mnesia-4.2.2.ez/mnesia-4.2.2/ebin is in the path, /usr/local/otp/lib/mnesia-4.2.2/ebin is returned. This means that the library directory for an application is the same, regardless if the application resides in an archive or not.

Warning

Archives are experimental. In a future release, they can be removed or their behavior can change.

Example:

> code:lib_dir(mnesia).
"/usr/local/otp/lib/mnesia-4.23"

Returns {error, bad_name} if Name is not the name of an application under $OTPROOT/lib or on a directory referred to through environment variable ERL_LIBS. Fails with an exception if Name has the wrong type.

Warning

For backward compatibility, Name is also allowed to be a string. That will probably change in a future release.

lib_dir(Name, SubDir)

This function is deprecated. code:lib_dir/2 is deprecated; this functionality will be removed in a future release.

-spec lib_dir(Name, SubDir) -> file:filename() | {error, bad_name} when Name :: atom(), SubDir :: atom().

Returns the path to a subdirectory directly under the top directory of an application.

Change

This function is part of the archive support, which is an experimental feature that will be changed or removed in a future release.

Normally the subdirectories reside under the top directory for the application, but when applications at least partly reside in an archive, the situation is different. Some of the subdirectories can reside as regular directories while others reside in an archive file. It is not checked whether this directory exists.

Instead of using this function, use code:lib_dir/1 and filename:join/2.

Example:

1> filename:join(code:lib_dir(megaco), "priv").
"/usr/local/otp/lib/megaco-3.9.1.1/priv"

Fails with an exception if Name or SubDir has the wrong type.

load_abs(Filename)

-spec load_abs(Filename) -> load_ret() when Filename :: file:filename().

Equivalent to load_file(Module), except that Filename is an absolute or relative filename.

The code path is not searched. It returns a value in the same way as load_file/1. Notice that Filename must not contain the extension (for example, .beam) because load_abs/1 adds the correct extension.

load_binary(Module, Filename, Binary)

-spec load_binary(Module, Filename, Binary) -> {module, Module} | {error, What}
                     when
                         Module :: module(),
                         Filename :: loaded_filename(),
                         Binary :: binary(),
                         What :: badarg | load_error_rsn().

Loads object code from a binary.

This function can be used to load object code on remote Erlang nodes. Argument Binary must contain object code for Module. Filename is only used by the code server to keep a record of from which file the object code for Module originates. Thus, Filename is not opened and read by the code server.

Returns {module, Module} if successful, or {error, Reason} if loading fails. See Error Reasons for Code-Loading Functions for a description of the possible error reasons.

load_file(Module)

-spec load_file(Module) -> load_ret() when Module :: module().

Tries to load the Erlang module Module using the code path.

It looks for the object code file with an extension corresponding to the Erlang machine used, for example, Module.beam. The loading fails if the module name found in the object code differs from the name Module. Use load_binary/3 to load object code with a module name that is different from the file name.

Returns {module, Module} if successful, or {error, Reason} if loading fails. See Error Reasons for Code-Loading Functions for a description of the possible error reasons.

modified_modules()

(since OTP 20.0)

-spec modified_modules() -> [module()].

Returns the list of all currently loaded modules for which module_status/1 returns modified.

See also all_loaded/0.

module_status()

(since OTP 23.0)

-spec module_status() -> [{module(), module_status()}].

See module_status/1 and all_loaded/0 for details.

module_status(Module)

(since OTP 20.0)

-spec module_status(Module :: module() | [module()]) -> module_status() | [{module(), module_status()}].

Returns the status of Module in relation to object file on disk.

The status of a module can be one of:

not_loaded - If Module is not currently loaded.

loaded - If Module is loaded, and the object file exists and contains the same code.

removed - If Module is loaded, but no corresponding object file can be found in the code path.

modified - If Module is loaded, but the object file contains code with a different MD5 checksum.

Preloaded modules are always reported as loaded, without inspecting the contents on disk. Cover-compiled modules will always be reported as modified if an object file exists, or as removed otherwise. Modules whose load path is an empty string (which is the convention for auto-generated code) will only be reported as loaded or not_loaded.

See also modified_modules/0.

objfile_extension()

-spec objfile_extension() -> nonempty_string().

Returns the object code file extension corresponding to the Erlang machine used.

For the official Erlang/OTP release, the return value is always .beam.

prepare_loading(Modules)

(since OTP 19.0)

-spec prepare_loading(Modules) -> {ok, Prepared} | {error, [{Module, What}]}
                         when
                             Modules :: [Module | {Module, Filename, Binary}],
                             Module :: module(),
                             Filename :: file:filename(),
                             Binary :: binary(),
                             Prepared :: prepared_code(),
                             What :: badfile | nofile | on_load_not_allowed | duplicated.

Prepares to load the modules in the list Modules.

Finish the loading by calling finish_loading(Prepared).

This function can fail with one of the following error reasons:

badfile - The object code has an incorrect format or the module name in the object code is not the expected module name.

nofile - No file with object code exists.

on_load_not_allowed - A module contains an -on_load function.

duplicated - A module is included more than once in Modules.

priv_dir(Name)

-spec priv_dir(Name) -> file:filename() | {error, bad_name} when Name :: atom().

Returns the path to the priv directory in an application.

Warning

For backward compatibility, Name is also allowed to be a string. That will probably change in a future release.

purge(Module)

-spec purge(Module) -> boolean() when Module :: module().

Purges the code for Module, that is, removes code marked as old.

If some processes still linger in the old code, these processes are killed before the code is removed.

Change

As of Erlang/OTP 20.0, a process is only considered to be lingering in the code if it has direct references to the code. For more information see documentation of erlang:check_process_code/3, which is used in order to determine whether a process is lingering.

Returns true if successful and any process is needed to be killed, otherwise false.

replace_path(Name, Dir)

-spec replace_path(Name, Dir) -> replace_path_ret() when Name :: atom(), Dir :: file:filename().

Equivalent to replace_path(Name, Dir, nocache).

replace_path(Name, Dir, Cache)

(since OTP 26.0)

-spec replace_path(Name, Dir, cache()) -> replace_path_ret() when Name :: atom(), Dir :: file:filename().

Replaces an old occurrence of a directory named .../Name[-Vsn][/ebin] in the code path, with Dir.

If Name does not exist, it adds the new directory Dir last in the code path. The new directory must also be named .../Name[-Vsn][/ebin]. This function is to be used if a new version of the directory (library) is added to a running system.

Argument Cache controls whether the content of the directory should be cached on first traversal. If Cache is cache the directory contents will be cached; if Cache is nocache it will not be cached.

Returns:

true - If successful

{error, bad_name} - If Name is not found

{error, bad_directory} - If Dir does not exist

{error, {badarg, [Name, Dir]}} - If Name or Dir is invalid

reset_coverage(Module)

(since OTP 27.0)

-spec reset_coverage(Module) -> ok when Module :: module().

Resets coverage information for module Module.

If the coverage mode is either function or line, all booleans for Module keeping track of executed functions or lines are set to false.

If the coverage mode is either function_counters or line_counters, all counters for Module are reset to zero.

Failures:

badarg - If Module is not an atom.

badarg - If Module does not refer to a loaded module.

badarg - If Module was not loaded with coverage enabled.

badarg - If the runtime system does not support coverage.

See also: Native Coverage Support

root_dir()

-spec root_dir() -> file:filename().

Returns the root directory of Erlang/OTP, which is the directory where it is installed.

Example:

1> code:root_dir().
"/usr/local/otp"

set_coverage_mode(Mode)

(since OTP 27.0)

-spec set_coverage_mode(Mode) -> OldMode when Mode :: coverage_mode(), OldMode :: coverage_mode().

Sets the coverage mode for modules that are subsequently loaded, similar to option +JPcover for erl.

The coverage mode will have the following effect on code that is loaded following this call:

function - All modules that are loaded will be instrumented to keep track of which functions are executed. Information about which functions that have been executed can be retrieved by calling get_coverage(function, Module).

function_counters - All modules that are loaded will be instrumented to count how many times each function is executed. Information about how many times each function has been executed can be retrieved by calling get_coverage(function, Module).

line - When modules that have been compiled with the line_coverage option are loaded, they will be instrumented to keep track of which lines have been executed. Information about which lines have been executed can be retrieved by calling get_coverage(line, Module), and information about which functions that have been executed can be retrieved by calling get_coverage(function, Module).

line_counters - When modules that have been compiled with the line_coverage option are loaded, they will be instrumented to count the number of times each line is executed. Information about how many times each line has been executed can be retrieved by calling get_coverage(line, Module), and information about which functions that have been executed can be retrieved by calling get_coverage(function, Module) (note that in this mode, counters for the number of times each function has been executed cannot be retrieved).

none - Modules will be loaded without coverage instrumentation.

Returns the previous coverage mode.

Failures:

badarg - If Mode is not a valid coverage mode.

badarg - If the runtime system does not support coverage.

See also: Native Coverage Support

set_path(Path)

-spec set_path(Path) -> set_path_ret() when Path :: [Dir :: file:filename()].

Equivalent to set_path(PathList, nocache).

set_path(PathList, Cache)

(since OTP 26.0)

-spec set_path(Path, cache()) -> set_path_ret() when Path :: [Dir :: file:filename()].

Sets the code path to the list of directories Path.

Argument Cache controls whether the content of the directory should be cached on first traversal. If Cache is cache the directory contents will be cached; if Cache is nocache it will not be cached.

Returns:

true - If successful

{error, bad_directory} - If any Dir is not a directory name

soft_purge(Module)

-spec soft_purge(Module) -> boolean() when Module :: module().

Purges the code for Module, that is, removes code marked as old, but only if no processes linger in it.

Change

As of Erlang/OTP 20.0, a process is only considered to be lingering in the code if it has direct references to the code. For more information see documentation of erlang:check_process_code/3, which is used in order to determine whether a process is lingering.

Returns false if the module cannot be purged because of processes lingering in old code, otherwise true.

stick_dir(Dir)

-spec stick_dir(Dir) -> ok | error when Dir :: file:filename().

Marks Dir as sticky.

Returns ok if successful, otherwise error.

unstick_dir(Dir)

-spec unstick_dir(Dir) -> ok | error when Dir :: file:filename().

Unsticks a directory that is marked as sticky.

Returns ok if successful, otherwise error.

where_is_file(Filename)

-spec where_is_file(Filename) -> non_existing | Absname
                       when Filename :: file:filename(), Absname :: file:filename().

Searches the code path for Filename, which is a file of arbitrary type.

If found, the full name is returned. non_existing is returned if the file cannot be found. The function can be useful, for example, to locate application resource files.

which(Module)

-spec which(Module) -> Which when Module :: module(), Which :: loaded_filename() | non_existing.

If the module is not loaded, this function searches the code path for the first file containing object code for Module and returns the absolute filename.

If the module is loaded, it returns the name of the file containing the loaded object code.

If the module is preloaded, preloaded is returned.

If the module is Cover-compiled, cover_compiled is returned.

If the module cannot be found, non_existing is returned.

erl_ddll

Dynamic driver loader and linker.

This module provides an interface for loading and unloading Erlang linked-in drivers in runtime.

Note

This is a large reference document. For casual use of this module, and for most real world applications, the descriptions of functions load/2 and unload/1 are enough to getting started.

The driver is to be provided as a dynamically linked library in an object code format specific for the platform in use, that is, .so files on most Unix systems and .ddl files on Windows. An Erlang linked-in driver must provide specific interfaces to the emulator, so this module is not designed for loading arbitrary dynamic libraries. For more information about Erlang drivers, see erl_driver .

When describing a set of functions (that is, a module, a part of a module, or an application), executing in a process and wanting to use a ddll-driver, we use the term user. A process can have many users (different modules needing the same driver) and many processes running the same code, making up many users of a driver.

In the basic scenario, each user loads the driver before starting to use it and unloads the driver when done. The reference counting keeps track of processes and the number of loads by each process. This way the driver is only unloaded when no one wants it (it has no user). The driver also keeps track of ports that are opened to it. This enables delay of unloading until all ports are closed, or killing of all ports that use the driver when it is unloaded.

The interface supports two basic scenarios of loading and unloading. Each scenario can also have the option of either killing ports when the driver is unloading, or waiting for the ports to close themselves. The scenarios are as follows:

Load and Unload on a "When Needed Basis" - This (most common) scenario simply supports that each user of the driver loads it when needed and unloads it when no longer needed. The driver is always reference counted and as long as a process keeping the driver loaded is still alive, the driver is present in the system.

Each user of the driver use literally the same pathname for the driver when demanding load, but the users are not concerned with if the driver is already loaded from the file system or if the object code must be loaded from file system.

The following two pairs of functions support this scenario:

load/2 and unload/1 - When using the load/unload interfaces, the driver is not unloaded until the last port using the driver is closed. Function unload/1 can return immediately, as the users have no interest in when the unloading occurs. The driver is unloaded when no one needs it any longer.

If a process having the driver loaded dies, it has the same effect as if unloading is done.

When loading, function load/2 returns ok when any instance of the driver is present. Thus, if a driver is waiting to get unloaded (because of open ports), it simply changes state to no longer need unloading.

load_driver/2 and unload_driver/1 - These interfaces are intended to be used when it is considered an error that ports are open to a driver that no user has loaded. The ports that are still open when the last user calls unload_driver/1 or when the last process having the driver loaded dies, are killed with reason driver_unloaded.

The function names load_driver and unload_driver are kept for backward compatibility.

Loading and Reloading for Code Replacement - This scenario can occur if the driver code needs replacement during operation of the Erlang emulator. Implementing driver code replacement is a little more tedious than Beam code replacement, as one driver cannot be loaded as both "old" and "new" code. All users of a driver must have it closed (no open ports) before the old code can be unloaded and the new code can be loaded.

The unloading/loading is done as one atomic operation, blocking all processes in the system from using the driver in question while in progress.

The preferred way to do driver code replacement is to let one single process keep track of the driver. When the process starts, the driver is loaded. When replacement is required, the driver is reloaded. Unload is probably never done, or done when the process exits. If more than one user has a driver loaded when code replacement is demanded, the replacement cannot occur until the last "other" user has unloaded the driver.

Demanding reload when a reload is already in progress is always an error. Using the high-level functions, it is also an error to demand reloading when more than one user has the driver loaded.

To simplify driver replacement, avoid designing your system so that more than one user has the driver loaded.

The two functions for reloading drivers are to be used together with corresponding load functions to support the two different behaviors concerning open ports:

load/2 and reload/2 - This pair of functions is used when reloading is to be done after the last open port to the driver is closed.

As reload/2 waits for the reloading to occur, a misbehaving process keeping open ports to the driver (or keeping the driver loaded) can cause infinite waiting for reload. Time-outs must be provided outside of the process demanding the reload or by using the low-level interface try_load/3 in combination with driver monitors.

load_driver/2 and reload_driver/2 - This pair of functions are used when open ports to the driver are to be killed with reason driver_unloaded to allow for new driver code to get loaded.

However, if another process has the driver loaded, calling reload_driver returns error code pending_process. As stated earlier, the recommended design is to not allow other users than the "driver reloader" to demand loading of the driver in question.

See Also

erl_driver(4), driver_entry(4)

Summary

Types

driver()

path()

Functions

demonitor(MonitorRef)

Removes a driver monitor in much the same way as erlang:demonitor/1 in ERTS does with process monitors.

format_error(ErrorDesc)

Takes an ErrorDesc returned by load, unload, or reload functions and returns a string that describes the error or warning.

info()

Returns a list of tuples {DriverName, InfoList}, where InfoList is the result of calling info/1 for that DriverName. Only dynamically linked-in drivers are included in the list.

info(Name)

Returns a list of tuples {Tag, Value}, where Tag is the information item and Value is the result of calling info/2 with this driver name and this tag. The result is a tuple list containing all information available about a driver.

info(Name, Tag)

Returns specific information about one aspect of a driver. Parameter Tag specifies which aspect to get information about. The return Value differs between different tags

load(Path, Name)

Loads and links the dynamic driver Name. Path is a file path to the directory containing the driver. Name must be a shareable object/dynamic library. Two drivers with different Path parameters cannot be loaded under the same name. Name is a string or atom containing at least one character.

load_driver(Path, Name)

Works essentially as load/2, but loads the driver with other options. All ports using the driver are killed with reason driver_unloaded when the driver is to be unloaded.

loaded_drivers()

Returns a list of all the available drivers, both (statically) linked-in and dynamically loaded ones.

monitor(Tag, Item)

Creates a driver monitor and works in many ways as erlang:monitor/2 in ERTS, does for processes. When a driver changes state, the monitor results in a monitor message that is sent to the calling process. MonitorRef returned by this function is included in the message sent.

reload(Path, Name)

Reloads the driver named Name from a possibly different Path than previously used. This function is used in the code change scenario described in the introduction.

reload_driver(Path, Name)

Works exactly as reload/2, but for drivers loaded with the load_driver/2 interface.

try_load(Path, Name, OptionList)

Provides more control than the load/2/reload/2 and load_driver/2/reload_driver/2 interfaces. It never waits for completion of other operations related to the driver, but immediately returns the status of the driver as one of the following

try_unload(Name, OptionList)

This is the low-level function to unload (or decrement reference counts of) a driver. It can be used to force port killing, in much the same way as the driver option kill_ports implicitly does. Also, it can trigger a monitor either because other users still have the driver loaded or because open ports use the driver.

unload(Name)

Unloads, or at least dereferences the driver named Name. If the caller is the last user of the driver, and no more open ports use the driver, the driver gets unloaded. Otherwise, unloading is delayed until all ports are closed and no users remain.

unload_driver(Name)

Unloads, or at least dereferences the driver named Name. If the caller is the last user of the driver, all remaining open ports using the driver are killed with reason driver_unloaded and the driver eventually gets unloaded.

Types

driver()

(not exported)

-type driver() :: iolist() | atom().

path()

(not exported)

-type path() :: string() | atom().

Functions

demonitor(MonitorRef)

-spec demonitor(MonitorRef) -> ok when MonitorRef :: reference().

Removes a driver monitor in much the same way as erlang:demonitor/1 in ERTS does with process monitors.

For details about how to create driver monitors, see monitor/2, try_load/3, and try_unload/2.

The function throws a badarg exception if the parameter is not a reference/0.

format_error(ErrorDesc)

-spec format_error(ErrorDesc) -> string() when ErrorDesc :: term().

Takes an ErrorDesc returned by load, unload, or reload functions and returns a string that describes the error or warning.

Note

Because of peculiarities in the dynamic loading interfaces on different platforms, the returned string is only guaranteed to describe the correct error if format_error/1 is called in the same instance of the Erlang virtual machine as the error appeared in (meaning the same operating system process).

info()

-spec info() -> AllInfoList
              when
                  AllInfoList :: [DriverInfo],
                  DriverInfo :: {DriverName, InfoList},
                  DriverName :: string(),
                  InfoList :: [InfoItem],
                  InfoItem :: {Tag :: atom(), Value :: term()}.

Returns a list of tuples {DriverName, InfoList}, where InfoList is the result of calling info/1 for that DriverName. Only dynamically linked-in drivers are included in the list.

info(Name)

-spec info(Name) -> InfoList
              when
                  Name :: driver(),
                  InfoList :: [InfoItem, ...],
                  InfoItem :: {Tag :: atom(), Value :: term()}.

Returns a list of tuples {Tag, Value}, where Tag is the information item and Value is the result of calling info/2 with this driver name and this tag. The result is a tuple list containing all information available about a driver.

The following tags appears in the list:

processes

driver_options

port_count

linked_in_driver

permanent

awaiting_load

awaiting_unload

For a detailed description of each value, see info/2.

The function throws a badarg exception if the driver is not present in the system.

info(Name, Tag)

-spec info(Name, Tag) -> Value
              when
                  Name :: driver(),
                  Tag ::
                      processes | driver_options | port_count | linked_in_driver | permanent |
                      awaiting_load | awaiting_unload,
                  Value :: term().

Returns specific information about one aspect of a driver. Parameter Tag specifies which aspect to get information about. The return Value differs between different tags:

processes - Returns all processes containing users of the specific drivers as a list of tuples {pid(),integer() >= 0}, where integer/0 denotes the number of users in process pid/0.

driver_options - Returns a list of the driver options provided when loading, and any options set by the driver during initialization. The only valid option is kill_ports.

port_count - Returns the number of ports (an integer() >= 0) using the driver.

linked_in_driver - Returns a boolean/0, which is true if the driver is a statically linked-in one, otherwise false.

permanent - Returns a boolean/0, which is true if the driver has made itself permanent (and is not a statically linked-in driver), otherwise false.

awaiting_load - Returns a list of all processes having monitors for loading active. Each process is returned as {pid(),integer() >= 0}, where integer/0 is the number of monitors held by process pid/0.

awaiting_unload - Returns a list of all processes having monitors for unloading active. Each process is returned as {pid(),integer() >= 0}, where integer/0 is the number of monitors held by process pid/0.

If option linked_in_driver or permanent returns true, all other options return linked_in_driver or permanent, respectively.

The function throws a badarg exception if the driver is not present in the system or if the tag is not supported.

load(Path, Name)

-spec load(Path, Name) -> ok | {error, ErrorDesc}
              when Path :: path(), Name :: driver(), ErrorDesc :: term().

Loads and links the dynamic driver Name. Path is a file path to the directory containing the driver. Name must be a shareable object/dynamic library. Two drivers with different Path parameters cannot be loaded under the same name. Name is a string or atom containing at least one character.

The Name specified is to correspond to the filename of the dynamically loadable object file residing in the directory specified as Path, but without the extension (that is, .so). The driver name provided in the driver initialization routine must correspond with the filename, in much the same way as Erlang module names correspond to the names of the .beam files.

If the driver was previously unloaded, but is still present because of open ports to it, a call to load/2 stops the unloading and keeps the driver (as long as Path is the same), and ok is returned. If you really want the object code to be reloaded, use reload/2 or the low-level interface try_load/3 instead. See also the description of different scenarios for loading/unloading in the introduction.

If more than one process tries to load an already loaded driver with the same Path, or if the same process tries to load it many times, the function returns ok. The emulator keeps track of the load/2 calls, so that a corresponding number of unload/2 calls must be done from the same process before the driver gets unloaded. It is therefore safe for an application to load a driver that is shared between processes or applications when needed. It can safely be unloaded without causing trouble for other parts of the system.

It is not allowed to load multiple drivers with the same name but with different Path parameters.

Note

Path is interpreted literally, so that all loaders of the same driver must specify the same literal Path string, although different paths can point out the same directory in the file system (because of use of relative paths and links).

On success, the function returns ok. On failure, the return value is {error,ErrorDesc}, where ErrorDesc is an opaque term to be translated into human readable form by function format_error/1.

For more control over the error handling, use the try_load/3 interface instead.

The function throws a badarg exception if the parameters are not specified as described here.

load_driver(Path, Name)

-spec load_driver(Path, Name) -> ok | {error, ErrorDesc}
                     when Path :: path(), Name :: driver(), ErrorDesc :: term().

Works essentially as load/2, but loads the driver with other options. All ports using the driver are killed with reason driver_unloaded when the driver is to be unloaded.

The number of loads and unloads by different users influences the loading and unloading of a driver file. The port killing therefore only occurs when the last user unloads the driver, or when the last process having loaded the driver exits.

This interface (or at least the name of the functions) is kept for backward compatibility. Using try_load/3 with {driver_options,[kill_ports]} in the option list gives the same effect regarding the port killing.

The function throws a badarg exception if the parameters are not specified as described here.

loaded_drivers()

-spec loaded_drivers() -> {ok, Drivers} when Drivers :: [Driver], Driver :: string().

Returns a list of all the available drivers, both (statically) linked-in and dynamically loaded ones.

The driver names are returned as a list of strings rather than a list of atoms for historical reasons.

For more information about drivers, see info.

monitor(Tag, Item)

-spec monitor(Tag, Item) -> MonitorRef
                 when
                     Tag :: driver,
                     Item :: {Name, When},
                     Name :: driver(),
                     When :: loaded | unloaded | unloaded_only,
                     MonitorRef :: reference().

Creates a driver monitor and works in many ways as erlang:monitor/2 in ERTS, does for processes. When a driver changes state, the monitor results in a monitor message that is sent to the calling process. MonitorRef returned by this function is included in the message sent.

As with process monitors, each driver monitor set only generates one single message. The monitor is "destroyed" after the message is sent, so it is then not needed to call demonitor/1.

MonitorRef can also be used in subsequent calls to demonitor/1 to remove a monitor.

The function accepts the following parameters:

Tag - The monitor tag is always driver, as this function can only be used to create driver monitors. In the future, driver monitors will be integrated with process monitors, why this parameter has to be specified for consistence.

Item - Parameter Item specifies which driver to monitor (the driver name) and which state change to monitor. The parameter is a tuple of arity two whose first element is the driver name and second element is one of the following:

loaded - Notifies when the driver is reloaded (or loaded if loading is underway). It only makes sense to monitor drivers that are in the process of being loaded or reloaded. A future driver name for loading cannot be monitored. That only results in a DOWN message sent immediately. Monitoring for loading is therefore most useful when triggered by function try_load/3, where the monitor is created because the driver is in such a pending state.

Setting a driver monitor for loading eventually leads to one of the following messages being sent:

{'UP', reference(), driver, Name, loaded} - This message is sent either immediately if the driver is already loaded and no reloading is pending, or when reloading is executed if reloading is pending.

The user is expected to know if reloading is demanded before creating a monitor for loading.

{'UP', reference(), driver, Name, permanent} - This message is sent if reloading was expected, but the (old) driver made itself permanent before reloading. It is also sent if the driver was permanent or statically linked-in when trying to create the monitor.

{'DOWN', reference(), driver, Name, load_cancelled} - This message arrives if reloading was underway, but the requesting user cancelled it by dying or calling try_unload/2 (or unload/1/unload_driver/1) again before it was reloaded.

{'DOWN', reference(), driver, Name, {load_failure, Failure}} - This message arrives if reloading was underway but the loading for some reason failed. The Failure term is one of the errors that can be returned from try_load/3. The error term can be passed to format_error/1 for translation into human readable form. Notice that the translation must be done in the same running Erlang virtual machine as the error was detected in.

unloaded - Monitors when a driver gets unloaded. If one monitors a driver that is not present in the system, one immediately gets notified that the driver got unloaded. There is no guarantee that the driver was ever loaded.

A driver monitor for unload eventually results in one of the following messages being sent:

{'DOWN', reference(), driver, Name, unloaded} - The monitored driver instance is now unloaded. As the unload can be a result of a reload/2 request, the driver can once again have been loaded when this message arrives.

{'UP', reference(), driver, Name, unload_cancelled} - This message is sent if unloading was expected, but while the driver was waiting for all ports to get closed, a new user of the driver appeared, and the unloading was cancelled.

This message appears if {ok, pending_driver} was returned from try_unload/2 for the last user of the driver, and then {ok, already_loaded} is returned from a call to try_load/3.

If one really wants to monitor when the driver gets unloaded, this message distorts the picture, because no unloading was done. Option unloaded_only creates a monitor similar to an unloaded monitor, but never results in this message.

{'UP', reference(), driver, Name, permanent} - This message is sent if unloading was expected, but the driver made itself permanent before unloading. It is also sent if trying to monitor a permanent or statically linked-in driver.

unloaded_only - A monitor created as unloaded_only behaves exactly as one created as unloaded except that the {'UP', reference(), driver, Name, unload_cancelled} message is never sent, but the monitor instead persists until the driver really gets unloaded.

The function throws a badarg exception if the parameters are not specified as described here.

reload(Path, Name)

-spec reload(Path, Name) -> ok | {error, ErrorDesc}
                when
                    Path :: path(),
                    Name :: driver(),
                    ErrorDesc :: pending_process | OpaqueError,
                    OpaqueError :: term().

Reloads the driver named Name from a possibly different Path than previously used. This function is used in the code change scenario described in the introduction.

If there are other users of this driver, the function returns {error, pending_process}, but if there are no other users, the function call hangs until all open ports are closed.

Note

Avoid mixing multiple users with driver reload requests.

To avoid hanging on open ports, use function try_load/3 instead.

The Name and Path parameters have exactly the same meaning as when calling the plain function load/2.

On success, the function returns ok. On failure, the function returns an opaque error, except the pending_process error described earlier. The opaque errors are to be translated into human readable form by function format_error/1.

For more control over the error handling, use the try_load/3 interface instead.

The function throws a badarg exception if the parameters are not specified as described here.

reload_driver(Path, Name)

-spec reload_driver(Path, Name) -> ok | {error, ErrorDesc}
                       when
                           Path :: path(),
                           Name :: driver(),
                           ErrorDesc :: pending_process | OpaqueError,
                           OpaqueError :: term().

Works exactly as reload/2, but for drivers loaded with the load_driver/2 interface.

As this interface implies that ports are killed when the last user disappears, the function does not hang waiting for ports to get closed.

For more details, see scenarios in this module description and the function description for reload/2.

The function throws a badarg exception if the parameters are not specified as described here.

try_load(Path, Name, OptionList)

-spec try_load(Path, Name, OptionList) -> {ok, Status} | {ok, PendingStatus, Ref} | {error, ErrorDesc}
                  when
                      Path :: path(),
                      Name :: driver(),
                      OptionList :: [Option],
                      Option ::
                          {driver_options, DriverOptionList} |
                          {monitor, MonitorOption} |
                          {reload, ReloadOption},
                      DriverOptionList :: [DriverOption],
                      DriverOption :: kill_ports,
                      MonitorOption :: pending_driver | pending,
                      ReloadOption :: pending_driver | pending,
                      Status :: loaded | already_loaded | PendingStatus,
                      PendingStatus :: pending_driver | pending_process,
                      Ref :: reference(),
                      ErrorDesc :: ErrorAtom | OpaqueError,
                      ErrorAtom ::
                          linked_in_driver | inconsistent | permanent | not_loaded_by_this_process |
                          not_loaded | pending_reload | pending_process,
                      OpaqueError :: term().

Provides more control than the load/2/reload/2 and load_driver/2/reload_driver/2 interfaces. It never waits for completion of other operations related to the driver, but immediately returns the status of the driver as one of the following:

{ok, loaded} - The driver was loaded and is immediately usable.

{ok, already_loaded} - The driver was already loaded by another process or is in use by a living port, or both. The load by you is registered and a corresponding try_unload is expected sometime in the future.

{ok, pending_driver}or {ok, pending_driver, reference()} - The load request is registered, but the loading is delayed because an earlier instance of the driver is still waiting to get unloaded (open ports use it). Still, unload is expected when you are done with the driver. This return value mostly occurs when options {reload,pending_driver} or {reload,pending} are used, but can occur when another user is unloading a driver in parallel and driver option kill_ports is set. In other words, this return value always needs to be handled.

{ok, pending_process}or {ok, pending_process, reference()} - The load request is registered, but the loading is delayed because an earlier instance of the driver is still waiting to get unloaded by another user (not only by a port, in which case {ok,pending_driver} would have been returned). Still, unload is expected when you are done with the driver. This return value only occurs when option {reload,pending} is used.

When the function returns {ok, pending_driver} or {ok, pending_process}, one can get information about when the driver is actually loaded by using option {monitor, MonitorOption}.

When monitoring is requested, and a corresponding {ok, pending_driver} or {ok, pending_process} would be returned, the function instead returns a tuple {ok, PendingStatus, reference()} and the process then gets a monitor message later, when the driver gets loaded. The monitor message to expect is described in the function description of monitor/2.

Note

In case of loading, monitoring can not only get triggered by using option {reload, ReloadOption}, but also in special cases where the load error is transient. Thus, {monitor, pending_driver} is to be used under basically all real world circumstances.

The function accepts the following parameters:

Path - The file system path to the directory where the driver object file is located. The filename of the object file (minus extension) must correspond to the driver name (used in parameter Name) and the driver must identify itself with the same name. Path can be provided as an iolist(), meaning it can be a list of other iolist/0s, characters (8-bit integers), or binaries, all to be flattened into a sequence of characters.

The (possibly flattened) Path parameter must be consistent throughout the system. A driver is to, by all users, be loaded using the same literal Path. The exception is when reloading is requested, in which case Path can be specified differently. Notice that all users trying to load the driver later need to use the new Path if Path is changed using a reload option. This is yet another reason to have only one loader of a driver one wants to upgrade in a running system.

Name - This parameter is the name of the driver to be used in subsequent calls to function erlang:open_port in ERTS. The name can be specified as an iolist/0 or an atom/0. The name specified when loading is used to find the object file (with the help of Path and the system-implied extension suffix, that is, .so). The name by which the driver identifies itself must also be consistent with this Name parameter, much as the module name of a Beam file much corresponds to its filename.

OptionList - Some options can be specified to control the loading operation. The options are specified as a list of two-tuples. The tuples have the following values and meanings:

{driver_options, DriverOptionList} - This is to provide options that changes its general behavior and "sticks" to the driver throughout its lifespan.

The driver options for a specified driver name need always to be consistent, even when the driver is reloaded, meaning that they are as much a part of the driver as the name.

The only allowed driver option is kill_ports, which means that all ports opened to the driver are killed with exit reason driver_unloaded when no process any longer has the driver loaded. This situation arises either when the last user calls try_unload/2, or when the last process having loaded the driver exits.

{monitor, MonitorOption} - A MonitorOption tells try_load/3 to trigger a driver monitor under certain conditions. When the monitor is triggered, the function returns a three-tuple {ok, PendingStatus, reference()}, where reference/0 is the monitor reference for the driver monitor.

Only one MonitorOption can be specified. It is one of the following:

The atom pending, which means that a monitor is to be created whenever a load operation is delayed,

The atom pending_driver, in which a monitor is created whenever the operation is delayed because of open ports to an otherwise unused driver.

Option pending_driver is of little use, but is present for completeness, as it is well defined which reload options that can give rise to which delays. However, it can be a good idea to use the same MonitorOption as the ReloadOption, if present.

If reloading is not requested, it can still be useful to specify option monitor, as forced unloads (driver option kill_ports or option kill_ports to try_unload/2) trigger a transient state where driver loading cannot be performed until all closing ports are closed. Thus, as try_unload can, in almost all situations, return {ok, pending_driver}, always specify at least {monitor, pending_driver} in production code (see the monitor discussion earlier).

{reload, ReloadOption} - This option is used to reload a driver from disk, most often in a code upgrade scenario. Having a reload option also implies that parameter Path does not need to be consistent with earlier loads of the driver.

To reload a driver, the process must have loaded the driver before, that is, there must be an active user of the driver in the process.

The reload option can be either of the following:

pending - With the atom pending, reloading is requested for any driver and is effectuated when all ports opened to the driver are closed. The driver replacement in this case takes place regardless if there are still pending users having the driver loaded.

The option also triggers port-killing (if driver option kill_ports is used) although there are pending users, making it usable for forced driver replacement, but laying much responsibility on the driver users. The pending option is seldom used as one does not want other users to have loaded the driver when code change is underway.

pending_driver - This option is more useful. Here, reloading is queued if the driver is not loaded by any other users, but the driver has opened ports, in which case {ok, pending_driver} is returned (a monitor option is recommended).

If the driver is unloaded (not present in the system), error code not_loaded is returned. Option reload is intended for when the user has already loaded the driver in advance.

The function can return numerous errors, some can only be returned given a certain combination of options.

Some errors are opaque and can only be interpreted by passing them to function format_error/1, but some can be interpreted directly:

{error,linked_in_driver} - The driver with the specified name is an Erlang statically linked-in driver, which cannot be manipulated with this API.

{error,inconsistent} - The driver is already loaded with other DriverOptionList or a different literal Path argument.

This can occur even if a reload option is specified, if DriverOptionList differs from the current.

{error, permanent} - The driver has requested itself to be permanent, making it behave like an Erlang linked-in driver and can no longer be manipulated with this API.

{error, pending_process} - The driver is loaded by other users when option {reload, pending_driver} was specified.

{error, pending_reload} - Driver reload is already requested by another user when option {reload, ReloadOption} was specified.

{error, not_loaded_by_this_process} - Appears when option reload is specified. The driver Name is present in the system, but there is no user of it in this process.

{error, not_loaded} - Appears when option reload is specified. The driver Name is not in the system. Only drivers loaded by this process can be reloaded.

All other error codes are to be translated by function format_error/1. Notice that calls to format_error are to be performed from the same running instance of the Erlang virtual machine as the error is detected in, because of system-dependent behavior concerning error values.

If the arguments or options are malformed, the function throws a badarg exception.

try_unload(Name, OptionList)

-spec try_unload(Name, OptionList) -> {ok, Status} | {ok, PendingStatus, Ref} | {error, ErrorAtom}
                    when
                        Name :: driver(),
                        OptionList :: [Option],
                        Option :: {monitor, MonitorOption} | kill_ports,
                        MonitorOption :: pending_driver | pending,
                        Status :: unloaded | PendingStatus,
                        PendingStatus :: pending_driver | pending_process,
                        Ref :: reference(),
                        ErrorAtom ::
                            linked_in_driver | not_loaded | not_loaded_by_this_process | permanent.

This is the low-level function to unload (or decrement reference counts of) a driver. It can be used to force port killing, in much the same way as the driver option kill_ports implicitly does. Also, it can trigger a monitor either because other users still have the driver loaded or because open ports use the driver.

Unloading can be described as the process of telling the emulator that this particular part of the code in this particular process (that is, this user) no longer needs the driver. That can, if there are no other users, trigger unloading of the driver, in which case the driver name disappears from the system and (if possible) the memory occupied by the driver executable code is reclaimed.

If the driver has option kill_ports set, or if kill_ports is specified as an option to this function, all pending ports using this driver are killed when unloading is done by the last user. If no port-killing is involved and there are open ports, the unloading is delayed until no more open ports use the driver. If, in this case, another user (or even this user) loads the driver again before the driver is unloaded, the unloading never takes place.

To allow the user to request unloading to wait for actual unloading, monitor triggers can be specified in much the same way as when loading. However, as users of this function seldom are interested in more than decrementing the reference counts, monitoring is seldom needed.

Note

If option kill_ports is used, monitor trigging is crucial, as the ports are not guaranteed to be killed until the driver is unloaded. Thus, a monitor must be triggered for at least the pending_driver case.

The possible monitor messages to expect are the same as when using option unloaded to function monitor/2.

The function returns one of the following statuses upon success:

{ok, unloaded} - The driver was immediately unloaded, meaning that the driver name is now free to use by other drivers and, if the underlying OS permits it, the memory occupied by the driver object code is now reclaimed.

The driver can only be unloaded when there are no open ports using it and no more users require it to be loaded.

{ok, pending_driver}or {ok, pending_driver, reference()} - Indicates that this call removed the last user from the driver, but there are still open ports using it. When all ports are closed and no new users have arrived, the driver is reloaded and the name and memory reclaimed.

This return value is valid even if option kill_ports was used, as killing ports can be a process that does not complete immediately. However, the condition is in that case transient. Monitors are always useful to detect when the driver is really unloaded.

{ok, pending_process}or {ok, pending_process, reference()} - The unload request is registered, but other users still hold the driver. Notice that the term pending_process can refer to the running process; there can be more than one user in the same process.

This is a normal, healthy, return value if the call was just placed to inform the emulator that you have no further use of the driver. It is the most common return value in the most common scenario described in the introduction.

The function accepts the following parameters:

Name - Name is the name of the driver to be unloaded. The name can be specified as an iolist/0 or as an atom/0.

OptionList - Argument OptionList can be used to specify certain behavior regarding ports and triggering monitors under certain conditions:

kill_ports - Forces killing of all ports opened using this driver, with exit reason driver_unloaded, if you are the last user of the driver.

If other users have the driver loaded, this option has no effect.

To get the consistent behavior of killing ports when the last user unloads, use driver option kill_ports when loading the driver instead.

{monitor, MonitorOption} - Creates a driver monitor if the condition specified in MonitorOption is true. The valid options are:

pending_driver - Creates a driver monitor if the return value is to be {ok, pending_driver}.

pending - Creates a monitor if the return value is {ok, pending_driver} or {ok, pending_process}.

The pending_driver MonitorOption is by far the most useful. It must be used to ensure that the driver really is unloaded and the ports closed whenever option kill_ports is used, or the driver can have been loaded with driver option kill_ports.

Using the monitor triggers in the call to try_unload ensures that the monitor is added before the unloading is executed, meaning that the monitor is always properly triggered, which is not the case if monitor/2 is called separately.

The function can return the following error conditions, all well specified (no opaque values):

{error, linked_in_driver} - You were trying to unload an Erlang statically linked-in driver, which cannot be manipulated with this interface (and cannot be unloaded at all).

{error, not_loaded} - The driver Name is not present in the system.

{error, not_loaded_by_this_process} - The driver Name is present in the system, but there is no user of it in this process.

As a special case, drivers can be unloaded from processes that have done no corresponding call to try_load/3 if, and only if, there are no users of the driver at all, which can occur if the process containing the last user dies.

{error, permanent} - The driver has made itself permanent, in which case it can no longer be manipulated by this interface (much like a statically linked-in driver).

The function throws a badarg exception if the parameters are not specified as described here.

unload(Name)

-spec unload(Name) -> ok | {error, ErrorDesc} when Name :: driver(), ErrorDesc :: term().

Unloads, or at least dereferences the driver named Name. If the caller is the last user of the driver, and no more open ports use the driver, the driver gets unloaded. Otherwise, unloading is delayed until all ports are closed and no users remain.

If there are other users of the driver, the reference counts of the driver is merely decreased, so that the caller is no longer considered a user of the driver. For use scenarios, see the description in the beginning of this module.

The ErrorDesc returned is an opaque value to be passed further on to function format_error/1. For more control over the operation, use the try_unload/2 interface.

The function throws a badarg exception if the parameters are not specified as described here.

unload_driver(Name)

-spec unload_driver(Name) -> ok | {error, ErrorDesc} when Name :: driver(), ErrorDesc :: term().

Unloads, or at least dereferences the driver named Name. If the caller is the last user of the driver, all remaining open ports using the driver are killed with reason driver_unloaded and the driver eventually gets unloaded.

If there are other users of the driver, the reference counts of the driver is merely decreased, so that the caller is no longer considered a user. For use scenarios, see the description in the beginning of this module.

The ErrorDesc returned is an opaque value to be passed further on to function format_error/1. For more control over the operation, use the try_unload/2 interface.

The function throws a badarg exception if the parameters are not specified as described here.

erl_debugger

Erlang debugger support (EXPERIMENTAL).

This module exposes low-level functionality for the implementation of a debugger for Erlang.

Any local process can register itself as the debugger for a node, but there can be at most one such process registered at any given time. Using the BIFs in this module, a debugger can:

set breakpoints;

inspect internal process state, such registers, stack-frames;

get notified on debugger events such as a process hitting a breakpoint;

resume processes paused on breakpoints

At the moment, the API is highly experimental; so don't depend on it, or otherwise expect frequent incompatible changes.

Summary

Types

event()

Debugger events.

event_message()

The debugger process will receive debugger-event messages, wrapped in an envelope of this type.

instrumentation()

Debugging instrumentations that can be applied on module loading.

reg_val()

The value of an X or a Y register, provided it fits within the requested size.

session()

Debugger session identifier.

stack_frame()

A stack-frame, including the value of each slot.

stack_frame_fun()

What is running in each stack frame, including special VM frames.

stack_frame_info()

Extra information about a stack-frame.

stack_frame_slot()

The contents of a stack frame slot can be a Y register or an exception handler.

Functions

breakpoint(Module, Line, Flag)

Sets or clear a breakpoint on the given Module/Line.

breakpoints(Module)

Returns information on available breakpoints for a module.

breakpoints(Module, FunName, Arity)

Returns information on available breakpoints for a given function. .

instrumentations()

Returns the instrumentations that will be applied on module loading.

peek_stack_frame_slot(Pid, FrameNo, Slot, MaxSize)

Gets the value of a slot in a suspended process stack-frame.

peek_xreg(Pid, Reg, MaxSize)

Get the value of an X register for a suspended process.

register(Pid)

Register the given process as the debugger.

stack_frames(Pid, MaxTermSize)

Get the all the stack-frames for a suspended process.

supported()

Returns true if the emulator supports debugging.

toggle_instrumentations(Toggle)

Updates the instrumentations that will be applied on module loading.

unregister(Pid, Session)

Unregisters the given process.

whereis()

Returns the pid of the registered debugger.

xregs_count(Pid)

Get the number of X registers currently in use by a suspended process.

Types

event()

(since OTP 28.0)

-type event() :: {breakpoint, pid(), mfa(), Line :: pos_integer(), Resume :: fun(() -> ok)}.

Debugger events.

Here are the possible events:

{breakpoint, Pid, {M,F,A}, Line, Resume}: process Pid hit a breakpoint on module M, at the given Line. The debugger can resume the process by executing Resume().

event_message()

(since OTP 28.0)

-type event_message() :: {debugger_event, session(), event()}.

The debugger process will receive debugger-event messages, wrapped in an envelope of this type.

instrumentation()

(since OTP 28.0)

-type instrumentation() :: line_breakpoint.

Debugging instrumentations that can be applied on module loading.

line_breakpoint: Allows setting breakpoints at the beginning of executable lines

reg_val()

(since OTP 28.0)

-type reg_val() :: {value, term()} | {too_large, Size :: pos_integer()}.

The value of an X or a Y register, provided it fits within the requested size.

If it is too large, then size of the term.

session()

(since OTP 28.0)

-opaque session()

Debugger session identifier.

It is attached to all debugger events.

stack_frame()

(since OTP 28.0)

-type stack_frame() :: {FrameNo :: non_neg_integer(), stack_frame_fun(), stack_frame_info()}.

A stack-frame, including the value of each slot.

stack_frame_fun()

(since OTP 28.0)

-type stack_frame_fun() ::
          #{function := mfa(), line := pos_integer() | undefined} |
          '' | '' | '' |
          '' | 'unknown function'.

What is running in each stack frame, including special VM frames.

stack_frame_info()

(since OTP 28.0)

-type stack_frame_info() :: #{slots := [stack_frame_slot()], code := pos_integer()}.

Extra information about a stack-frame.

slots: Y-registers (in order [Y0,...Yk]), followed by exception-handlers.

code: Memory address of the next instruction to execute in this frame.

stack_frame_slot()

(since OTP 28.0)

-type stack_frame_slot() :: reg_val() | {'catch', stack_frame_fun()}.

The contents of a stack frame slot can be a Y register or an exception handler.

Functions

breakpoint(Module, Line, Flag)

(since OTP 28.0)

-spec breakpoint(Module, Line, Flag) -> ok | {error, Reason}
                    when
                        Module :: module(),
                        Line :: pos_integer(),
                        Flag :: boolean(),
                        Reason :: {unsupported, Module | Line} | {badkey, Module | Line}.

Sets or clear a breakpoint on the given Module/Line.

When a process hits a breakpoint, it will pause and a breakpoint message is sent to the registered debugger.

Returns ok on success. It can fail with the following reasons:

{badkey, Module}: The given module is not loaded.

{unsupported, Module}: The module was loaded without support for line breakpoints.

{badkey, Line}: The line is not relevant; it could refer to a comment, not existing in the module source, and so on.

{unsupported, Line}: It is not possible to set a breakpoint in in the given line; for example, if it refers to a function head.

breakpoints(Module)

(since OTP 28.0)

-spec breakpoints(Module) -> {ok, Result} | {error, Reason}
                     when
                         Module :: module(),
                         Result :: #{Fun => #{Line => boolean()}},
                         Fun :: {atom(), arity()},
                         Line :: pos_integer(),
                         Reason :: badkey.

Returns information on available breakpoints for a module.

For each function in the module, returns a map #{Line => boolean()}, where the keys are lines where breakpoints can be set, and the value represents whether be breakpoint is enabled (true) or not (false).

breakpoints(Module, FunName, Arity)

(since OTP 28.0)

-spec breakpoints(Module, FunName, Arity) -> {ok, Result} | {error, Reason}
                     when
                         Module :: module(),
                         FunName :: atom(),
                         Arity :: arity(),
                         Result :: #{Line => boolean()},
                         Line :: pos_integer(),
                         Reason :: {badkey, module() | {FunName, Arity}}.

Returns information on available breakpoints for a given function. .

The function need not be exported.

Returns a map #{Line => boolean()}, where the keys are lines where breakpoints can be set, and the value represents whether be breakpoint is enabled (true) or not (false).

instrumentations()

(since OTP 28.0)

-spec instrumentations() -> #{instrumentation() => boolean()}.

Returns the instrumentations that will be applied on module loading.

Modules that are already loaded may have had a different set of instrumentations applied.

peek_stack_frame_slot(Pid, FrameNo, Slot, MaxSize)

(since OTP 28.0)

-spec peek_stack_frame_slot(Pid, FrameNo, Slot, MaxSize) -> running | undefined | stack_frame_slot()
                               when
                                   Pid :: pid(),
                                   FrameNo :: pos_integer(),
                                   Slot :: non_neg_integer(),
                                   MaxSize :: non_neg_integer().

Gets the value of a slot in a suspended process stack-frame.

Returns running if the process is not suspended, and undefined if the frame or the slot does not exist for that process. Otherwise, returns the slot, that can be a term, if its size is less than MaxTermSize, or an exeption handler.

peek_xreg(Pid, Reg, MaxSize)

(since OTP 28.0)

-spec peek_xreg(Pid, Reg, MaxSize) -> running | undefined | reg_val()
                   when Pid :: pid(), Reg :: non_neg_integer(), MaxSize :: non_neg_integer().

Get the value of an X register for a suspended process.

register(Pid)

(since OTP 28.0)

-spec register(Pid) -> {ok, session()} | {error, already_exists} when Pid :: pid().

Register the given process as the debugger.

If the registration succeeds, it returns {ok, Session}, where Session is a token that will be included in every message sent to the process.

Returns {error, already_exists} if some process is currently registered as debugger.

stack_frames(Pid, MaxTermSize)

(since OTP 28.0)

-spec stack_frames(Pid, MaxTermSize) -> running | [stack_frame()]
                      when Pid :: pid(), MaxTermSize :: non_neg_integer().

Get the all the stack-frames for a suspended process.

If the given process is not in a suspended state, returns running. Otherwise, a list of stack frames including the content of each slot is returned. For slots containing terms, MaxTermSize controls the maximum size of values that are allowed to be returned (to avoid accidentally blowing the heap of the caller).

supported()

(since OTP 28.0)

-spec supported() -> boolean().

Returns true if the emulator supports debugging.

The debugger can only be used if the +D argument was passed to the emulator on start-up.

toggle_instrumentations(Toggle)

(since OTP 28.0)

-spec toggle_instrumentations(Toggle) -> ok when Toggle :: #{instrumentation() => boolean()}.

Updates the instrumentations that will be applied on module loading.

Modules that are already loaded will keep the instrumentation they had at their time of loading.

unregister(Pid, Session)

(since OTP 28.0)

-spec unregister(Pid, Session) -> ok when Pid :: pid(), Session :: session().

Unregisters the given process.

The session given on registration needs to be provided.

whereis()

(since OTP 28.0)

-spec whereis() -> undefined | pid().

Returns the pid of the registered debugger.

xregs_count(Pid)

(since OTP 28.0)

-spec xregs_count(Pid) -> running | non_neg_integer() when Pid :: pid().

Get the number of X registers currently in use by a suspended process.

seq_trace

Sequential tracing of information transfers.

Sequential tracing makes it possible to trace information flows between processes resulting from one initial transfer of information. Sequential tracing is independent of the ordinary tracing in Erlang, which is controlled by the erlang:trace/3 BIF. For more information about what sequential tracing is and how it can be used, see section Sequential Tracing.

seq_trace provides functions that control all aspects of sequential tracing. There are functions for activation, deactivation, inspection, and for collection of the trace output.

Trace Messages Sent to the System Tracer

The format of the messages is one of the following, depending on if flag timestamp of the trace token is set to true or false:

{seq_trace, Label, SeqTraceInfo, TimeStamp}

or

{seq_trace, Label, SeqTraceInfo}

Where:

Label = int()
TimeStamp = {Seconds, Milliseconds, Microseconds}
  Seconds = Milliseconds = Microseconds = int()

SeqTraceInfo can have the following formats:

{send, Serial, From, To, Message} - Used when a process From with its trace token flag send set to true has sent information. To may be a process identifier, a registered name on a node represented as {NameAtom, NodeAtom}, or a node name represented as an atom. From may be a process identifier or a node name represented as an atom. Message contains the information passed along in this information transfer. If the transfer is done via message passing, it is the actual message.

{'receive', Serial, From, To, Message} - Used when a process To receives information with a trace token that has flag 'receive' set to true. To may be a process identifier, or a node name represented as an atom. From may be a process identifier or a node name represented as an atom. Message contains the information passed along in this information transfer. If the transfer is done via message passing, it is the actual message.

{print, Serial, From, _, Info} - Used when a process From has called seq_trace:print(Label, TraceInfo) and has a trace token with flag print set to true, and label set to Label.

Serial is a tuple {PreviousSerial, ThisSerial}, where:

Integer PreviousSerial denotes the serial counter passed in the last received information that carried a trace token. If the process is the first in a new sequential trace, PreviousSerial is set to the value of the process internal "trace clock".

Integer ThisSerial is the serial counter that a process sets on outgoing messages. It is based on the process internal "trace clock", which is incremented by one before it is attached to the trace token in the message.

Sequential Tracing

Sequential tracing is a way to trace a sequence of information transfers between different local or remote processes, where the sequence is initiated by a single transfer. The typical information transfer is an ordinary Erlang message passed between two processes, but information is transferred also in other ways. In short, it works as follows:

Each process has a trace token, which can be empty or not empty. When not empty, the trace token can be seen as the tuple {Label, Flags, Serial, From}. The trace token is passed invisibly when information is passed between processes. In most cases the information is passed in ordinary messages between processes, but information is also passed between processes by other means. For example, by spawning a new process. An information transfer between two processes is represented by a send event and a receive event regardless of how it is passed.

To start a sequential trace, the user must explicitly set the trace token in the process that will send the first information in a sequence.

The trace token of a process is set each time the process receives information. This is typically when the process matches a message in a receive statement, according to the trace token carried by the received message, empty or not.

On each Erlang node, a process can be set as the system tracer. This process will receive trace messages each time information with a trace token is sent or received (if the trace token flag send or 'receive' is set). The system tracer can then print each trace event, write it to a file, or whatever suitable.

Note

The system tracer only receives those trace events that occur locally within the Erlang node. To get the whole picture of a sequential trace, involving processes on many Erlang nodes, the output from the system tracer on each involved node must be merged (offline).

The following sections describe sequential tracing and its most fundamental concepts.

Different Information Transfers

Information flows between processes in a lot of different ways. Not all flows of information will be covered by sequential tracing. One example is information passed via ETS tables. Below is a list of information paths that are covered by sequential tracing:

Message Passing - All ordinary messages passed between Erlang processes.

Exit signals - An exit signal is represented as an {'EXIT', Pid, Reason} tuple.

Process Spawn - A process spawn is represented as multiple information transfers. At least one spawn request and one spawn reply. The actual amount of information transfers depends on what type of spawn it is and may also change in future implementations. Note that this is more or less an internal protocol that you are peeking at. The spawn request will be represented as a tuple with the first element containing the atom spawn_request, but this is more or less all that you can depend on.

Note

If you do ordinary send or receive trace on the system, you will only see ordinary message passing, not the other information transfers listed above.

Note

When a send event and corresponding receive event do not both correspond to ordinary Erlang messages, the Message part of the trace messages may not be identical. This since all information not necessarily are available when generating the trace messages.

Trace Token

Each process has a current trace token which is "invisibly" passed from the parent process on creation of the process.

The current token of a process is set in one of the following two ways:

Explicitly by the process itself, through a call to seq_trace:set_token/1,2

When information is received. This is typically when a received message is matched out in a receive expression, but also when information is received in other ways.

In both cases, the current token is set. In particular, if the token of a received message is empty, the current token of the process is set to empty.

A trace token contains a label and a set of flags. Both the label and the flags are set in both alternatives above.

Serial

The trace token contains a component called serial. It consists of two integers, Previous and Current. The purpose is to uniquely identify each traced event within a trace sequence, as well as to order the messages chronologically and in the different branches, if any.

The algorithm for updating Serial can be described as follows:

Let each process have two counters, prev_cnt and curr_cnt, both are set to 0 when a process is created outside of a trace sequence. The counters are updated at the following occasions:

When the process is about to pass along information to another process and the trace token is not empty. This typically occurs when sending a message, but also, for example, when spawning another process.

Let the serial of the trace token be tprev and tcurr.

curr_cnt := curr_cnt + 1
tprev := prev_cnt
tcurr := curr_cnt

The trace token with tprev and tcurr is then passed along with the information passed to the other process.

When the process calls seq_trace:print(Label, Info), Label matches the label part of the trace token and the trace token print flag is true.

The algorithm is the same as for send above.

When information is received that also contains a non-empty trace token. For example, when a message is matched out in a receive expression, or when a new process is spawned.

The process trace token is set to the trace token from the message.

Let the serial of the trace token be tprev and tcurr.

if (curr_cnt < tcurr )
   curr_cnt := tcurr
prev_cnt := tcurr

curr_cnt of a process is incremented each time the process is involved in a sequential trace. The counter can reach its limit (27 bits) if a process is very long-lived and is involved in much sequential tracing. If the counter overflows, the serial for ordering of the trace events cannot be used. To prevent the counter from overflowing in the middle of a sequential trace, function seq_trace:reset_trace/0 can be called to reset prev_cnt and curr_cnt of all processes in the Erlang node. This function also sets all trace tokens in processes and their message queues to empty, and thus stops all ongoing sequential tracing.

Performance Considerations

The performance degradation for a system that is enabled for sequential tracing is negligible as long as no tracing is activated. When tracing is activated, there is an extra cost for each traced message, but all other messages are unaffected.

Ports

Sequential tracing is not performed across ports.

If the user for some reason wants to pass the trace token to a port, this must be done manually in the code of the port controlling process. The port controlling processes have to check the appropriate sequential trace settings (as obtained from seq_trace:get_token/1) and include trace information in the message data sent to their respective ports.

Similarly, for messages received from a port, a port controller has to retrieve trace-specific information, and set appropriate sequential trace flags through calls to seq_trace:set_token/2.

Distribution

Sequential tracing between nodes is performed transparently. This applies to C-nodes built with Erl_Interface too. A C-node built with Erl_Interface only maintains one trace token, which means that the C-node appears as one process from the sequential tracing point of view.

Example of Use

This example gives a rough idea of how the new primitives can be used and what kind of output it produces.

Assume that you have an initiating process with Pid == <0.30.0> like this:

-module(seqex).
-compile(export_all).

loop(Port) ->
    receive
        {Port,Message} ->
            seq_trace:set_token(label,17),
            seq_trace:set_token('receive',true),
            seq_trace:set_token(print,true),
            seq_trace:print(17,"**** Trace Started ****"),
            call_server ! {self(),the_message};
        {ack,Ack} ->
            ok
    end,
    loop(Port).

And a registered process call_server with Pid == <0.31.0> like this:

loop() ->
    receive
        {PortController,Message} ->
            Ack = {received, Message},
            seq_trace:print(17,"We are here now"),
            PortController ! {ack,Ack}
    end,
    loop().

A possible output from the system's sequential_tracer can be like this:

17:<0.30.0> Info {0,1} WITH
"**** Trace Started ****"
17:<0.31.0> Received {0,2} FROM <0.30.0> WITH
{<0.30.0>,the_message}
17:<0.31.0> Info {2,3} WITH
"We are here now"
17:<0.30.0> Received {2,4} FROM <0.31.0> WITH
{ack,{received,the_message}}

The implementation of a system tracer process that produces this printout can look like this:

tracer() ->
    receive
        {seq_trace,Label,TraceInfo} ->
           print_trace(Label,TraceInfo,false);
        {seq_trace,Label,TraceInfo,Ts} ->
           print_trace(Label,TraceInfo,Ts);
        _Other -> ignore
    end,
    tracer().

print_trace(Label,TraceInfo,false) ->
    io:format("~p:",[Label]),
    print_trace(TraceInfo);
print_trace(Label,TraceInfo,Ts) ->
    io:format("~p ~p:",[Label,Ts]),
    print_trace(TraceInfo).

print_trace({print,Serial,From,_,Info}) ->
    io:format("~p Info ~p WITH~n~p~n", [From,Serial,Info]);
print_trace({'receive',Serial,From,To,Message}) ->
    io:format("~p Received ~p FROM ~p WITH~n~p~n",
              [To,Serial,From,Message]);
print_trace({send,Serial,From,To,Message}) ->
    io:format("~p Sent ~p TO ~p WITH~n~p~n",
              [From,Serial,To,Message]).

The code that creates a process that runs this tracer function and sets that process as the system tracer can look like this:

start() ->
    Pid = spawn(?MODULE,tracer,[]),
    seq_trace:set_system_tracer(Pid), % set Pid as the system tracer
    ok.

With a function like test/0, the whole example can be started:

test() ->
    P = spawn(?MODULE, loop, [port]),
    register(call_server, spawn(?MODULE, loop, [])),
    start(),
    P ! {port,message}.

Summary

Types

component()

flag()

token()

An opaque term (a tuple) representing a trace token.

tracer()

value()

Functions

get_system_tracer()

Returns the pid, port identifier or tracer module of the current system tracer or false if no system tracer is activated.

get_token()

Returns the value of the trace token for the calling process. If [] is returned, it means that tracing is not active. Any other value returned is the value of an active trace token. The value returned can be used as input to the set_token/1 function.

get_token(Component)

Returns the value of the trace token component Component. See set_token/2 for possible values of Component and Val.

print(TraceInfo)

Puts the Erlang term TraceInfo into the sequential trace output if the calling process currently is executing within a sequential trace and the print flag of the trace token is set.

print(Label, TraceInfo)

Same as print/1 with the additional condition that TraceInfo is output only if Label is equal to the label component of the trace token.

reset_trace()

Sets the trace token to empty for all processes on the local node. The process internal counters used to create the serial of the trace token is set to 0. The trace token is set to empty for all messages in message queues. Together this will effectively stop all ongoing sequential tracing in the local node.

set_system_tracer(Tracer)

Sets the system tracer. The system tracer can be either a process, port or tracer module denoted by Tracer. Returns the previous value (which can be false if no system tracer is active).

set_token(Token)

Sets the trace token for the calling process to Token. If Token == [] then tracing is disabled, otherwise Token should be an Erlang term returned from get_token/0 or set_token/1. set_token/1 can be used to temporarily exclude message passing from the trace by setting the trace token to empty like this

set_token(Component, Val)

Sets the individual Component of the trace token to Val. Returns the previous value of the component.

Types

component()

(not exported)

-type component() :: label | serial | flag().

flag()

(not exported)

-type flag() :: send | 'receive' | print | timestamp | monotonic_timestamp | strict_monotonic_timestamp.

token()

(not exported)

-type token() :: {integer(), boolean(), _, _, _}.

An opaque term (a tuple) representing a trace token.

tracer()

(not exported)

-type tracer() :: (Pid :: pid()) | port() | (TracerModule :: {module(), term()}) | false.

value()

(not exported)

-type value() ::
          (Label :: term()) |
          {Previous :: non_neg_integer(), Current :: non_neg_integer()} |
          (Bool :: boolean()).

Functions

get_system_tracer()

-spec get_system_tracer() -> Tracer when Tracer :: tracer().

Returns the pid, port identifier or tracer module of the current system tracer or false if no system tracer is activated.

get_token()

-spec get_token() -> [] | token().

Returns the value of the trace token for the calling process. If [] is returned, it means that tracing is not active. Any other value returned is the value of an active trace token. The value returned can be used as input to the set_token/1 function.

get_token(Component)

-spec get_token(Component) -> [] | {Component, Val} when Component :: component(), Val :: value().

Returns the value of the trace token component Component. See set_token/2 for possible values of Component and Val.

print(TraceInfo)

-spec print(TraceInfo) -> ok when TraceInfo :: term().

Puts the Erlang term TraceInfo into the sequential trace output if the calling process currently is executing within a sequential trace and the print flag of the trace token is set.

print(Label, TraceInfo)

-spec print(Label, TraceInfo) -> ok when Label :: integer(), TraceInfo :: term().

Same as print/1 with the additional condition that TraceInfo is output only if Label is equal to the label component of the trace token.

reset_trace()

-spec reset_trace() -> true.

Sets the trace token to empty for all processes on the local node. The process internal counters used to create the serial of the trace token is set to 0. The trace token is set to empty for all messages in message queues. Together this will effectively stop all ongoing sequential tracing in the local node.

set_system_tracer(Tracer)

-spec set_system_tracer(Tracer) -> OldTracer when Tracer :: tracer(), OldTracer :: tracer().

Sets the system tracer. The system tracer can be either a process, port or tracer module denoted by Tracer. Returns the previous value (which can be false if no system tracer is active).

Failure: {badarg, Info}} if Pid is not an existing local pid.

set_token(Token)

-spec set_token(Token) -> PreviousToken | ok when Token :: [] | token(), PreviousToken :: [] | token().

Sets the trace token for the calling process to Token. If Token == [] then tracing is disabled, otherwise Token should be an Erlang term returned from get_token/0 or set_token/1. set_token/1 can be used to temporarily exclude message passing from the trace by setting the trace token to empty like this:

OldToken = seq_trace:set_token([]), % set to empty and save
                                    % old value
% do something that should not be part of the trace
io:format("Exclude the signalling caused by this~n"),
seq_trace:set_token(OldToken), % activate the trace token again
...

Returns the previous value of the trace token.

set_token(Component, Val)

-spec set_token(Component, Val) -> OldVal
                   when Component :: component(), Val :: value(), OldVal :: value().

Sets the individual Component of the trace token to Val. Returns the previous value of the component.

set_token(label, Label) - The label component is a term which identifies all events belonging to the same sequential trace. If several sequential traces can be active simultaneously, label is used to identify the separate traces. Default is 0.

Warning

Labels were restricted to small signed integers (28 bits) prior to OTP 21. The trace token will be silently dropped if it crosses over to a node that does not support the label.

set_token(serial, SerialValue) - SerialValue = {Previous, Current}. The serial component contains counters which enables the traced messages to be sorted, should never be set explicitly by the user as these counters are updated automatically. Default is {0, 0}.

set_token(send, Bool) - A trace token flag (true | false) which enables/disables tracing on information sending. Default is false.

set_token('receive', Bool) - A trace token flag (true | false) which enables/disables tracing on information reception. Default is false.

set_token(print, Bool) - A trace token flag (true | false) which enables/disables tracing on explicit calls to seq_trace:print/1. Default is false.

set_token(timestamp, Bool) - A trace token flag (true | false) which enables/disables a timestamp to be generated for each traced event. Default is false.

set_token(strict_monotonic_timestamp, Bool) - A trace token flag (true | false) which enables/disables a strict monotonic timestamp to be generated for each traced event. Default is false. Timestamps will consist of Erlang monotonic time and a monotonically increasing integer. The time-stamp has the same format and value as produced by {erlang:monotonic_time(nanosecond), erlang:unique_integer([monotonic])}.

set_token(monotonic_timestamp, Bool) - A trace token flag (true | false) which enables/disables a strict monotonic timestamp to be generated for each traced event. Default is false. Timestamps will use Erlang monotonic time. The time-stamp has the same format and value as produced by erlang:monotonic_time(nanosecond).

If multiple timestamp flags are passed, timestamp has precedence over strict_monotonic_timestamp which in turn has precedence over monotonic_timestamp. All timestamp flags are remembered, so if two are passed and the one with highest precedence later is disabled the other one will become active.

trace

The Erlang trace interface.

The Erlang run-time system exposes several trace points that allow users to be notified when they are triggered. Trace points are things such as function calls, message sending and receiving, garbage collection, and process scheduling.

The functions in this module can be used directly, but can also be used as building blocks to build more sophisticated debugging or profiling tools. For debugging Erlang code it is recommended to use dbg and for profiling to use tprof.

Trace Sessions

All tracing is done within a trace session. Trace sessions can be created and destroyed dynamically. Each session has its own tracer that will receive all trace messages. Several sessions can exist at the same time without interfering with each other. When a trace session is destroyed, all its trace settings are automatically cleaned up.

Example:

%% Create a tracer process that will receive the trace events
1> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end).
<0.91.0>
%% Create a session using the Tracer
2> Session = trace:session_create(my_session, Tracer, []).
{#Ref<0.1543805153.1548353537.92331>,{my_session, 0}}
%% Setup call tracing on self()
3> trace:process(Session, self(), true, [call]).
1
%% Setup call tracing on lists:seq/2
4> trace:function(Session, {lists,seq,2}, [], []).
1
%% Call the traced function
5> lists:seq(1, 10).
{trace,<0.89.0>,call,{lists,seq,[1,10]}} % The trace message
[1,2,3,4,5,6,7,8,9,10] % The return value
%% Cleanup the trace session
6> trace:session_destroy(Session).
ok

Node Local Tracing Only

The functions in this module only operates on the local node. That is, both the traced processes/ports as well as the tracer process/port/module must all reside on the same local node as the call is made. To trace remote nodes use dbg or ttb.

Change

This trace module was introduced in OTP 27.0. The interface and semantics are similar to the older functions erlang:trace/3, erlang:trace_pattern/3, and erlang:trace_info/2.

The main difference is the old functions operate on a single static trace session per node. That could impose the problem that different users and tools would interfere with each other's trace settings. The new trace functions in this module all operate on dynamically created trace sesssions isolated from each other. Also, this makes it easier to safely disable all trace settings when done by a single call to session_destroy/1.

To change an existing tool to use the interface the following table can be useful:

Old function call | corresponds to
erlang:trace(Pid, ...) | process(S, Pid, ...)
erlang:trace(processes, ...) | process(S, all, ...)
erlang:trace(existing_processes, ...) | process(S, existing, ...)
erlang:trace(new_processes, ...) | process(S, new, ...)
erlang:trace(Port, ...) | port(S, Port, ...)
erlang:trace(ports, ...) | port(S, all, ...)
erlang:trace(existing_ports, ...) | port(S, existing, ...)
erlang:trace(new_ports, ...) | port(S, new, ...)
erlang:trace(all, ...) | process(S, all, ...) and port(S, all, ...)
erlang:trace(existing, ...) | process(S, existing, ...) and port(S, existing, ...)
erlang:trace(new, ...) | process(S, new, ...) and port(S, new, ...)
erlang:trace_pattern(MFA, ...) | function(S, MFA, ...)
erlang:trace_pattern(send, ...) | send(S, ...)
erlang:trace_pattern('receive', ...) | recv(S, ...)
erlang:trace_info(...) | info(S, ...)

Argument S is the trace session that must first be created with session_create/3. The other arguments (implied by ...) are mostly the same. The only other difference is that the tracer is always the tracer specified when the session was created. Options {tracer,T}, {tracer,M,S}, {meta,T}, and {meta,M,S} are therefore not allowed, and the default tracer is never the calling process.

Summary

Types

match_variable()

session()

A handle to an isolated trace session.

session_strong_ref()

session_weak_ref()

A weak session handle as returned by session_info/1. A weak session handle can be used like a full session handle, but it will not prevent the session from being destroyed when the last strong handle is garbage collected.

system_event()

system_value()

trace_flag()

trace_info_flag()

trace_info_item_result()

trace_info_return()

trace_info_system_item()

trace_match_spec()

trace_pattern_flag()

trace_pattern_mfa()

Functions

delivered(Session, Tracee)

Equivalent to erlang:trace_delivered(Tracee) except that it is run within the given session/0.

function(Session, MFA, MatchSpec, FlagList)

Enable or disable call tracing for one or more functions.

info(Session, PidPortFuncEvent, Item)

Return trace information about a port, process, function, or event.

port(Session, Ports, How, FlagList)

Turn on or off trace flags for one or more ports.

process(Session, Procs, How, FlagList)

Turn on or off trace flags for one or more processes.

recv(Session, MatchSpec, FlagList)

Set trace pattern for message receiving.

send(Session, MatchSpec, FlagList)

Set trace pattern for message sending.

session_create(Name, Tracer, Opts)

Create a new trace session.

session_destroy(Session)

Destroy a trace session and cleanup all its settings on processes, ports, and functions.

session_info(PidPortFuncEvent)

Return which trace sessions that affect a port, process, function, or event.

system(Session, Event, Value)

Enable/disable monitoring of system events.

Types

match_variable()

(not exported) (since OTP 27.0)

-type match_variable() :: atom().

session()

(since OTP 27.0)

-type session() :: {session_strong_ref(), session_weak_ref()} | session_weak_ref().

A handle to an isolated trace session.

session_strong_ref()

(since OTP 27.0)

-opaque session_strong_ref()

session_weak_ref()

(since OTP 27.0)

-opaque session_weak_ref()

A weak session handle as returned by session_info/1. A weak session handle can be used like a full session handle, but it will not prevent the session from being destroyed when the last strong handle is garbage collected.

system_event()

(not exported) (since OTP 27.0)

-type system_event() ::
          busy_port | busy_dist_port | long_gc | long_message_queue | long_schedule | large_heap.

system_value()

(not exported) (since OTP 27.0)

-type system_value() ::
          true | false | non_neg_integer() | {Disable :: non_neg_integer(), Enable :: pos_integer()}.

trace_flag()

(not exported) (since OTP 27.0)

-type trace_flag() :: trace_info_flag() | all | cpu_timestamp.

trace_info_flag()

(not exported) (since OTP 27.0)

-type trace_info_flag() ::
          arity | call | exiting | garbage_collection | monotonic_timestamp | procs | ports |
          'receive' | return_to | running | running_procs | running_ports | send | set_on_first_link |
          set_on_first_spawn | set_on_link | set_on_spawn | silent | strict_monotonic_timestamp |
          timestamp.

trace_info_item_result()

(not exported) (since OTP 27.0)

-type trace_info_item_result() ::
          {traced, global | local | false | undefined} |
          {match_spec, trace_match_spec() | false | undefined} |
          {meta, pid() | port() | false | undefined | []} |
          {meta, module(), term()} |
          {meta_match_spec, trace_match_spec() | false | undefined} |
          {call_count, non_neg_integer() | boolean() | undefined} |
          {call_time,
           [{pid(), non_neg_integer(), non_neg_integer(), non_neg_integer()}] | boolean() | undefined} |
          {call_memory, [{pid(), non_neg_integer(), non_neg_integer()}] | boolean() | undefined}.

trace_info_return()

(not exported) (since OTP 27.0)

-type trace_info_return() ::
          undefined |
          {flags, [trace_info_flag()]} |
          {tracer, pid() | port() | []} |
          {tracer, module(), term()} |
          trace_info_item_result() |
          {all, [trace_info_item_result()] | false | undefined} |
          {system, [trace_info_system_item()]}.

trace_info_system_item()

(not exported) (since OTP 27.0)

-type trace_info_system_item() ::
          busy_port | busy_dist_port |
          {long_gc, non_neg_integer()} |
          {long_message_queue, {Disable :: non_neg_integer(), Enable :: pos_integer()}} |
          {long_schedule, non_neg_integer()} |
          {large_heap, non_neg_integer()}.

trace_match_spec()

(not exported) (since OTP 27.0)

-type trace_match_spec() :: [{[term()] | '_' | match_variable(), [term()], [term()]}].

trace_pattern_flag()

(not exported) (since OTP 27.0)

-type trace_pattern_flag() :: global | local | meta | call_count | call_time | call_memory.

trace_pattern_mfa()

(not exported) (since OTP 27.0)

-type trace_pattern_mfa() :: {atom(), atom(), arity() | '_'}.

Functions

delivered(Session, Tracee)

(since OTP 27.0)

-spec delivered(Session :: session(), Tracee :: pid() | all) -> reference().

Equivalent to erlang:trace_delivered(Tracee) except that it is run within the given session/0.

function(Session, MFA, MatchSpec, FlagList)

(since OTP 27.0)

-spec function(Session, MFA, MatchSpec, FlagList) -> non_neg_integer()
                  when
                      Session :: session(),
                      MFA :: trace_pattern_mfa() | on_load,
                      MatchSpec :: trace_match_spec() | boolean() | restart | pause,
                      FlagList :: [trace_pattern_flag()].

Enable or disable call tracing for one or more functions.

Must be combined with process/4 to set the call trace flag for one or more processes.

Conceptually, call tracing works as follows. In each trace session, a set of processes and a set of functions have been marked for tracing. If a traced process calls a traced function, the trace action is taken. Otherwise, nothing happens.

To add or remove one or more processes to the set of traced processes, use process/4.

Use this function to add or remove functions to the set of traced functions in a trace session.

Argument Session is the trace session to operate on as returned by session_create/3.

Argument MFA is to be a tuple, such as {Module, Function, Arity}, or the atom on_load (described below). The MFA tuple specifies the module, function, and arity for the functions to be traced. The atom '_' can be used as a wildcard in any of the following ways:

{Module,Function,'_'} - All functions of any arity named Function in module Module.

{Module,'_','_'} - All functions in module Module.

{'_','_','_'} - All functions in all loaded modules.

Other combinations, such as {Module,'_',Arity}, are not allowed.

If argument MFA is the atom on_load, the match specification and flag list are used on all functions in all modules that are newly loaded.

Argument MatchSpec can take the following forms:

true - Enable tracing for the matching functions. Any match specification is removed.

false - Disable tracing for the matching functions. Any match specification is removed.

MatchExpression - A match specification. An empty list is equivalent to true. For a description of match specifications, see section Match Specifications in Erlang in the User's Guide for the ERTS application.

restart - For the FlagList options call_count, call_time and call_memory: restarts the existing counters. The behavior is undefined for other FlagList options.

pause - For the FlagList options call_count, call_time and call_memory: pauses the existing counters. The behavior is undefined for other FlagList options.

Argument FlagList is a list of options. The following are the valid options:

global - Turn on or off call tracing for global function calls (that is, calls specifying the module explicitly). Only exported functions match and only global calls generate trace messages. This is the default if FlagList is empty.

local - Turn on or off call tracing for all types of function calls. Trace messages are sent whenever any of the specified functions are called, regardless of how they are called. If flag return_to is set for the process, a return_to message is also sent when this function returns to its caller.

meta - Turn on or off meta-tracing for all types of function calls. Trace messages are sent to the tracer whenever any of the specified functions are called.

Meta-tracing traces all processes and does not care about the process trace flags set by process/4, the trace flags are instead fixed to [call, timestamp].

The match specification function {return_trace} works with meta-trace.

call_count - Start (MatchSpec == true) or stop (MatchSpec == false) call count tracing for all types of function calls. For every function, a counter is incremented when the function is called, in any process. No process trace flags need to be activated.

If call count tracing is started while already running, the count is restarted from zero. To pause running counters, use MatchSpec == pause. Paused and running counters can be restarted from zero with MatchSpec == restart.

To read the counter value for a function, call trace:info(_, MFA, call_count).

call_time - Start (MatchSpec is true) or stops (MatchSpec is false) call time tracing for all types of function calls. For every function, a counter is incremented when the function is called and the time spent in the function is measured and accumulated in another counter. The counters are stored for each call traced process.

If call time tracing is started while already running, the count and time restart from zero. To pause running counters, use MatchSpec == pause. Paused and running counters can be restarted from zero with MatchSpec == restart.

To read the counter values, use info/3.

call_memory - Start (MatchSpec == true) or stop (MatchSpec == false) call memory tracing for all types of function calls. For every function, a counter is incremented when the function is called and the memory consumed by the function is measured and accumulated in another counter. Separate counters are stored for each call traced process.

If call memory tracing is started while already running, counters and allocations restart from zero. To pause running counters, use MatchSpec == pause. Paused and running counters can be restarted from zero with MatchSpec == restart.

To read the counter value, use info/3.

Option global cannot be combined with any of the other options, which all perform some kind of local tracing. If global tracing is specified for a set of functions, then local, meta, call_count, call_time, and call_memory tracing for the matching set of functions are disabled, and vice versa.

When disabling trace, the option must match the type of trace set on the function. That is, local tracing must be disabled with option local and global tracing with option global (or no option), and so on.

Part of a match specification cannot be changed directly. If a function has a match specification, it can be replaced with a new one. Function info/3 can be used to retrieve the existing match specification.

Returns the number of functions matching argument MFA. Zero is returned if none matched or if on_load was specified.

Fails by raising an error exception with an error reason of:

badarg - If an argument is invalid.

system_limit - If a match specification passed as argument has excessive nesting which causes scheduler stack exhaustion for the scheduler that the calling process is executing on. Scheduler stack size can be configured when starting the runtime system.

info(Session, PidPortFuncEvent, Item)

(since OTP 27.0)

-spec info(Session, PidPortFuncEvent, Item) -> Res
              when
                  Session :: session(),
                  PidPortFuncEvent ::
                      pid() |
                      port() |
                      new | new_processes | new_ports | MFA | on_load | send | 'receive' | system,
                  MFA :: {module(), atom(), arity()},
                  Item ::
                      flags | tracer | traced | match_spec | meta | meta_match_spec | call_count |
                      call_time | call_memory | all,
                  Res :: trace_info_return().

Return trace information about a port, process, function, or event.

Argument Session is the trace session to inspect as returned by session_create/3 or session_info/1.

To get information about a port or process, PidPortFuncEvent is to be a process identifier (pid), port identifier, or one of the atoms new, new_processes, or new_ports. The atom new or new_processes means that the default trace state for processes to be created is returned. The atom new_ports means that the default trace state for ports to be created is returned.

Valid Item values for ports and processes:

flags - Returns a list of atoms indicating what kind of traces is enabled for the process. The list is empty if no traces are enabled, and one or more of trace_info_flag() if traces are enabled. The order is arbitrary.

tracer - Returns the identifier for process, port, or a tuple containing the tracer module and tracer state tracing this process. If this process is not traced, the return value is [].

To get information about a function, PidPortFuncEvent is to be the three-element tuple {Module, Function, Arity} or the atom on_load. No wildcards are allowed. Returns undefined if the function does not exist or false if the function is not traced. If PidPortFuncEvent is on_load, the information returned refers to the default value for code that will be loaded.

Valid Item values for functions:

traced - Returns global if this function is traced on global function calls, local if this function is traced on local function calls (that is, local and global function calls), and false if local or global function calls are not traced.

match_spec - Returns the match specification for this function, if it has one. If the function is locally or globally traced but has no match specification defined, the returned value is [].

meta - Returns the meta-trace tracer process, port, or trace module for this function, if it has one. If the function is not meta-traced, the returned value is false. If the function is meta-traced but has once detected that the tracer process is invalid, the returned value is [].

meta_match_spec - Returns the meta-trace match specification for this function, if it has one. If the function is meta-traced but has no match specification defined, the returned value is [].

call_count - Returns the call count value for this function or true for the pseudo function on_load if call count tracing is active. Otherwise false is returned.

See also function/4.

call_time - Returns the call time values for this function or true for the pseudo function on_load if call time tracing is active. Otherwise false is returned. The call time values returned, [{Pid, Count, S, Us}], is a list of each process that executed the function and its specific counters. Count is the call count. S and Us are the accumulated call time expressed in seconds and microseconds.

See also function/4.

call_memory - Returns the accumulated number of words allocated by this function. Accumulation stops at the next memory traced function: if there are outer, middle and inner functions each allocating 3 words, but only outer is traced, it will report 9 allocated words. If outer and inner are traced, 6 words are reported for outer and 3 for inner. When function is not traced, false is returned. Returned tuple is [{Pid, Count, Words}], for each process that executed the function.

See also function/4.

all - Returns a list containing the {Item, Value} tuples for all other items, or returns false if no tracing is active for this function.

To get information about an event, PidPortFuncEvent is to be one of the atoms send or 'receive'.

One valid Item for events exists:

match_spec - Returns the match specification for this event, if it has one, or true if no match specification has been set.

To get information about monitored system events, PidPortFuncEvent is to be the atom system.

Only valid Item for system is

all - Returns a list of all monitored system events enabled by system/3.

The return value is {Item, Value}, where Value is the requested information as described earlier. If a pid for a dead process was specified, or the name of a non-existing function, Value is undefined.

port(Session, Ports, How, FlagList)

(since OTP 27.0)

-spec port(Session, Ports, How, FlagList) -> integer()
              when
                  Session :: session(),
                  Ports :: port() | all | existing | new,
                  How :: boolean(),
                  FlagList :: [trace_flag()].

Turn on or off trace flags for one or more ports.

Argument Session is the trace session to operate on as returned by session_create/3.

Ports is either a port identifier for a local port or one of the following atoms:

all - All currently existing ports and all that will be created in the future.

existing - All currently existing ports.

new - All ports that will be created in the future.

FlagList can contain any number of the following flags (the "message tags" refers to the list of trace messages):

all - Sets all trace flags except cpu_timestamp, which are in its nature different than the others.

send - Traces sending of messages.

Message tags: send and send_to_non_existing_process.

'receive' - Traces receiving of messages.

Message tags: 'receive'.

ports - Traces port-related events.

Message tags: open, closed, register, unregister, getting_linked, and getting_unlinked.

running_ports - Traces scheduling of ports.

Message tags: in and out.

timestamp, cpu_timestamp, monotonic_timestamp, strict_monotonic_timestamp - Same as for timestamps in process/4.

The tracing process receives the trace messages described in the following list. Port is the port identifier of the traced port in which the traced event has occurred. The third tuple element is the message tag.

If flag timestamp, strict_monotonic_timestamp, or monotonic_timestamp is specified, the first tuple element is trace_ts instead, and the time stamp is added as an extra element last in the message tuple. If multiple time stamp flags are passed, timestamp has precedence over strict_monotonic_timestamp, which in turn has precedence over monotonic_timestamp. All time stamp flags are remembered, so if two are passed and the one with highest precedence later is disabled, the other one becomes active.

If a match specification (applicable only for send and 'receive' tracing) contains a {message} action function with a non-boolean value, that value is added as an extra element to the message tuple either in the last position or before the timestamp (if it is present).

Trace messages:

{trace, Port, send, Msg, To} - When Port sends message Msg to process To.

{trace, Port, send_to_non_existing_process, Msg, To} - When Port sends message Msg to the non-existing process To.

{trace, Port, 'receive', Msg} - When Port receives message Msg. If Msg is set to time-out, a receive statement can have timed out, or the process received a message with the payload timeout.

{trace, Port, register, RegName} - When Port gets the name RegName registered.

{trace, Port, unregister, RegName} - When Port gets the name RegName unregistered. This is done automatically when a registered process or port exits.

{trace, Port, getting_linked, Pid2} - When Port gets linked to a process Pid2.

{trace, Port, getting_unlinked, Pid2} - When Port gets unlinked from a process Pid2.

{trace, Port, open, Pid, Driver} - When Pid opens a new port Port with the running Driver.

Driver is the name of the driver as an atom.

{trace, Port, closed, Reason} - When Port closes with Reason.

{trace, Port, in, Command | 0} - When Port is scheduled to run. Command is the first thing the port will execute, it can however run several commands before being scheduled out. On some rare occasions, the current function cannot be determined, then the last element is 0.

The possible commands are call, close, command, connect, control, flush, info, link, open, and unlink.

{trace, Port, out, Command | 0} - When Port is scheduled out. The last command run was Command. On some rare occasions, the current function cannot be determined, then the last element is 0. Command can contain the same commands as in

If the tracing process/port dies or the tracer module returns remove, the flags are silently removed.

Returns a number indicating the number of ports that matched Ports. If Ports is a port identifier, the return value is 1. If Ports is all or existing, the return value is the number of existing ports. If Ports is new, the return value is 0.

Failure: badarg if the specified arguments are not supported. For example, cpu_timestamp is not supported on all platforms.

process(Session, Procs, How, FlagList)

(since OTP 27.0)

-spec process(Session, Procs, How, FlagList) -> integer()
                 when
                     Session :: session(),
                     Procs :: pid() | all | existing | new,
                     How :: boolean(),
                     FlagList :: [trace_flag()].

Turn on or off trace flags for one or more processes.

Argument Session is the trace session to operate on as returned by session_create/3.

Argument Procs is either a process identifier (pid) for a local process or one of the following atoms:

all - All currently existing processes and all that will be created in the future.

existing - All currently existing processes.

new - All processes that will be created in the future.

Argument How is either true to turn on trace flags or false to turn them off.

Argument FlagList can contain any number of the following flags (the "message tags" refers to the list of trace messages):

all - Sets all trace flags except cpu_timestamp, which is in its nature different than the others.

send - Traces sending of messages. Limit which sent messages to trace by calling send/3.

Message tags: send and send_to_non_existing_process.

'receive' - Traces receiving of messages. Limit which received messages to trace by calling recv/3.

Message tags: 'receive'.

call - Traces certain function calls. Specify which function calls to trace by calling function/4.

Message tags: call and return_from.

silent - Used with the call trace flag. The call, return_from, and return_to trace messages are inhibited if this flag is set, but they are executed as normal if there are match specifications.

Silent mode is inhibited by executing trace:process(_, _, false, [silent|_]), or by a match specification executing the function {silent, false}.

The silent trace flag facilitates setting up a trace on many or even all processes in the system. The trace can then be activated and deactivated using the match specification function {silent,Bool}, giving a high degree of control of which functions with which arguments that trigger the trace.

Message tags: call, return_from, and return_to. Or rather, the absence of.

return_to - Used with the call trace flag. Traces the exit from call traced functions back to where the execution resumes. Only works for functions traced with option local to function/4.

The semantics is that a return_to trace message is sent when a call traced function returns or throws and exception that is caught. For tail calls, only one trace message is sent per chain of tail calls, so the properties of tail recursiveness for function calls are kept while tracing with this flag. Similar for exceptions, only one return_to trace message is sent, even if the exception passed more than one call traced function before it was caught.

Using call and return_to trace together makes it possible to know exactly in which function a process executes at any time.

To get trace messages containing return values from functions, use the {return_trace} match specification action instead.

Message tags: return_to.

procs - Traces process-related events.

Message tags: spawn, spawned, exit, register, unregister, link, unlink, getting_linked, and getting_unlinked.

running - Traces scheduling of processes.

Message tags: in and out.

exiting - Traces scheduling of exiting processes.

Message tags: in_exiting, out_exiting, and out_exited.

running_procs - Traces scheduling of processes just like running. However, this option also includes schedule events when the process executes within the context of a port without being scheduled out itself.

Message tags: in and out.

garbage_collection - Traces garbage collections of processes.

Message tags: gc_minor_start, gc_max_heap_size, and gc_minor_end.

timestamp - Includes a time stamp in all trace messages. The time stamp (Ts) has the same form as returned by erlang:now/0.

cpu_timestamp - A global trace flag for the Erlang node that makes all trace time stamps using flag timestamp to be in CPU time, not wall clock time. That is, cpu_timestamp is not be used if monotonic_timestamp or strict_monotonic_timestamp is enabled. Only allowed with Procs==all. If the host machine OS does not support high-resolution CPU time measurements, process/4 exits with badarg. Notice that most OS do not synchronize this value across cores, so be prepared that time can seem to go backwards when using this option.

monotonic_timestamp - Includes an Erlang monotonic time time stamp in all trace messages. The time stamp (Ts) has the same format and value as produced by erlang:monotonic_time(nanosecond). This flag overrides flag cpu_timestamp.

strict_monotonic_timestamp - Includes an time stamp consisting of Erlang monotonic time and a monotonically increasing integer in all trace messages. The time stamp (Ts) has the same format and value as produced by { erlang:monotonic_time(nanosecond), erlang:unique_integer([monotonic])}. This flag overrides flag cpu_timestamp.

If multiple time stamp flags are passed, timestamp has precedence over strict_monotonic_timestamp, which in turn has precedence over monotonic_timestamp. All time stamp flags are remembered, so if two are passed and the one with highest precedence later is disabled, the other one becomes active.

arity - Used with the call trace flag. {M, F, Arity} is specified instead of {M, F, Args} in call trace messages.

set_on_spawn - Makes any process created by a traced process inherit all its trace flags, including flag set_on_spawn itself.

set_on_first_spawn - Makes the first process created by a traced process inherit all its trace flags, excluding flag set_on_first_spawn itself. That is, after the first spawn is done, set_on_first_spawn will be cleared in both the spawned process and the spawning process.

If both are set, set_on_first_spawn will supersede set_on_spawn.

set_on_link - Makes any process linked by a traced process inherit all its trace flags, including flag set_on_link itself.

set_on_first_link - Makes the first process linked to by a traced process inherit all its trace flags, excluding flag set_on_first_link itself. That is, after the first link is done, set_on_first_link will be cleared in both the linked process and the linking process.

If both are set, set_on_first_link will supersede set_on_link.

The tracing process receives the trace messages described in the following list. Pid is the process identifier of the traced process in which the traced event has occurred. The third tuple element is the message tag.

If flag timestamp, strict_monotonic_timestamp, or monotonic_timestamp is specified, the first tuple element is trace_ts instead, and the time stamp is added as an extra element last in the message tuple.

If a match specification (applicable only for call, send, and 'receive' tracing) contains a {message} action function with a non-boolean value, that value is added as an extra element to the message tuple either in the last position or before the timestamp (if it is present).

Trace messages:

{trace, Pid, send, Msg, To} - When process Pid sends message Msg to process To.

{trace, Pid, send_to_non_existing_process, Msg, To} - When process Pid sends message Msg to the non-existing process To.

{trace, Pid, 'receive', Msg} - When process Pid receives message Msg. If Msg is set to time-out, a receive statement can have timed out, or the process received a message with the payload timeout.

{trace, Pid, call, {M, F, Args}} - When process Pid calls a traced function. The return values of calls are never supplied, only the call and its arguments.

Trace flag arity can be used to change the contents of this message, so that Arity is specified instead of Args.

{trace, Pid, return_to, {M, F, Arity}} - When process Pid returns to the specified function. This trace message is sent if both the flags call and return_to are set, and the function is set to be traced on local function calls. The message is only sent when returning from a chain of tail recursive function calls, where at least one call generated a call trace message (that is, the functions match specification matched, and {message, false} was not an action).

{trace, Pid, return_from, {M, F, Arity}, ReturnValue} - When Pid returns from the specified function. This trace message is sent if flag call is set, and the function has a match specification with a return_trace or exception_trace action.

{trace, Pid, exception_from, {M, F, Arity}, {Class, Value}} - When Pid exits from the specified function because of an exception. This trace message is sent if flag call is set, and the function has a match specification with an exception_trace action.

{trace, Pid, spawn, Pid2, {M, F, Args}} - When Pid spawns a new process Pid2 with the specified function call as entry point.

Args is supposed to be the argument list, but can be any term if the spawn is erroneous.

{trace, Pid, spawned, Pid2, {M, F, Args}} - When Pid is spawned by process Pid2 with the specified function call as entry point.

Args is supposed to be the argument list, but can be any term if the spawn is erroneous.

{trace, Pid, exit, Reason} - When Pid exits with reason Reason.

{trace, Pid, register, RegName} - When process Pid gets the name RegName registered.

{trace, Pid, unregister, RegName} - When process Pid gets the name RegName unregistered. This is done automatically when a registered process or port exits.

{trace, Pid, link, Pid2} - When Pid links to a process Pid2.

{trace, Pid, unlink, Pid2} - When Pid removes the link from a process Pid2.

{trace, Pid, getting_linked, Pid2} - When Pid gets linked to a process Pid2.

{trace, Pid, getting_unlinked, Pid2} - When Pid gets unlinked from a process Pid2.

{trace, Port, open, Pid, Driver} - When Pid opens a new port Port with the running Driver.

Driver is the name of the driver as an atom.

{trace, Pid, in | in_exiting, {M, F, Arity} | 0} When Pid is scheduled to run. The process runs in function {M, F, Arity}. On some rare occasions, the current function cannot be determined, then the last element is 0.

{trace, Pid, out | out_exiting | out_exited, {M, F, Arity} | 0} When Pid is scheduled out. The process was running in function {M, F, Arity}. On some rare occasions, the current function cannot be determined, then the last element is 0.

{trace, Pid, gc_minor_start, Info} - Sent when a garbage collection of the young generation is about to be started. Info is a list of two-element tuples, where the first element is a key, and the second is the value. Do not depend on any order of the tuples. The following keys are defined:

heap_size - The size of the used part of the heap.

heap_block_size - The size of the memory block used for storing the heap and the stack.

old_heap_size - The size of the used part of the old heap.

old_heap_block_size - The size of the memory block used for storing the old heap.

stack_size - The size of the stack.

recent_size - The size of the data that survived the previous garbage collection.

mbuf_size - The combined size of message buffers associated with the process.

bin_vheap_size - The total size of unique off-heap binaries referenced from the process heap.

bin_vheap_block_size - The total size of binaries allowed in the virtual heap in the process before doing a garbage collection.

bin_old_vheap_size - The total size of unique off-heap binaries referenced from the process old heap.

bin_old_vheap_block_size - The total size of binaries allowed in the virtual old heap in the process before doing a garbage collection.

wordsize - For the gc_minor_start event it is the size of the need that triggered the GC. For the corresponding gc_minor_end event it is the size of reclaimed memory = start heap_size - end heap_size.

All sizes are in words.

{trace, Pid, gc_max_heap_size, Info} - Sent when the max_heap_size is reached during garbage collection. Info contains the same kind of list as in message gc_start, but the sizes reflect the sizes that triggered max_heap_size to be reached.

{trace, Pid, gc_minor_end, Info} - Sent when young garbage collection is finished. Info contains the same kind of list as in message gc_minor_start, but the sizes reflect the new sizes after garbage collection.

{trace, Pid, gc_major_start, Info} - Sent when fullsweep garbage collection is about to be started. Info contains the same kind of list as in message gc_minor_start.

{trace, Pid, gc_major_end, Info} - Sent when fullsweep garbage collection is finished. Info contains the same kind of list as in message gc_minor_start, but the sizes reflect the new sizes after a fullsweep garbage collection.

If the tracing process dies or the tracer module returns remove, the flags are silently removed.

Returns a number indicating the number of processes that matched Procs. If Procs is a process identifier, the return value is 1. If Procs is all or existing, the return value is the number of processes running. If Procs is new, the return value is 0.

Failure: badarg if the specified arguments are not supported. For example, cpu_timestamp is not supported on all platforms.

recv(Session, MatchSpec, FlagList)

(since OTP 27.0)

-spec recv(Session, MatchSpec, FlagList) -> non_neg_integer()
              when Session :: session(), MatchSpec :: trace_match_spec() | boolean(), FlagList :: [].

Set trace pattern for message receiving.

Must be combined with process/4 or port/4 to set the 'receive' trace flag for one or more processes or ports.

Argument Session is the trace session to operate on as returned by session_create/3.

The default value for the receive trace pattern in each session is true. That is, all messages received by processes having 'receive' trace enabled will be traced. Use this function to limit traced 'receive' events based on the message content, the sender, and/or the receiver.

Argument MatchSpec can take the following forms:

MatchExpression - A match specification. The matching is done on the list [Node, Sender, Msg]. Node is the node name of the sender. Sender is the process or port identity of the sender, or the atom undefined if the sender is not known (which can be the case for remote senders). Msg is the message term. The pid of the receiving process can be accessed with the guard function self/0. An empty list is the same as true. For more information, see section Match Specifications in Erlang in the User's Guide for the ERTS application.

true - Enable tracing for all received messages (to 'receive' traced processes). Any match specification is removed. This is the default.

false - Disable tracing for all received messages. Any match specification is removed.

Argument FlagList must be [] for receive tracing.

The return value is always 1.

Examples:

Only trace messages from a specific process Pid:

> trace:recv(Session, [{['_',Pid, '_'],[],[]}], []).
1

Only trace messages matching {reply, _}:

> trace:recv(Session, [{['_','_', {reply,'_'}],[],[]}], []).
1

Only trace messages from other nodes:

> trace:recv(Session, [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).
1

Note

A match specification for 'receive' trace can use all guard and body functions except caller, is_seq_trace, get_seq_token, set_seq_token, enable_trace, disable_trace, trace, silent, and process_dump.

Fails by raising an error exception with an error reason of:

badarg - If an argument is invalid.

system_limit - If a match specification passed as argument has excessive nesting which causes scheduler stack exhaustion for the scheduler that the calling process is executing on. Scheduler stack size can be configured when starting the runtime system.

send(Session, MatchSpec, FlagList)

(since OTP 27.0)

-spec send(Session, MatchSpec, FlagList) -> non_neg_integer()
              when Session :: session(), MatchSpec :: trace_match_spec() | boolean(), FlagList :: [].

Set trace pattern for message sending.

Must be combined with process/4 or port/4 to set the send trace flag for one or more processes or ports.

Argument Session is the trace session to operate on as returned by session_create/3.

The default value for the send trace pattern in each session is true. That is, all messages sent from processes having send trace enabled will be traced. Use this function to limit traced send events based on the message content, the sender, and/or the receiver.

Argument MatchSpec can take the following forms:

MatchExpression - A match specification. The matching is done on the list [Receiver, Msg]. Receiver is the process or port identity of the receiver and Msg is the message term. The pid of the sending process can be accessed with the guard function self/0. An empty list is the same as true. For more information, see section Match Specifications in Erlang in the User's Guide for the ERTS application.

true - Enable tracing for all sent messages (from send traced processes). Any match specification is removed.

false - Disable tracing for all sent messages. Any match specification is removed.

Argument FlagList must be [].

The return value is always 1.

Examples:

Only trace messages to a specific process Pid:

> trace:send(Session, [{[Pid, '_'],[],[]}], []).
1

Only trace messages matching {reply, _}:

> trace:send(Session, [{['_', {reply,'_'}],[],[]}], []).
1

Only trace messages sent to the sender itself:

> trace:send(Session, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).
1

Only trace messages sent to other nodes:

> trace:send(Session, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).
1

Note

A match specification for send trace can use all guard and body functions except caller.

Fails by raising an error exception with an error reason of:

badarg - If an argument is invalid.

system_limit - If a match specification passed as argument has excessive nesting which causes scheduler stack exhaustion for the scheduler that the calling process is executing on. Scheduler stack size can be configured when starting the runtime system.

session_create(Name, Tracer, Opts)

(since OTP 27.0)

-spec session_create(Name, Tracer, Opts) -> session()
                        when Name :: atom(), Tracer :: pid() | port() | {module(), term()}, Opts :: [].

Create a new trace session.

Argument Name is an atom name for the session. It will be returned when inspecting with session_info/1.

Argument Tracer specifies the consumer of all trace events for the session. It can be an identifier of a local process or port to receive all trace messages.

Tracer can also be a tuple {TracerModule, TracerState} for a tracer module to be called instead of sending a trace message. The tracer module can then ignore or change the trace message. For more details on how to write a tracer module, see module erl_tracer.

Argument Opts must be [].

Returns an opaque handle to the trace session. The handle will keep the session alive. If the handle is dropped and garbage collected, the session will be destroyed and cleaned up as if session_destroy/1 was called.

session_destroy(Session)

(since OTP 27.0)

-spec session_destroy(Session) -> true | false when Session :: session().

Destroy a trace session and cleanup all its settings on processes, ports, and functions.

The only things not cleaned up are trace messages that have already been sent.

Returns true if the session was active. Returns false if the session had already been destroyed by either an earler call to this function or the garbage collector.

session_info(PidPortFuncEvent)

(since OTP 27.0)

-spec session_info(PidPortFuncEvent) -> Res
                      when
                          PidPortFuncEvent ::
                              all |
                              pid() |
                              port() |
                              new | new_processes | new_ports | MFA | on_load | send | 'receive',
                          MFA :: {module(), atom(), arity()},
                          Res :: undefined | [session_weak_ref()].

Return which trace sessions that affect a port, process, function, or event.

Argument all returns all active trace sessions that exists on the node.

Returns a list of weak session handles or undefined if the process/port/function does not exists.

system(Session, Event, Value)

(since OTP 28.0)

-spec system(Session :: session(), Event :: system_event(), Value :: system_value()) -> ok.

Enable/disable monitoring of system events.

Argument Session is the trace session to operate on as returned by session_create/3.

Argument Event is an atom describing the kind of system event to monitor. To enable monitoring argument Value is, depending on event, either a limit of that event or the atom true. To disable monitoring pass Value as the atom false.

When a monitored system event happens, a message is sent to the session tracer. The session tracer must be a process otherwise the function call will fail.

The following Events with Values can be monitored:

long_gc, Time - If a garbage collection in the system takes at least Time wall clock milliseconds, a message {monitor, GcPid, long_gc, Info} is sent. GcPid is the pid that was garbage collected. Info is a list of two-element tuples describing the result of the garbage collection.

One of the tuples is {timeout, GcTime}, where GcTime is the time for the garbage collection in milliseconds. The other tuples are tagged with heap_size, heap_block_size, stack_size, mbuf_size, old_heap_size, and old_heap_block_size. These tuples are explained in the description of trace message gc_minor_start (see trace:process/4). New tuples can be added, and the order of the tuples in the Info list can be changed at any time without prior notice.

long_message_queue, {Disable, Enable} - If the number of messages in the message queue of a process reach Enable, a message {monitor, Pid, long_message_queue, Long} is sent. Pid is the process identifier of the process that got a long message queue and Long will equal true indicating that it is in a long message queue state. No more long_message_queue monitor messages will be sent due to the process identified by Pid until its message queue length falls down to a length of Disable length. When this happens, a long_message_queue monitor message with Long equal to false will be sent indicating that the process is no longer in a long message queue state. As of this, if the message queue length should again reach Enable length, a new long_message_queue monitor message with Long set to true will again be sent. That is, a long_message_queue monitor message is sent when a process enters or leaves a long message queue state where these state changes are defined by the Enable and Disable parameters.

Enable must be an integer larger than zero. Disable must be an integer larger than or equal to zero and smaller than Enable. If the above is not satisfied the operation will fail with a badarg error exception. You are recommended to use a much smaller value for Disable length than Enable length in order not to be flooded with long_message_queue monitor messages.

long_schedule, Time - If a process or port in the system runs uninterrupted for at least Time wall clock milliseconds, a message {monitor, PidOrPort, long_schedule, Info} is sent. PidOrPort is the process or port that was running. Info is a list of two-element tuples describing the event.

If a pid/0, the tuples {timeout, Millis}, {in, Location}, and {out, Location} are present, where Location is either an MFA ({Module, Function, Arity}) describing the function where the process was scheduled in/out, or the atom undefined.

If a port/0, the tuples {timeout, Millis} and {port_op,Op} are present. Op is one of proc_sig, timeout, input, output, event, or dist_cmd, depending on which driver callback was executing.

proc_sig is an internal operation and is never to appear, while the others represent the corresponding driver callbacks timeout, ready_input, ready_output, event, and outputv (when the port is used by distribution). Value Millis in tuple timeout informs about the uninterrupted execution time of the process or port, which always is equal to or higher than the Time value supplied when starting the trace. New tuples can be added to the Info list in a future release. The order of the tuples in the list can be changed at any time without prior notice.

This can be used to detect problems with NIFs or drivers that take too long to execute. 1 ms is considered a good maximum time for a driver callback or a NIF. However, a time-sharing system is usually to consider everything < 100 ms as "possible" and fairly "normal". However, longer schedule times can indicate swapping or a misbehaving NIF/driver. Misbehaving NIFs and drivers can cause bad resource utilization and bad overall system performance.

large_heap, Size - If a garbage collection in the system results in the allocated size of a heap being at least Size words, a message {monitor, GcPid, large_heap, Info} is sent. GcPid and Info are the same as for long_gc described above, except that the tuple tagged with timeout is not present.

The monitor message is sent if the sum of the sizes of all memory blocks allocated for all heap generations after a garbage collection is equal to or higher than Size.

When a process is killed by max_heap_size, it is killed before the garbage collection is complete and thus no large heap message is sent.

busy_port, true - If a process in the system gets suspended because it sends to a busy port, a message {monitor, SusPid, busy_port, Port} is sent. SusPid is the pid that got suspended when sending to Port.

busy_dist_port, true If a process in the system gets suspended because it sends to a process on a remote node whose inter-node communication was handled by a busy port, a message {monitor, SusPid, busy_dist_port, Port} is sent. SusPid is the pid that got suspended when sending through the inter-node communication port Port.

To disable system monitoring of a event pass the value as false. There are no other special values (like zero) to disable monitoring of an event. Some of the events have an unspecified minimum value. Lower values will be adjusted to the minimum value. For example, it is currently not possible to monitor all garbage collections with {long_gc, 0}.

Note

If the session tracer process gets so large that it itself starts to cause system monitor messages when garbage collecting, the messages enlarge the process message queue and probably make the problem worse.

Keep the tracer process neat and do not set the system monitor limits too tight.

Failures:

badarg - If the session tracer is not a local process.