aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel')
-rw-r--r--lib/kernel/doc/src/Makefile1
-rw-r--r--lib/kernel/doc/src/application.xml9
-rw-r--r--lib/kernel/doc/src/error_handler.xml38
-rw-r--r--lib/kernel/doc/src/file.xml40
-rw-r--r--lib/kernel/doc/src/heart.xml35
-rw-r--r--lib/kernel/doc/src/inet.xml195
-rw-r--r--lib/kernel/doc/src/notes.xml38
-rw-r--r--lib/kernel/doc/src/packages.xml208
-rw-r--r--lib/kernel/doc/src/ref_man.xml1
-rw-r--r--lib/kernel/src/Makefile11
-rw-r--r--lib/kernel/src/application.erl16
-rw-r--r--lib/kernel/src/application_controller.erl2
-rw-r--r--lib/kernel/src/code.erl6
-rw-r--r--lib/kernel/src/code_server.erl9
-rw-r--r--lib/kernel/src/disk_log.erl2
-rw-r--r--lib/kernel/src/dist_util.erl3
-rw-r--r--lib/kernel/src/erl_ddll.erl4
-rw-r--r--lib/kernel/src/error_handler.erl53
-rw-r--r--lib/kernel/src/file.erl21
-rw-r--r--lib/kernel/src/file_io_server.erl22
-rw-r--r--lib/kernel/src/gen_sctp.erl2
-rw-r--r--lib/kernel/src/gen_tcp.erl10
-rw-r--r--lib/kernel/src/gen_udp.erl6
-rw-r--r--lib/kernel/src/group.erl8
-rw-r--r--lib/kernel/src/heart.erl5
-rw-r--r--lib/kernel/src/inet.erl64
-rw-r--r--lib/kernel/src/inet_int.hrl5
-rw-r--r--lib/kernel/src/inet_parse.erl13
-rw-r--r--lib/kernel/src/kernel.app.src1
-rw-r--r--lib/kernel/src/packages.erl158
-rw-r--r--lib/kernel/src/pg2.erl4
-rw-r--r--lib/kernel/src/ram_file.erl7
-rw-r--r--lib/kernel/src/rpc.erl2
-rw-r--r--lib/kernel/src/user.erl190
-rw-r--r--lib/kernel/src/wrap_log_reader.erl4
-rw-r--r--lib/kernel/test/Makefile2
-rw-r--r--lib/kernel/test/application_SUITE.erl13
-rw-r--r--lib/kernel/test/code_SUITE.erl4
-rw-r--r--lib/kernel/test/error_handler_SUITE.erl68
-rw-r--r--lib/kernel/test/error_logger_warn_SUITE.erl4
-rw-r--r--lib/kernel/test/file_SUITE.erl72
-rw-r--r--lib/kernel/test/file_name_SUITE.erl165
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl50
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl5
-rw-r--r--lib/kernel/test/global_SUITE.erl158
-rw-r--r--lib/kernel/test/heart_SUITE.erl430
-rw-r--r--lib/kernel/test/ignore_cores.erl158
-rw-r--r--lib/kernel/test/inet_SUITE.erl21
-rw-r--r--lib/kernel/test/inet_sockopt_SUITE.erl155
-rw-r--r--lib/kernel/test/interactive_shell_SUITE.erl215
-rw-r--r--lib/kernel/test/kernel.cover2
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl74
-rw-r--r--lib/kernel/test/ram_file_SUITE.erl17
-rw-r--r--lib/kernel/test/wrap_log_reader_SUITE.erl4
54 files changed, 1767 insertions, 1043 deletions
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile
index 5e04bff0c1..de3ca1e176 100644
--- a/lib/kernel/doc/src/Makefile
+++ b/lib/kernel/doc/src/Makefile
@@ -58,7 +58,6 @@ XML_REF3_FILES = application.xml \
net_adm.xml \
net_kernel.xml \
os.xml \
- packages.xml \
pg2.xml \
rpc.xml \
seq_trace.xml \
diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml
index 51a3311ec2..9f19efc793 100644
--- a/lib/kernel/doc/src/application.xml
+++ b/lib/kernel/doc/src/application.xml
@@ -121,6 +121,15 @@
</desc>
</func>
<func>
+ <name name="get_env" arity="3"/>
+ <fsummary>Get the value of a configuration parameter using a default</fsummary>
+ <desc>
+ <p>Works like <seealso marker="#get_env/2">get_env/2</seealso> but returns
+ <c><anno>Def</anno></c> value when configuration parameter
+ <c><anno>Par</anno></c> does not exist.</p>
+ </desc>
+ </func>
+ <func>
<name name="get_key" arity="1"/>
<name name="get_key" arity="2"/>
<fsummary>Get the value of an application specification key</fsummary>
diff --git a/lib/kernel/doc/src/error_handler.xml b/lib/kernel/doc/src/error_handler.xml
index acbf9a2c6e..610b65f0a2 100644
--- a/lib/kernel/doc/src/error_handler.xml
+++ b/lib/kernel/doc/src/error_handler.xml
@@ -43,19 +43,39 @@
A (possibly empty) list of arguments <c>Arg1,..,ArgN</c>
</type_desc>
<desc>
- <p>This function is evaluated if a call is made to
+ <p>This function is called by the run-time system if a call is made to
<c><anno>Module</anno>:<anno>Function</anno>(Arg1,.., ArgN)</c> and
<c><anno>Module</anno>:<anno>Function</anno>/N</c> is undefined. Note that
<c>undefined_function/3</c> is evaluated inside the process
making the original call.</p>
- <p>If <c><anno>Module</anno></c> is interpreted, the interpreter is invoked
- and the return value of the interpreted
- <c><anno>Function</anno>(Arg1,.., ArgN)</c> call is returned.</p>
- <p>Otherwise, it returns, if possible, the value of
- <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> after an attempt has been
- made to autoload <c><anno>Module</anno></c>. If this is not possible, the
- call to <c><anno>Module</anno>:<anno>Function</anno>(Arg1,.., ArgN)</c> fails with
- exit reason <c>undef</c>.</p>
+
+ <p>This function will first attempt to autoload
+ <c><anno>Module</anno></c>. If that is not possible,
+ an <c>undef</c> exception will be raised.</p>
+
+ <p>If it was possible to load <c><anno>Module</anno></c>
+ and the function <c><anno>Function</anno>/N</c> is exported,
+ it will be called.</p>
+
+ <p>Otherwise, if the function <c>'$handle_undefined_function'/2</c>
+ is exported, it will be called as
+ <c>'$handle_undefined_function'(</c><anno>Function</anno>,
+ <anno>Args</anno>).
+ </p>
+ <p>Otherwise an <c>undef</c> exception will be raised.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="raise_undef_exception" arity="3"/>
+ <fsummary>Raise an undef exception</fsummary>
+ <type_desc variable="Args">
+ A (possibly empty) list of arguments <c>Arg1,..,ArgN</c>
+ </type_desc>
+ <desc>
+ <p>Raise an <c>undef</c> exception with a stacktrace indicating
+ that <c><anno>Module</anno>:<anno>Function</anno>/N</c> is
+ undefined.
+ </p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index b2a259080d..e30ade1bd2 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -110,7 +110,7 @@
<desc>
<p>As returned by
<seealso marker="#open/2">file:open/2</seealso>,
- a process handling IO protocols.</p>
+ a process handling I/O-protocols.</p>
</desc>
</datatype>
<datatype>
@@ -170,6 +170,18 @@
</desc>
</func>
<func>
+ <name name="allocate" arity="3"/>
+ <fsummary>Allocate file space</fsummary>
+ <desc>
+ <p><c>allocate/3</c> can be used to preallocate space for a file.</p>
+ <p>This function only succeeds in platforms that implement this
+ feature. When it succeeds, space is preallocated for the file but
+ the file size might not be updated. This behaviour depends on the
+ preallocation implementation. To guarantee the file size is updated
+ one must truncate the file to the new size.</p>
+ </desc>
+ </func>
+ <func>
<name name="change_group" arity="2"/>
<fsummary>Change group of a file</fsummary>
<desc>
@@ -261,6 +273,9 @@
{person, "pelle", 30}.</code>
<pre>1> <input>file:consult("f.txt").</input>
{ok,[{person,"kalle",25},{person,"pelle",30}]}</pre>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
@@ -399,6 +414,9 @@
of the error.</p>
</item>
</taglist>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
@@ -610,7 +628,7 @@
<name name="open" arity="2"/>
<fsummary>Open a file</fsummary>
<desc>
- <p>Opens the file <c><anno>Filename</anno></c> in the mode determined
+ <p>Opens the file <c><anno>File</anno></c> in the mode determined
by <c><anno>Modes</anno></c>, which may contain one or more of the
following items:</p>
<taglist>
@@ -767,6 +785,10 @@
<p>The Encoding can be changed for a file "on the fly" by using the <seealso marker="stdlib:io#setopts/2">io:setopts/2</seealso> function, why a file can be analyzed in latin1 encoding for i.e. a BOM, positioned beyond the BOM and then be set for the right encoding before further reading.See the <seealso marker="stdlib:unicode">unicode(3)</seealso> module for functions identifying BOM's.</p>
<p>This option is not allowed on <c>raw</c> files.</p>
</item>
+ <tag><c>ram</c></tag>
+ <item>
+ <p><c>File</c> must be <c>iodata()</c>. Returns an <c>fd()</c> which lets the <c>file</c> module operate on the data in-memory as if it is a file.</p>
+ </item>
</taglist>
<p>Returns:</p>
<taglist>
@@ -861,6 +883,9 @@
the error.</p>
</item>
</taglist>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
@@ -902,6 +927,9 @@
of the error.</p>
</item>
</taglist>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
@@ -971,7 +999,10 @@
of the error.</p>
</item>
</taglist>
- </desc>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
+ </desc>
</func>
<func>
<name name="path_script" arity="3"/>
@@ -1502,6 +1533,9 @@
of the error.</p>
</item>
</taglist>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index 26d1e27822..2856d84dcf 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -71,6 +71,39 @@
timeout and try to reboot the system. This can happen, for
example, if the system clock is adjusted automatically by use of
NTP (Network Time Protocol).</p>
+
+ <p> If a crash occurs, an <c><![CDATA[erl_crash.dump]]></c> will <em>not</em> be written
+ unless the environment variable <c><![CDATA[ERL_CRASH_DUMP_SECONDS]]></c> is set.
+ </p>
+
+ <pre>
+% <input>erl -heart -env ERL_CRASH_DUMP_SECONDS 10 ...</input></pre>
+ <p>
+ Furthermore, <c><![CDATA[ERL_CRASH_DUMP_SECONDS]]></c> has the following behaviour on
+ <c>heart</c>:
+ </p>
+ <taglist>
+ <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c></tag>
+ <item><p>
+ Suppresses the writing a crash dump file entirely,
+ thus rebooting the runtime system immediately.
+ This is the same as not setting the environment variable.
+ </p>
+ </item>
+ <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c></tag>
+ <item><p> Setting the environment variable to a negative value will not reboot
+ the runtime system until the crash dump file has been completly written.
+ </p>
+ </item>
+ <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=S]]></c></tag>
+ <item><p>
+ Heart will wait for <c>S</c> seconds to let the crash dump file be written.
+ After <c>S</c> seconds <c>heart</c> will reboot the runtime system regardless of
+ the crash dump file has been written or not.
+ </p>
+ </item>
+ </taglist>
+
<p>In the following descriptions, all function fails with reason
<c>badarg</c> if <c>heart</c> is not started.</p>
</description>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index 32b4a429dd..3d929a772e 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -323,8 +323,11 @@ fe80::204:acff:fe17:bf38
<type name="stat_option"/>
<desc>
<p>Gets one or more statistic options for a socket.</p>
+
<p><c>getstat(<anno>Socket</anno>)</c> is equivalent to
- <c>getstat(<anno>Socket</anno>,&nbsp;[recv_avg,&nbsp;recv_cnt,&nbsp;recv_dvi,&nbsp;recv_max,&nbsp;recv_oct,&nbsp;send_avg,&nbsp;send_cnt,&nbsp;send_dvi,&nbsp;send_max,&nbsp;send_oct])</c></p>
+ <c>getstat(<anno>Socket</anno>, [recv_avg, recv_cnt, recv_dvi,
+ recv_max, recv_oct, send_avg, send_cnt, send_dvi, send_max,
+ send_oct])</c>.</p>
<p>The following options are available:</p>
<taglist>
<tag><c>recv_avg</c></tag>
@@ -371,7 +374,51 @@ fe80::204:acff:fe17:bf38
</taglist>
</desc>
</func>
-
+ <func>
+ <name name="parse_ipv4_address" arity="1" />
+ <fsummary>Parse an IPv4 address</fsummary>
+ <desc>
+ <p>Parses an IPv4 address string and returns an <a href="#type-ip4_address">ip4_address()</a>.
+ Accepts a shortened IPv4 shortened address string.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="parse_ipv4strict_address" arity="1" />
+ <fsummary>Parse an IPv4 address strict.</fsummary>
+ <desc>
+ <p>Parses an IPv4 address string containing four fields, i.e <b>not</b> shortened, and returns an <a href="#type-ip4_adress">ip4_address()</a>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="parse_ipv6_address" arity="1" />
+ <fsummary>Parse an IPv6 address</fsummary>
+ <desc>
+ <p>Parses an IPv6 address string and returns an <a href="#type-ip6_address">ip6_address()</a>.
+ If an IPv4 address string is passed, an IPv4-mapped IPv6 address is returned.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="parse_ipv6strict_address" arity="1" />
+ <fsummary>Parse an IPv6 address strict.</fsummary>
+ <desc>
+ <p>Parses an IPv6 address string and returns an <a href="#type-ip6_address">ip6_address()</a>.
+ Does <b>not</b> accept IPv4 adresses.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="parse_address" arity="1" />
+ <fsummary>Parse an IPv4 or IPv6 address.</fsummary>
+ <desc>
+ <p>Parses an IPv4 or IPv6 address string and returns an <a href="#type-ip4_address">ip4_address()</a> or <a href="#type-ip6_address">ip6_address()</a>. Accepts a shortened IPv4 address string.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="parse_strict_address" arity="1" />
+ <fsummary>Parse an IPv4 or IPv6 address strict.</fsummary>
+ <desc>
+ <p>Parses an IPv4 or IPv6 address string and returns an <a href="#type-ip4_address">ip4_address()</a> or <a href="#type-ip6_adress">ip6_address()</a>. Does <b>not</b> accept a shortened IPv4 address string.</p>
+ </desc>
+ </func>
<func>
<name name="peername" arity="1"/>
<fsummary>Return the address and port for the other end of a connection</fsummary>
@@ -512,13 +559,100 @@ fe80::204:acff:fe17:bf38
<c>[Byte1,Byte2|Binary]</c>.</p>
</item>
- <tag><c>{high_watermark, Size}</c></tag>
- <item> <p>
- Sender is forced busy if sent and enqueued data
- reaches the highwater mark.
- <br /> Default: 8192 kB.
- </p>
- </item>
+ <tag><c>{high_msgq_watermark, Size}</c> (TCP/IP sockets)</tag>
+ <item>
+ <p>The socket message queue will be set into a busy
+ state when the amount of data queued on the message
+ queue reaches this limit. Note that this limit only
+ concerns data that have not yet reached the ERTS internal
+ socket implementation. Default value used is 8 kB.</p>
+ <p>Senders of data to the socket will be suspended if
+ either the socket message queue is busy, or the socket
+ itself is busy.</p>
+ <p>For more information see the <c>low_msgq_watermark</c>,
+ <c>high_watermark</c>, and <c>low_watermark</c> options.</p>
+ <p>Note that distribution sockets will disable the use of
+ <c>high_msgq_watermark</c> and <c>low_msgq_watermark</c>,
+ and will instead use the
+ <seealso marker="erts:erlang#system_info_dist_buf_busy_limit">distribution
+ buffer busy limit</seealso> which is a similar feature.</p>
+ </item>
+
+ <tag><c>{high_watermark, Size}</c> (TCP/IP sockets)</tag>
+ <item>
+ <p>The socket will be set into a busy state when the amount
+ of data queued internally by the ERTS socket implementation
+ reaches this limit. Default value used is 8 kB.</p>
+ <p>Senders of data to the socket will be suspended if
+ either the socket message queue is busy, or the socket
+ itself is busy.</p>
+ <p>For more information see the <c>low_watermark</c>,
+ <c>high_msgq_watermark</c>, and <c>low_msqg_watermark</c>
+ options.</p>
+ </item>
+
+ <tag><c>{ipv6_v6only, Boolean}</c></tag>
+ <item>
+ <p>
+ Restricts the socket to only use IPv6, prohibiting any
+ IPv4 connections. This is only applicable for
+ IPv6 sockets (option <c>inet6</c>).
+ </p>
+ <p>
+ On most platforms this option has to be set on the socket
+ before associating it to an address. Therefore it is only
+ reasonable to give it when creating the socket and not
+ to use it when calling the function
+ (<seealso marker="#setopts/2">setopts/2</seealso>)
+ containing this description.
+ </p>
+ <p>
+ The behaviour of a socket with this socket option set to
+ <c>true</c> is becoming 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
+ <c>{ipv6_v6only,false}</c> to override the recommended
+ system default value),
+ forbidden by OpenBSD (the supported GENERIC kernel)
+ and impossible on Windows (that has separate
+ IPv4 and IPv6 protocol stacks). Most Linux distros
+ still have a system default value of <c>false</c>.
+ This policy shift among operating systems towards
+ separating IPv6 from IPv4 traffic has evolved since
+ it gradually proved hard and complicated to get
+ a dual stack implementation correct and secure.
+ </p>
+ <p>
+ On some platforms the only allowed value for this option
+ is <c>true</c>, e.g. OpenBSD and Windows. Trying to set
+ this option to <c>false</c> when creating the socket
+ will in this case fail.
+ </p>
+ <p>
+ Setting this option on platforms where it does not exist
+ is ignored and getting this option with
+ <seealso marker="#getopts/2">getopts/2</seealso>
+ returns no value i.e the returned list will not contain an
+ <c>{ipv6_v6only,_}</c> tuple. On Windows the option acually
+ does not exist, but it is emulated as being a
+ read-only option with the value <c>true</c>.
+ </p>
+ <p>
+ So it boils down to that setting this option to <c>true</c>
+ when creating a socket will never fail except possibly
+ (at the time of this writing) on a platform where you
+ have customized the kernel to only allow <c>false</c>,
+ which might be doable (but weird) on e.g. OpenBSD.
+ </p>
+ <p>
+ If you read back the option value using
+ <seealso marker="#getopts/2">getopts/2</seealso>
+ and get no value the option does not exist in the host OS
+ and all bets are off regarding the behaviour of both
+ an IPv6 and an IPv4 socket listening on the same port
+ as well as for an IPv6 socket getting IPv4 traffic.
+ </p>
+ </item>
<tag><c>{keepalive, Boolean}</c>(TCP/IP sockets)</tag>
<item>
@@ -540,14 +674,41 @@ fe80::204:acff:fe17:bf38
the flushing time-out in seconds.</p>
</item>
- <tag><c>{low_watermark, Size}</c></tag>
- <item> <p>
- If the port has reached its <c>high_watermark</c> it will
- force busy onto senders. When the port data queue reaches the
- <c>low_watermark</c> callers are no longer forced busy.
- <br /> Default: 4096 kB.
- </p>
- </item>
+ <tag><c>{low_msgq_watermark, Size}</c> (TCP/IP sockets)</tag>
+ <item>
+ <p>If the socket message queue is in a busy state, the
+ socket message queue will be set in a not busy state when
+ the amount of data queued in the message queue falls
+ below this limit. Note that this limit only concerns data
+ that have not yet reached the ERTS internal socket
+ implementation. Default value used is 4 kB.</p>
+ <p>Senders that have been suspended due to either a
+ busy message queue or a busy socket, will be resumed
+ when neither the socket message queue, nor the socket
+ are busy.</p>
+ <p>For more information see the <c>high_msgq_watermark</c>,
+ <c>high_watermark</c>, and <c>low_watermark</c> options.</p>
+ <p>Note that distribution sockets will disable the use of
+ <c>high_msgq_watermark</c> and <c>low_msgq_watermark</c>,
+ and will instead use the
+ <seealso marker="erts:erlang#system_info_dist_buf_busy_limit">distribution
+ buffer busy limit</seealso> which is a similar feature.</p>
+ </item>
+
+ <tag><c>{low_watermark, Size}</c> (TCP/IP sockets)</tag>
+ <item>
+ <p>If the socket is in a busy state, the socket will
+ be set in a not busy state when the amount of data
+ queued internally by the ERTS socket implementation
+ falls below this limit. Default value used is 4 kB.</p>
+ <p>Senders that have been suspended due to either a
+ busy message queue or a busy socket, will be resumed
+ when neither the socket message queue, nor the socket
+ are busy.</p>
+ <p>For more information see the <c>high_watermark</c>,
+ <c>high_msgq_watermark</c>, and <c>low_msgq_watermark</c>
+ options.</p>
+ </item>
<tag><c>{mode, Mode :: binary | list}</c></tag>
<item>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index 8e911a406b..78bc533464 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -30,6 +30,44 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 2.15.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Ensure 'erl_crash.dump' when asked for it. This will
+ change erl_crash.dump behaviour.</p>
+ <p>
+ * Not setting ERL_CRASH_DUMP_SECONDS will now terminate
+ beam immediately on a crash without writing a crash dump
+ file.</p>
+ <p>
+ * 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.</p>
+ <p>
+ * Setting ERL_CRASH_DUMP_SECONDS to a negative value will
+ let the beam wait indefinitely on the crash dump file
+ being written.</p>
+ <p>
+ * Setting ERL_CRASH_DUMP_SECONDS to a positive value will
+ let the beam wait that many seconds on the crash dump
+ file being written.</p>
+ <p>
+ A positive value will set an alarm/timeout for restart
+ both in beam and in heart if heart is running.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-10422 Aux Id: kunagi-250 [161] </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 2.15.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/doc/src/packages.xml b/lib/kernel/doc/src/packages.xml
deleted file mode 100644
index 8a82b91a90..0000000000
--- a/lib/kernel/doc/src/packages.xml
+++ /dev/null
@@ -1,208 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2004</year><year>2012</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- </legalnotice>
-
- <title>packages</title>
- <prepared>Kenneth Lundin</prepared>
- <responsible>Kenneth Lundin</responsible>
- <docno>1</docno>
- <approved>Kenneth Lundin</approved>
- <checked></checked>
- <date>2004-09-07</date>
- <rev>A</rev>
- <file>packages.sgml</file>
- </header>
- <module>packages</module>
- <modulesummary>Packages in Erlang</modulesummary>
- <description>
- <warning><p>
- Packages has since it was introduced more than 5 years ago been an
- experimental feature. Use it at your own risk, we do not
- actively maintain and develop this feature. It might however be
- supported some
- day.
- </p>
- <p>
- In spite of this packages work quite well, but there are some
- known issues in tools and other parts where packages don't work well.
- </p>
- </warning>
- <p><em>Introduction</em></p>
- <p>Packages are simply namespaces for modules.
- All old Erlang modules automatically belong to the top level
- ("empty-string") namespace, and do not need any changes.</p>
- <p>The full name of a packaged module is written as e.g.
- "<c>fee.fie.foe.foo</c>",
- i.e., as atoms separated by periods,
- where the package name is the part up to
- but not including the last period;
- in this case "<c>fee.fie.foe</c>".
- A more concrete example is the module <c>erl.lang.term</c>,
- which is in the
- package <c>erl.lang</c>.
- Package names can have any number of segments, as in
- <c>erl.lang.list.sort</c>.
- The atoms in the name can be quoted, as in <c>foo.'Bar'.baz</c>,
- or even the
- whole name, as in <c>'foo.bar.baz'</c> but the concatenation of
- atoms and
- periods must not contain two consecutive period characters or
- end with a period,
- as in <c>'foo..bar'</c>, <c>foo.'.bar'</c>, or <c>foo.'bar.'</c>.
- The periods must not be followed by whitespace.</p>
- <p>The code loader maps module names onto the file system directory
- structure.
- E.g., the module <c>erl.lang.term</c> corresponds to a file
- <c>.../erl/lang/term.beam</c>
- in the search path.
- Note that the name of the actual object file corresponds to
- the last part only of the full module name.
- (Thus, old existing modules such as <c>lists</c>
- simply map to <c>.../lists.beam</c>, exactly as before.)</p>
- <p>A packaged module in a file "<c>foo/bar/fred.erl</c>" is declared
- as:</p>
- <code type="none">
--module(foo.bar.fred).</code>
- <p>This can be compiled and loaded from the Erlang shell using
- <c>c(fred)</c>, if
- your current directory is the same as that of the file.
- The object file will be named <c>fred.beam</c>.</p>
- <p>The Erlang search path works exactly as before,
- except that the package segments will be appended to each
- directory in the path in order to find the
- file. E.g., assume the path is <c>["/usr/lib/erl", "/usr/local/lib/otp/legacy/ebin", "/home/barney/erl"]</c>.
- Then, the code for a module named <c>foo.bar.fred</c> will be
- searched for
- first as <c>"/usr/lib/erl/foo/bar/fred.beam"</c>, then
- <c>"/usr/local/lib/otp/legacy/ebin/foo/bar/fred.beam"</c>
- and lastly <c>"/home/barney/erl/foo/bar/fred.beam"</c>.
- A module
- like <c>lists</c>, which is in the top-level package,
- will be looked for as <c>"/usr/lib/erl/lists.beam"</c>,
- <c>"/usr/local/lib/otp/legacy/ebin/lists.beam"</c> and
- <c>"/home/barney/erl/lists.beam"</c>.</p>
- <p><em>Programming</em></p>
- <p>Normally, if a call is made from one module to another,
- it is assumed that the
- called module belongs to the same package as the source module.
- The compiler
- automatically expands such calls. E.g., in:</p>
- <code type="none">
--module(foo.bar.m1).
--export([f/1]).
-
-f(X) -> m2:g(X).</code>
- <p><c>m2:g(X)</c> becomes a call to <c>foo.bar.m2</c>
- If this is not what was intended, the call can be written
- explicitly, as in</p>
- <code type="none">
--module(foo.bar.m1).
--export([f/1]).
-
-f(X) -> fee.fie.foe.m2:g(X).</code>
- <p>Because the called module is given with an explicit package name,
- no expansion is done in this case.</p>
- <p>If a module from another package is used repeatedly in a module,
- an import declaration can make life easier:</p>
- <code type="none">
--module(foo.bar.m1).
--export([f/1, g/1]).
--import(fee.fie.foe.m2).
-
-f(X) -> m2:g(X).
-g(X) -> m2:h(X).</code>
- <p>will make the calls to <c>m2</c> refer to <c>fee.fie.foe.m2</c>.
- More generally, a declaration <c>-import(Package.Module).</c>
- will cause calls to <c>Module</c>
- to be expanded to <c>Package.Module</c>.</p>
- <p>Old-style function imports work as normal (but full module
- names must be
- used); e.g.:</p>
- <code type="none">
--import(fee.fie.foe.m2, [g/1, h/1]).</code>
- <p>however, it is probably better to avoid this form of import
- altogether in new
- code, since it makes it hard to see what calls are really "remote".</p>
- <p>If it is necessary to call a module in the top-level package
- from within a
- named package, the module name can be written either with an
- initial period as
- in e.g. "<c>.lists</c>", or with an empty initial atom, as in
- "<c>''.lists</c>".
- However, the best way is to use an import declaration -
- this is most obvious to
- the eye, and makes sure we don't forget adding a period somewhere:</p>
- <code type="none">
--module(foo.bar.fred).
--export([f/1]).
--import(lists).
-
-f(X) -> lists:reverse(X).</code>
- <p>The dot-syntax for module names can be used in any expression.
- All segments must
- be constant atoms, and the result must be a well-formed
- package/module name.
- E.g.:</p>
- <code type="none">
-spawn(foo.bar.fred, f, [X])</code>
- <p>is equivalent to <c>spawn('foo.bar.fred', f, [X])</c>.</p>
- <p><em>The Erlang Shell</em></p>
- <p>The shell also automatically expands remote calls,
- however currently no
- expansions are made by default.
- The user can change the behaviour by using the <c>import/1</c>
- shell command (or its abbreviation <c>use/1</c>). E.g.:</p>
- <pre>
-1> <input>import(foo.bar.m).</input>
-ok
-2> <input>m:f().</input></pre>
- <p>will evaluate <c>foo.bar.m:f()</c>.
- If a new import is made of the same name,
- this overrides any previous import.
- (It is likely that in the future, some
- system packages will be pre-imported.)</p>
- <p>In addition, the shell command <c>import_all/1</c>
- (and its alias <c>use_all/1</c>)
- imports all modules currently found in the path for a given
- package name. E.g.,
- assuming the files "<c>.../foo/bar/fred.beam</c>",
- "<c>.../foo/bar/barney.beam</c>"
- and "<c>.../foo/bar/bambam.beam</c>" can be found from our current
- path,</p>
- <pre>
-1> <input>import_all(foo.bar).</input></pre>
- <p>will make <c>fred</c>, <c>barney</c> and <c>bambam</c>
- expand to <c>foo.bar.fred</c>,
- <c>foo.bar.barney</c> and <c>foo.bar.bambam</c>, respectively.</p>
- <p>Note: The compiler does not have an "import all" directive, for the
- reason that Erlang has no compile time type checking.
- E.g. if the wrong search
- path is used at compile time, a call <c>m:f(...)</c>
- could be expanded to <c>foo.bar.m:f(...)</c>
- without any warning, instead of the intended
- <c>frob.ozz.m:f(...)</c>, if
- package <c>foo.bar</c> happens to be found first in the path.
- Explicitly
- declaring each use of a module makes for safe code.</p>
- </description>
-</erlref>
-
diff --git a/lib/kernel/doc/src/ref_man.xml b/lib/kernel/doc/src/ref_man.xml
index 9ef0959271..67d91ba585 100644
--- a/lib/kernel/doc/src/ref_man.xml
+++ b/lib/kernel/doc/src/ref_man.xml
@@ -64,6 +64,5 @@
<xi:include href="zlib_stub.xml"/>
<xi:include href="app.xml"/>
<xi:include href="config.xml"/>
- <xi:include href="packages.xml"/>
</application>
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index c76ff9e2f0..eaced4861a 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -107,7 +107,6 @@ MODULES = \
net_adm \
net_kernel \
os \
- packages \
pg2 \
ram_file \
rpc \
@@ -171,13 +170,13 @@ docs:
# ----------------------------------------------------
../../hipe/main/hipe.hrl: ../../hipe/vsn.mk ../../hipe/main/hipe.hrl.src
- sed -e "s;%VSN%;$(HIPE_VSN);" ../../hipe/main/hipe.hrl.src > ../../hipe/main/hipe.hrl
+ $(vsn_verbose)sed -e "s;%VSN%;$(HIPE_VSN);" ../../hipe/main/hipe.hrl.src > ../../hipe/main/hipe.hrl
$(APP_TARGET): $(APP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(KERNEL_VSN);' $< > $@
+ $(vsn_verbose)sed -e 's;%VSN%;$(KERNEL_VSN);' $< > $@
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(KERNEL_VSN);' $< > $@
+ $(vsn_verbose)sed -e 's;%VSN%;$(KERNEL_VSN);' $< > $@
EPMD_FLAGS = -Depmd_port_no=$(EPMD_PORT_NO) \
@@ -187,10 +186,10 @@ EPMD_FLAGS = -Depmd_port_no=$(EPMD_PORT_NO) \
-Derlang_daemon_port=$(EPMD_PORT_NO)
$(ESRC)/inet_dns_record_adts.hrl: $(ESRC)/inet_dns_record_adts.pl
- LANG=C $(PERL) $< > $@
+ $(gen_verbose)LANG=C $(PERL) $< > $@
$(EBIN)/erl_epmd.beam: $(ESRC)/erl_epmd.erl
- $(ERLC) $(ERL_COMPILE_FLAGS) $(EPMD_FLAGS) -o$(EBIN) $<
+ $(V_ERLC) $(ERL_COMPILE_FLAGS) $(EPMD_FLAGS) -o$(EBIN) $<
# ----------------------------------------------------
# Release Target
diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl
index 9b7c4aa7b8..4e65883be7 100644
--- a/lib/kernel/src/application.erl
+++ b/lib/kernel/src/application.erl
@@ -23,7 +23,7 @@
which_applications/0, which_applications/1,
loaded_applications/0, permit/2]).
-export([set_env/3, set_env/4, unset_env/2, unset_env/3]).
--export([get_env/1, get_env/2, get_all_env/0, get_all_env/1]).
+-export([get_env/1, get_env/2, get_env/3, get_all_env/0, get_all_env/1]).
-export([get_key/1, get_key/2, get_all_key/0, get_all_key/1]).
-export([get_application/0, get_application/1, info/0]).
-export([start_type/0]).
@@ -264,6 +264,20 @@ get_env(Key) ->
get_env(Application, Key) ->
application_controller:get_env(Application, Key).
+-spec get_env(Application, Par, Def) -> Val when
+ Application :: atom(),
+ Par :: atom(),
+ Def :: term(),
+ Val :: term().
+
+get_env(Application, Key, Def) ->
+ case get_env(Application, Key) of
+ {ok, Val} ->
+ Val;
+ undefined ->
+ Def
+ end.
+
-spec get_all_env() -> Env when
Env :: [{Par :: atom(), Val :: term()}].
diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl
index 68cd26ec10..75ce852001 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_controller.erl
@@ -1960,5 +1960,5 @@ to_string(Term) ->
true ->
Term;
false ->
- lists:flatten(io_lib:write(Term))
+ lists:flatten(io_lib:format("~134217728p", [Term]))
end.
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index c808ac7cb7..361f2bdf8a 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -359,7 +359,6 @@ load_code_server_prerequisites() ->
hipe_unified_loader,
lists,
os,
- packages,
unicode],
[M = M:module_info(module) || M <- Needed],
ok.
@@ -413,7 +412,7 @@ which(Module) when is_atom(Module) ->
end.
which2(Module) ->
- Base = to_path(Module),
+ Base = atom_to_list(Module),
File = filename:basename(Base) ++ objfile_extension(),
Path = get_path(),
which(File, filename:dirname(Base), Path).
@@ -547,9 +546,6 @@ has_ext(Ext, Extlen, File) ->
_ -> false
end.
-to_path(X) ->
- filename:join(packages:split(X)).
-
-spec load_native_code_for_all_loaded() -> ok.
load_native_code_for_all_loaded() ->
Architecture = erlang:system_info(hipe_architecture),
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 00ad923466..b2d2c19f78 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1229,7 +1229,7 @@ load_abs(File, Mod0, Caller, St) ->
end.
try_load_module(Mod, Dir, Caller, St) ->
- File = filename:append(Dir, to_path(Mod) ++
+ File = filename:append(Dir, to_list(Mod) ++
objfile_extension()),
case erl_prim_loader:get_file(File) of
error ->
@@ -1347,7 +1347,7 @@ load_file_1(Mod, Caller, #state{cache=Cache}=St0) ->
end.
mod_to_bin([Dir|Tail], Mod) ->
- File = filename:append(Dir, to_path(Mod) ++ objfile_extension()),
+ File = filename:append(Dir, to_list(Mod) ++ objfile_extension()),
case erl_prim_loader:get_file(File) of
error ->
mod_to_bin(Tail, Mod);
@@ -1356,7 +1356,7 @@ mod_to_bin([Dir|Tail], Mod) ->
end;
mod_to_bin([], Mod) ->
%% At last, try also erl_prim_loader's own method
- File = to_path(Mod) ++ objfile_extension(),
+ File = to_list(Mod) ++ objfile_extension(),
case erl_prim_loader:get_file(File) of
error ->
error; % No more alternatives !
@@ -1570,6 +1570,3 @@ to_list(X) when is_atom(X) -> atom_to_list(X).
to_atom(X) when is_atom(X) -> X;
to_atom(X) when is_list(X) -> list_to_atom(X).
-
-to_path(X) ->
- filename:join(packages:split(X)).
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 5b1efcd395..1513fdaec0 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -44,6 +44,8 @@
%% To be used for debugging only:
-export([pid2name/1]).
+-export_type([continuation/0]).
+
-type dlog_state_error() :: 'ok' | {'error', term()}.
-record(state, {queue = [],
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index f0d54a2f3e..e3511988a6 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -757,7 +757,8 @@ setup_timer(Pid, Timeout) ->
end.
reset_timer(Timer) ->
- Timer ! {self(), reset}.
+ Timer ! {self(), reset},
+ ok.
cancel_timer(Timer) ->
unlink(Timer),
diff --git a/lib/kernel/src/erl_ddll.erl b/lib/kernel/src/erl_ddll.erl
index f967fcc2ef..e03d280cd8 100644
--- a/lib/kernel/src/erl_ddll.erl
+++ b/lib/kernel/src/erl_ddll.erl
@@ -54,9 +54,7 @@ info(_, _) ->
erlang:nif_error(undef).
-spec format_error_int(ErrSpec) -> string() when
- ErrSpec :: inconsisten | linked_in_driver | permanent
- | not_loaded | not_loaded_by_this_process | not_pending
- | already_loaded | unloading.
+ ErrSpec :: term().
format_error_int(_) ->
erlang:nif_error(undef).
diff --git a/lib/kernel/src/error_handler.erl b/lib/kernel/src/error_handler.erl
index f8bc5f499c..a3aa1f1dcf 100644
--- a/lib/kernel/src/error_handler.erl
+++ b/lib/kernel/src/error_handler.erl
@@ -23,10 +23,12 @@
%% "error_handler: add no_native compiler directive"
-compile(no_native).
-%% A simple error handler.
+%% Callbacks called from the run-time system.
+-export([undefined_function/3,undefined_lambda/3,breakpoint/3]).
--export([undefined_function/3, undefined_lambda/3, stub_function/3,
- breakpoint/3]).
+%% Exported utility functions.
+-export([raise_undef_exception/3]).
+-export([stub_function/3]).
-spec undefined_function(Module, Function, Args) ->
any() when
@@ -41,12 +43,7 @@ undefined_function(Module, Func, Args) ->
true ->
apply(Module, Func, Args);
false ->
- case check_inheritance(Module, Args) of
- {value, Base, Args1} ->
- apply(Base, Func, Args1);
- none ->
- crash(Module, Func, Args)
- end
+ call_undefined_function_handler(Module, Func, Args)
end;
{module, _} ->
crash(Module, Func, Args);
@@ -77,6 +74,14 @@ undefined_lambda(Module, Fun, Args) ->
breakpoint(Module, Func, Args) ->
(int()):eval(Module, Func, Args).
+-spec raise_undef_exception(Module, Function, Args) -> no_return() when
+ Module :: atom(),
+ Function :: atom(),
+ Args :: list().
+
+raise_undef_exception(Module, Func, Args) ->
+ crash({Module,Func,Args,[]}).
+
%% Used to make the call to the 'int' module a "weak" one, to avoid
%% building strong components in xref or dialyzer.
@@ -130,27 +135,11 @@ ensure_loaded(Module) ->
stub_function(Mod, Func, Args) ->
exit({undef,[{Mod,Func,Args,[]}]}).
-check_inheritance(Module, Args) ->
- Attrs = erlang:get_module_info(Module, attributes),
- case lists:keyfind(extends, 1, Attrs) of
- {extends, [Base]} when is_atom(Base), Base =/= Module ->
- %% This is just a heuristic for detecting abstract modules
- %% with inheritance so they can be handled; it would be
- %% much better to do it in the emulator runtime
- case lists:keyfind(abstract, 1, Attrs) of
- {abstract, [true]} ->
- case lists:reverse(Args) of
- [M|Rs] when tuple_size(M) > 1,
- element(1,M) =:= Module,
- tuple_size(element(2,M)) > 0,
- is_atom(element(1,element(2,M))) ->
- {value, Base, lists:reverse(Rs, [element(2,M)])};
- _ ->
- {value, Base, Args}
- end;
- _ ->
- {value, Base, Args}
- end;
- _ ->
- none
+call_undefined_function_handler(Module, Func, Args) ->
+ Handler = '$handle_undefined_function',
+ case erlang:function_exported(Module, Handler, 2) of
+ false ->
+ crash(Module, Func, Args);
+ true ->
+ Module:Handler(Func, Args)
end.
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 22af38c598..16f2dde464 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -38,7 +38,7 @@
%% Specialized
-export([ipread_s32bu_p32bu/3]).
%% Generic file contents.
--export([open/2, close/1, advise/4,
+-export([open/2, close/1, advise/4, allocate/3,
read/2, write/2,
pread/2, pread/3, pwrite/2, pwrite/3,
read_line/1,
@@ -397,9 +397,10 @@ raw_write_file_info(Name, #file_info{} = Info) ->
%% Contemporary mode specification - list of options
--spec open(Filename, Modes) -> {ok, IoDevice} | {error, Reason} when
+-spec open(File, Modes) -> {ok, IoDevice} | {error, Reason} when
+ File :: Filename | iodata(),
Filename :: name(),
- Modes :: [mode()],
+ Modes :: [mode() | ram],
IoDevice :: io_device(),
Reason :: posix() | badarg | system_limit.
@@ -489,6 +490,18 @@ advise(#file_descriptor{module = Module} = Handle, Offset, Length, Advise) ->
advise(_, _, _, _) ->
{error, badarg}.
+-spec allocate(File, Offset, Length) ->
+ 'ok' | {'error', posix()} when
+ File :: io_device(),
+ Offset :: non_neg_integer(),
+ Length :: non_neg_integer().
+
+allocate(File, Offset, Length) when is_pid(File) ->
+ R = file_request(File, {allocate, Offset, Length}),
+ wait_file_reply(File, R);
+allocate(#file_descriptor{module = Module} = Handle, Offset, Length) ->
+ Module:allocate(Handle, Offset, Length).
+
-spec read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason} when
IoDevice :: io_device() | atom(),
Number :: non_neg_integer(),
@@ -1314,6 +1327,7 @@ sendfile_send(Sock, Data, Old) ->
%%% Helpers
consult_stream(Fd) ->
+ _ = epp:set_encoding(Fd),
consult_stream(Fd, 1, []).
consult_stream(Fd, Line, Acc) ->
@@ -1327,6 +1341,7 @@ consult_stream(Fd, Line, Acc) ->
end.
eval_stream(Fd, Handling, Bs) ->
+ _ = epp:set_encoding(Fd),
eval_stream(Fd, Handling, 1, undefined, [], Bs).
eval_stream(Fd, H, Line, Last, E, Bs) ->
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index 0bff56cf46..fad2ed7fb3 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -40,6 +40,8 @@ format_error({_Line, ?MODULE, Reason}) ->
io_lib:format("~w", [Reason]);
format_error({_Line, Mod, Reason}) ->
Mod:format_error(Reason);
+format_error(invalid_unicode) ->
+ io_lib:format("cannot translate from UTF-8", []);
format_error(ErrorId) ->
erl_posix_msg:message(ErrorId).
@@ -209,6 +211,10 @@ file_request({advise,Offset,Length,Advise},
Reply ->
{reply,Reply,State}
end;
+file_request({allocate, Offset, Length},
+ #state{handle = Handle} = State) ->
+ Reply = ?PRIM_FILE:allocate(Handle, Offset, Length),
+ {reply, Reply, State};
file_request({pread,At,Sz},
#state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) ->
case position(Handle, At, Buf) of
@@ -549,7 +555,7 @@ get_chars_notempty(Mod, Func, XtraArg, S, OutEnc,
<<>> ->
get_chars_apply(Mod, Func, XtraArg, S, OutEnc, State, eof);
_ ->
- {stop,invalid_unicode,{error,invalid_unicode},State}
+ {stop,invalid_unicode,invalid_unicode_error(Mod, Func, XtraArg, S),State}
end;
{error,Reason}=Error ->
{stop,Reason,Error,State}
@@ -616,12 +622,22 @@ get_chars_apply(Mod, Func, XtraArg, S0, OutEnc,
end
catch
exit:ExReason ->
- {stop,ExReason,{error,err_func(Mod, Func, XtraArg)},State};
+ {stop,ExReason,invalid_unicode_error(Mod, Func, XtraArg, S0),State};
error:ErrReason ->
{stop,ErrReason,{error,err_func(Mod, Func, XtraArg)},State}
end.
-
+%% A hack that tries to inform the caller about the position where the
+%% error occured.
+invalid_unicode_error(Mod, Func, XtraArg, S) ->
+ try
+ {erl_scan,tokens,_Args} = XtraArg,
+ Location = erl_scan:continuation_location(S),
+ {error,{Location, ?MODULE, invalid_unicode},Location}
+ catch
+ _:_ ->
+ {error,err_func(Mod, Func, XtraArg)}
+ end.
%% Convert error code to make it look as before
err_func(io_lib, get_until, {_,F,_}) ->
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index 8fa963ec78..74ad192802 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -44,6 +44,7 @@
{priority, non_neg_integer()} |
{recbuf, non_neg_integer()} |
{reuseaddr, boolean()} |
+ {ipv6_v6only, boolean()} |
{sctp_adaptation_layer, #sctp_setadaptation{}} |
{sctp_associnfo, #sctp_assocparams{}} |
{sctp_autoclose, non_neg_integer()} |
@@ -72,6 +73,7 @@
priority |
recbuf |
reuseaddr |
+ ipv6_v6only |
sctp_adaptation_layer |
sctp_associnfo |
sctp_autoclose |
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index e6dfdadb03..ec13ab6d2e 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -37,9 +37,11 @@
{dontroute, boolean()} |
{exit_on_close, boolean()} |
{header, non_neg_integer()} |
+ {high_msgq_watermark, pos_integer()} |
{high_watermark, non_neg_integer()} |
{keepalive, boolean()} |
{linger, {boolean(), non_neg_integer()}} |
+ {low_msgq_watermark, pos_integer()} |
{low_watermark, non_neg_integer()} |
{mode, list | binary} | list | binary |
{nodelay, boolean()} |
@@ -57,7 +59,8 @@
{send_timeout, non_neg_integer() | infinity} |
{send_timeout_close, boolean()} |
{sndbuf, non_neg_integer()} |
- {tos, non_neg_integer()}.
+ {tos, non_neg_integer()} |
+ {ipv6_v6only, boolean()}.
-type option_name() ::
active |
buffer |
@@ -66,9 +69,11 @@
dontroute |
exit_on_close |
header |
+ high_msgq_watermark |
high_watermark |
keepalive |
linger |
+ low_msgq_watermark |
low_watermark |
mode |
nodelay |
@@ -85,7 +90,8 @@
send_timeout |
send_timeout_close |
sndbuf |
- tos.
+ tos |
+ ipv6_v6only.
-type connect_option() ::
{ip, inet:ip_address()} |
{fd, Fd :: non_neg_integer()} |
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 830ca61b3c..c5a1173575 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -47,7 +47,8 @@
{recbuf, non_neg_integer()} |
{reuseaddr, boolean()} |
{sndbuf, non_neg_integer()} |
- {tos, non_neg_integer()}.
+ {tos, non_neg_integer()} |
+ {ipv6_v6only, boolean()}.
-type option_name() ::
active |
broadcast |
@@ -69,7 +70,8 @@
recbuf |
reuseaddr |
sndbuf |
- tos.
+ tos |
+ ipv6_v6only.
-type socket() :: port().
-export_type([option/0, option_name/0]).
diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl
index f92c6f7208..4d2e31a429 100644
--- a/lib/kernel/src/group.erl
+++ b/lib/kernel/src/group.erl
@@ -424,7 +424,7 @@ get_password_chars(Drv,Buf) ->
end.
get_chars(Prompt, M, F, Xa, Drv, Buf, Encoding) ->
- Pbs = prompt_bytes(Prompt),
+ Pbs = prompt_bytes(Prompt, Encoding),
get_chars_loop(Pbs, M, F, Xa, Drv, Buf, start, Encoding).
get_chars_loop(Pbs, M, F, Xa, Drv, Buf0, State, Encoding) ->
@@ -688,9 +688,9 @@ edit_password([Char|Cs],Chars) ->
edit_password(Cs,[Char|Chars]).
%% prompt_bytes(Prompt)
-%% Return a flat list of bytes for the Prompt.
-prompt_bytes(Prompt) ->
- lists:flatten(io_lib:format_prompt(Prompt)).
+%% Return a flat list of characters for the Prompt.
+prompt_bytes(Prompt, Encoding) ->
+ lists:flatten(io_lib:format_prompt(Prompt, Encoding)).
cast(L, binary,latin1) when is_list(L) ->
list_to_binary(L);
diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl
index 28452a377e..87cb9d7f51 100644
--- a/lib/kernel/src/heart.erl
+++ b/lib/kernel/src/heart.erl
@@ -42,9 +42,11 @@
-define(CLEAR_CMD, 5).
-define(GET_CMD, 6).
-define(HEART_CMD, 7).
+-define(PREPARING_CRASH, 8). % Used in beam vm
-define(TIMEOUT, 5000).
-define(CYCLE_TIMEOUT, 10000).
+-define(HEART_PORT_NAME, heart_port).
%%---------------------------------------------------------------------
@@ -130,6 +132,8 @@ start_portprogram() ->
Port when is_port(Port) ->
case wait_ack(Port) of
ok ->
+ %% register port so the vm can find it if need be
+ register(?HEART_PORT_NAME, Port),
{ok, Port};
{error, Reason} ->
report_problem({{port_problem, Reason},
@@ -225,6 +229,7 @@ no_reboot_shutdown(Port) ->
end.
do_cycle_port_program(Caller, Parent, Port, Cmd) ->
+ unregister(?HEART_PORT_NAME),
case catch start_portprogram() of
{ok, NewPort} ->
send_shutdown(Port),
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index b4ebb1500c..9670271b2e 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -30,7 +30,9 @@
ifget/3, ifget/2, ifset/3, ifset/2,
getstat/1, getstat/2,
ip/1, stats/0, options/0,
- pushf/3, popf/1, close/1, gethostname/0, gethostname/1]).
+ pushf/3, popf/1, close/1, gethostname/0, gethostname/1,
+ parse_ipv4_address/1, parse_ipv6_address/1, parse_ipv4strict_address/1,
+ parse_ipv6strict_address/1, parse_address/1, parse_strict_address/1]).
-export([connect_options/2, listen_options/2, udp_options/2, sctp_options/2]).
@@ -527,14 +529,57 @@ getservbyname(Name, Protocol) when is_atom(Name) ->
Error -> Error
end.
+-spec parse_ipv4_address(Address) ->
+ {ok, IPv4Address} | {error, einval} when
+ Address :: string(),
+ IPv4Address :: ip_address().
+parse_ipv4_address(Addr) ->
+ inet_parse:ipv4_address(Addr).
+
+-spec parse_ipv6_address(Address) ->
+ {ok, IPv6Address} | {error, einval} when
+ Address :: string(),
+ IPv6Address :: ip_address().
+parse_ipv6_address(Addr) ->
+ inet_parse:ipv6_address(Addr).
+
+-spec parse_ipv4strict_address(Address) ->
+ {ok, IPv4Address} | {error, einval} when
+ Address :: string(),
+ IPv4Address :: ip_address().
+parse_ipv4strict_address(Addr) ->
+ inet_parse:ipv4strict_address(Addr).
+
+-spec parse_ipv6strict_address(Address) ->
+ {ok, IPv6Address} | {error, einval} when
+ Address :: string(),
+ IPv6Address :: ip_address().
+parse_ipv6strict_address(Addr) ->
+ inet_parse:ipv6strict_address(Addr).
+
+-spec parse_address(Address) ->
+ {ok, IPAddress} | {error, einval} when
+ Address :: string(),
+ IPAddress :: ip_address().
+parse_address(Addr) ->
+ inet_parse:address(Addr).
+
+-spec parse_strict_address(Address) ->
+ {ok, IPAddress} | {error, einval} when
+ Address :: string(),
+ IPAddress :: ip_address().
+parse_strict_address(Addr) ->
+ inet_parse:strict_address(Addr).
+
%% Return a list of available options
options() ->
[
tos, priority, reuseaddr, keepalive, dontroute, linger,
- broadcast, sndbuf, recbuf, nodelay,
+ broadcast, sndbuf, recbuf, nodelay, ipv6_v6only,
buffer, header, active, packet, deliver, mode,
multicast_if, multicast_ttl, multicast_loop,
exit_on_close, high_watermark, low_watermark,
+ high_msgq_watermark, low_msgq_watermark,
send_timeout, send_timeout_close
].
@@ -552,8 +597,8 @@ stats() ->
connect_options() ->
[tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
header, active, packet, packet_size, buffer, mode, deliver,
- exit_on_close, high_watermark, low_watermark, send_timeout,
- send_timeout_close, delay_send,raw].
+ exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
+ low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw].
connect_options(Opts, Family) ->
BaseOpts =
@@ -607,9 +652,10 @@ con_add(Name, Val, R, Opts, AllOpts) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
listen_options() ->
[tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
- header, active, packet, buffer, mode, deliver, backlog,
- exit_on_close, high_watermark, low_watermark, send_timeout,
- send_timeout_close, delay_send, packet_size,raw].
+ header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only,
+ exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
+ low_msgq_watermark, send_timeout, send_timeout_close, delay_send,
+ packet_size, raw].
listen_options(Opts, Family) ->
BaseOpts =
@@ -664,7 +710,7 @@ list_add(Name, Val, R, Opts, As) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
udp_options() ->
[tos, priority, reuseaddr, sndbuf, recbuf, header, active, buffer, mode,
- deliver,
+ deliver, ipv6_v6only,
broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop,
add_membership, drop_membership, read_packets,raw].
@@ -720,7 +766,7 @@ udp_add(Name, Val, R, Opts, As) ->
sctp_options() ->
[ % The following are generic inet options supported for SCTP sockets:
mode, active, buffer, tos, priority, dontroute, reuseaddr, linger, sndbuf,
- recbuf,
+ recbuf, ipv6_v6only,
% Other options are SCTP-specific (though they may be similar to their
% TCP and UDP counter-parts):
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 467c4d5065..000119bc74 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -124,6 +124,7 @@
-define(UDP_OPT_MULTICAST_LOOP, 13).
-define(UDP_OPT_ADD_MEMBERSHIP, 14).
-define(UDP_OPT_DROP_MEMBERSHIP, 15).
+-define(INET_OPT_IPV6_V6ONLY, 16).
% "Local" options: codes start from 20:
-define(INET_LOPT_BUFFER, 20).
-define(INET_LOPT_HEADER, 21).
@@ -140,6 +141,8 @@
-define(INET_LOPT_READ_PACKETS, 33).
-define(INET_OPT_RAW, 34).
-define(INET_LOPT_TCP_SEND_TIMEOUT_CLOSE, 35).
+-define(INET_LOPT_TCP_MSGQ_HIWTRMRK, 36).
+-define(INET_LOPT_TCP_MSGQ_LOWTRMRK, 37).
% Specific SCTP options: separate range:
-define(SCTP_OPT_RTOINFO, 100).
-define(SCTP_OPT_ASSOCINFO, 101).
diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl
index ba62a59068..3551e701b6 100644
--- a/lib/kernel/src/inet_parse.erl
+++ b/lib/kernel/src/inet_parse.erl
@@ -36,7 +36,7 @@
-export([ipv4_address/1, ipv6_address/1]).
-export([ipv4strict_address/1, ipv6strict_address/1]).
--export([address/1]).
+-export([address/1, strict_address/1]).
-export([visible_string/1, domain/1]).
-export([ntoa/1, dots/1]).
-export([split_line/1]).
@@ -456,6 +456,17 @@ address(Cs) when is_list(Cs) ->
address(_) ->
{error, einval}.
+%%Parse ipv4 strict address or ipv6 strict address
+strict_address(Cs) when is_list(Cs) ->
+ case ipv4strict_address(Cs) of
+ {ok,IP} ->
+ {ok,IP};
+ _ ->
+ ipv6strict_address(Cs)
+ end;
+strict_address(Cs) ->
+ {error, einval}.
+
%%
%% Parse IPv4 address:
%% d1.d2.d3.d4
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 17ab84c177..9a20baf8d0 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -28,7 +28,6 @@
application_starter,
auth,
code,
- packages,
code_server,
dist_util,
erl_boot_server,
diff --git a/lib/kernel/src/packages.erl b/lib/kernel/src/packages.erl
deleted file mode 100644
index e0b1f36b85..0000000000
--- a/lib/kernel/src/packages.erl
+++ /dev/null
@@ -1,158 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(packages).
-
--export([to_string/1, concat/1, concat/2, is_valid/1, is_segmented/1,
- split/1, last/1, first/1, strip_last/1, find_modules/1,
- find_modules/2]).
-
-%% A package name (or a package-qualified module name) may be an atom or
-%% a string (list of nonnegative integers) - not a deep list, and not a
-%% list containing atoms. A name may be empty, but may not contain two
-%% consecutive period (`.') characters or end with a period character.
-
--type package_name() :: atom() | string().
-
--spec to_string(package_name()) -> string().
-to_string(Name) when is_atom(Name) ->
- atom_to_list(Name);
-to_string(Name) ->
- Name.
-
-%% `concat' does not insert a leading period if the first segment is
-%% empty. However, the result may contain leading, consecutive or
-%% dangling period characters, if any of the segments after the first
-%% are empty. Use 'is_valid' to check the result if necessary.
-
--spec concat(package_name(), package_name()) -> string().
-concat(A, B) ->
- concat([A, B]).
-
--spec concat([package_name()]) -> string().
-concat([H | T]) when is_atom(H) ->
- concat([atom_to_list(H) | T]);
-concat(["" | T]) ->
- concat_1(T);
-concat(L) ->
- concat_1(L).
-
-concat_1([H | T]) when is_atom(H) ->
- concat_1([atom_to_list(H) | T]);
-concat_1([H]) ->
- H;
-concat_1([H | T]) ->
- H ++ "." ++ concat_1(T);
-concat_1([]) ->
- "";
-concat_1(Name) ->
- erlang:error({badarg, Name}).
-
--spec is_valid(package_name()) -> boolean().
-is_valid(Name) when is_atom(Name) ->
- is_valid_1(atom_to_list(Name));
-is_valid([$. | _]) ->
- false;
-is_valid(Name) ->
- is_valid_1(Name).
-
-is_valid_1([$.]) -> false;
-is_valid_1([$., $. | _]) -> false;
-is_valid_1([H | T]) when is_integer(H), H >= 0 ->
- is_valid_1(T);
-is_valid_1([]) -> true;
-is_valid_1(_) -> false.
-
--spec split(package_name()) -> [string()].
-split(Name) when is_atom(Name) ->
- split_1(atom_to_list(Name), []);
-split(Name) ->
- split_1(Name, []).
-
-split_1([$. | T], Cs) ->
- [lists:reverse(Cs) | split_1(T, [])];
-split_1([H | T], Cs) when is_integer(H), H >= 0 ->
- split_1(T, [H | Cs]);
-split_1([], Cs) ->
- [lists:reverse(Cs)];
-split_1(_, _) ->
- erlang:error(badarg).
-
-%% This is equivalent to testing if `split(Name)' yields a list of
-%% length larger than one (i.e., if the name can be split into two or
-%% more segments), but is cheaper.
-
--spec is_segmented(package_name()) -> boolean().
-is_segmented(Name) when is_atom(Name) ->
- is_segmented_1(atom_to_list(Name));
-is_segmented(Name) ->
- is_segmented_1(Name).
-
-is_segmented_1([$. | _]) -> true;
-is_segmented_1([H | T]) when is_integer(H), H >= 0 ->
- is_segmented_1(T);
-is_segmented_1([]) -> false;
-is_segmented_1(_) ->
- erlang:error(badarg).
-
--spec last(package_name()) -> string().
-last(Name) ->
- last_1(split(Name)).
-
-last_1([H]) -> H;
-last_1([_ | T]) -> last_1(T).
-
--spec first(package_name()) -> [string()].
-first(Name) ->
- first_1(split(Name)).
-
-first_1([H | T]) when T =/= [] -> [H | first_1(T)];
-first_1(_) -> [].
-
--spec strip_last(package_name()) -> string().
-strip_last(Name) ->
- concat(first(Name)).
-
-%% This finds all modules available for a given package, using the
-%% current code server search path. (There is no guarantee that the
-%% modules are loadable; only that the object files exist.)
-
--spec find_modules(package_name()) -> [string()].
-find_modules(P) ->
- find_modules(P, code:get_path()).
-
--spec find_modules(package_name(), [string()]) -> [string()].
-find_modules(P, Paths) ->
- P1 = filename:join(packages:split(P)),
- find_modules(P1, Paths, code:objfile_extension(), sets:new()).
-
-find_modules(P, [Path | Paths], Ext, S0) ->
- case file:list_dir(filename:join(Path, P)) of
- {ok, Fs} ->
- Fs1 = [F || F <- Fs, filename:extension(F) =:= Ext],
- S1 = lists:foldl(fun (F, S) ->
- F1 = filename:rootname(F, Ext),
- sets:add_element(F1, S)
- end,
- S0, Fs1),
- find_modules(P, Paths, Ext, S1);
- _ ->
- find_modules(P, Paths, Ext, S0)
- end;
-find_modules(_P, [], _Ext, S) ->
- sets:to_list(S).
diff --git a/lib/kernel/src/pg2.erl b/lib/kernel/src/pg2.erl
index 0d5838716e..1ff10eb303 100644
--- a/lib/kernel/src/pg2.erl
+++ b/lib/kernel/src/pg2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -159,7 +159,7 @@ get_closest_pid(Name) ->
-record(state, {}).
--opaque state() :: #state{}.
+-type state() :: #state{}.
-spec init(Arg :: []) -> {'ok', state()}.
diff --git a/lib/kernel/src/ram_file.erl b/lib/kernel/src/ram_file.erl
index 48ea871433..ca881ff8a4 100644
--- a/lib/kernel/src/ram_file.erl
+++ b/lib/kernel/src/ram_file.erl
@@ -29,6 +29,7 @@
%% Specialized file operations
-export([get_size/1, get_file/1, set_file/2, get_file_close/1]).
-export([compress/1, uncompress/1, uuencode/1, uudecode/1, advise/4]).
+-export([allocate/3]).
-export([open_mode/1]). %% used by ftp-file
@@ -72,6 +73,7 @@
-define(RAM_FILE_UUDECODE, 36).
-define(RAM_FILE_SIZE, 37).
-define(RAM_FILE_ADVISE, 38).
+-define(RAM_FILE_ALLOCATE, 39).
%% Open modes for RAM_FILE_OPEN
-define(RAM_FILE_MODE_READ, 1).
@@ -383,6 +385,11 @@ advise(#file_descriptor{module = ?MODULE, data = Port}, Offset,
advise(#file_descriptor{}, _Offset, _Length, _Advise) ->
{error, enotsup}.
+allocate(#file_descriptor{module = ?MODULE, data = Port}, Offset, Length) ->
+ call_port(Port, <<?RAM_FILE_ALLOCATE, Offset:64/signed, Length:64/signed>>);
+allocate(#file_descriptor{}, _Offset, _Length) ->
+ {error, enotsup}.
+
%%%-----------------------------------------------------------------
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index 0b1fc6e939..7c965ca384 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -62,6 +62,8 @@
%% Internals
-export([proxy_user_flush/0]).
+-export_type([key/0]).
+
%%------------------------------------------------------------------------
-type state() :: gb_tree().
diff --git a/lib/kernel/src/user.erl b/lib/kernel/src/user.erl
index 88f32df20b..d6449d9e5e 100644
--- a/lib/kernel/src/user.erl
+++ b/lib/kernel/src/user.erl
@@ -81,7 +81,7 @@ server(PortName,PortSettings) ->
run(P) ->
put(read_mode,list),
- put(unicode,false),
+ put(encoding,latin1),
case init:get_argument(noshell) of
%% non-empty list -> noshell
{ok, [_|_]} ->
@@ -191,39 +191,27 @@ do_io_request(Req, From, ReplyAs, Port, Q0) ->
%% New in R13B
%% Encoding option (unicode/latin1)
io_request({put_chars,unicode,Chars}, Port, Q) -> % Binary new in R9C
- put_chars(wrap_characters_to_binary(Chars,unicode,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end), Port, Q);
+ put_chars(wrap_characters_to_binary(Chars,unicode, get(encoding)), Port, Q);
io_request({put_chars,unicode,Mod,Func,Args}, Port, Q) ->
Result = case catch apply(Mod,Func,Args) of
Data when is_list(Data); is_binary(Data) ->
- wrap_characters_to_binary(Data,unicode,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end);
+ wrap_characters_to_binary(Data,unicode,get(encoding));
Undef ->
Undef
end,
put_chars(Result, Port, Q);
io_request({put_chars,latin1,Chars}, Port, Q) -> % Binary new in R9C
- Data = case get(unicode) of
- true ->
+ Data = case get(encoding) of
+ unicode ->
unicode:characters_to_binary(Chars,latin1,unicode);
- false ->
+ latin1 ->
erlang:iolist_to_binary(Chars)
end,
put_chars(Data, Port, Q);
io_request({put_chars,latin1,Mod,Func,Args}, Port, Q) ->
Result = case catch apply(Mod,Func,Args) of
Data when is_list(Data); is_binary(Data) ->
- unicode:characters_to_binary(Data,latin1,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end);
+ unicode:characters_to_binary(Data,latin1,get(encoding));
Undef ->
Undef
end,
@@ -351,9 +339,9 @@ check_valid_opts(_) ->
do_setopts(Opts, _Port, Q) ->
case proplists:get_value(encoding,Opts) of
Valid when Valid =:= unicode; Valid =:= utf8 ->
- put(unicode,true);
+ put(encoding,unicode);
latin1 ->
- put(unicode,false);
+ put(encoding,latin1);
undefined ->
ok
end,
@@ -370,12 +358,7 @@ do_setopts(Opts, _Port, Q) ->
getopts(_Port,Q) ->
Bin = {binary, get(read_mode) =:= binary},
- Uni = {encoding, case get(unicode) of
- true ->
- unicode;
- _ ->
- latin1
- end},
+ Uni = {encoding, get(encoding)},
{ok,[Bin,Uni],Q}.
@@ -575,31 +558,32 @@ binrev(L, T) ->
%% end
%% end
%% end.
-%% get_chars(Prompt, Module, Function, XtraArg, Port, Queue)
+%% get_chars(Prompt, Module, Function, XtraArg, Port, Queue, Encoding)
%% Gets characters from the input port until the applied function
%% returns {stop,Result,RestBuf}. Does not block output until input
-%% has been received.
+%% has been received. Encoding is the encoding of the data sent to
+%% the client and to Function.
%% Returns:
%% {Status,Result,NewQueue}
%% {exit,Reason}
%% Entry function.
-get_chars(Prompt, M, F, Xa, Port, Q, Fmt) ->
+get_chars(Prompt, M, F, Xa, Port, Q, Enc) ->
prompt(Port, Prompt),
case {get(eof),queue:is_empty(Q)} of
{true,true} ->
{ok,eof,Q};
_ ->
- get_chars(Prompt, M, F, Xa, Port, Q, start, Fmt)
+ get_chars(Prompt, M, F, Xa, Port, Q, start, Enc)
end.
%% First loop. Wait for port data. Respond to output requests.
-get_chars(Prompt, M, F, Xa, Port, Q, State, Fmt) ->
+get_chars(Prompt, M, F, Xa, Port, Q, State, Enc) ->
case queue:is_empty(Q) of
true ->
receive
{Port,{data,Bytes}} ->
- get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Fmt);
+ get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Enc);
{Port, eof} ->
put(eof, true),
{ok, eof, []};
@@ -610,41 +594,41 @@ get_chars(Prompt, M, F, Xa, Port, Q, State, Fmt) ->
do_io_request(Req, From, ReplyAs, Port,
queue:new()), %Keep Q over this call
%% No prompt.
- get_chars(Prompt, M, F, Xa, Port, Q, State, Fmt);
+ get_chars(Prompt, M, F, Xa, Port, Q, State, Enc);
{io_request,From,ReplyAs,Request} when is_pid(From) ->
get_chars_req(Prompt, M, F, Xa, Port, Q, State,
- Request, From, ReplyAs, Fmt);
+ Request, From, ReplyAs, Enc);
{'EXIT',From,What} when node(From) =:= node() ->
{exit,What}
end;
false ->
- get_chars_apply(State, M, F, Xa, Port, Q, Fmt)
+ get_chars_apply(State, M, F, Xa, Port, Q, Enc)
end.
get_chars_req(Prompt, M, F, XtraArg, Port, Q, State,
- Req, From, ReplyAs, Fmt) ->
+ Req, From, ReplyAs, Enc) ->
do_io_request(Req, From, ReplyAs, Port, queue:new()), %Keep Q over this call
prompt(Port, Prompt),
- get_chars(Prompt, M, F, XtraArg, Port, Q, State, Fmt).
+ get_chars(Prompt, M, F, XtraArg, Port, Q, State, Enc).
%% Second loop. Pass data to client as long as it wants more.
%% A ^G in data interrupts loop if 'noshell' is not undefined.
-get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Fmt) ->
+get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Enc) ->
case get(shell) of
noshell ->
- get_chars_apply(State, M, F, Xa, Port, queue:snoc(Q, Bytes),Fmt);
+ get_chars_apply(State, M, F, Xa, Port, queue:snoc(Q, Bytes),Enc);
_ ->
case contains_ctrl_g_or_ctrl_c(Bytes) of
false ->
get_chars_apply(State, M, F, Xa, Port,
- queue:snoc(Q, Bytes),Fmt);
+ queue:snoc(Q, Bytes),Enc);
_ ->
throw(new_shell)
end
end.
-get_chars_apply(State0, M, F, Xa, Port, Q, Fmt) ->
- case catch M:F(State0, cast(queue:head(Q),Fmt), Fmt, Xa) of
+get_chars_apply(State0, M, F, Xa, Port, Q, Enc) ->
+ case catch M:F(State0, cast(queue:head(Q),Enc), Enc, Xa) of
{stop,Result,<<>>} ->
{ok,Result,queue:tail(Q)};
{stop,Result,[]} ->
@@ -653,32 +637,32 @@ get_chars_apply(State0, M, F, Xa, Port, Q, Fmt) ->
{ok,Result,queue:tail(Q)};
{stop,Result,Buf} ->
{ok,Result,queue:cons(Buf, queue:tail(Q))};
- {'EXIT',_} ->
+ {'EXIT',_Why} ->
{error,{error,err_func(M, F, Xa)},queue:new()};
State1 ->
- get_chars_more(State1, M, F, Xa, Port, queue:tail(Q), Fmt)
+ get_chars_more(State1, M, F, Xa, Port, queue:tail(Q), Enc)
end.
-get_chars_more(State, M, F, Xa, Port, Q, Fmt) ->
+get_chars_more(State, M, F, Xa, Port, Q, Enc) ->
case queue:is_empty(Q) of
true ->
case get(eof) of
undefined ->
receive
{Port,{data,Bytes}} ->
- get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Fmt);
+ get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Enc);
{Port,eof} ->
put(eof, true),
get_chars_apply(State, M, F, Xa, Port,
- queue:snoc(Q, eof), Fmt);
+ queue:snoc(Q, eof), Enc);
{'EXIT',From,What} when node(From) =:= node() ->
{exit,What}
end;
_ ->
- get_chars_apply(State, M, F, Xa, Port, queue:snoc(Q, eof), Fmt)
+ get_chars_apply(State, M, F, Xa, Port, queue:snoc(Q, eof), Enc)
end;
false ->
- get_chars_apply(State, M, F, Xa, Port, Q, Fmt)
+ get_chars_apply(State, M, F, Xa, Port, Q, Enc)
end.
@@ -689,11 +673,10 @@ get_chars_more(State, M, F, Xa, Port, Q, Fmt) ->
prompt(_Port, '') -> ok;
prompt(Port, Prompt) ->
- put_port(wrap_characters_to_binary(io_lib:format_prompt(Prompt),unicode,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end), Port).
+ Encoding = get(encoding),
+ put_port(wrap_characters_to_binary(io_lib:format_prompt(Prompt, Encoding),
+ unicode, Encoding),
+ Port).
%% Convert error code to make it look as before
err_func(io_lib, get_until, {_,F,_}) ->
@@ -710,56 +693,65 @@ contains_ctrl_g_or_ctrl_c(BinOrList)->
end.
%% Convert a buffer between list and binary
-cast(Data, _Format) when is_atom(Data) ->
+cast(Data, _Encoding) when is_atom(Data) ->
Data;
-cast(Data, Format) ->
- cast(Data, get(read_mode), Format, get(unicode)).
+cast(Data, Encoding) ->
+ IoEncoding = get(encoding),
+ cast(Data, get(read_mode), IoEncoding, Encoding).
-cast(B, binary, latin1, false) when is_binary(B) ->
+cast(B, binary, latin1, latin1) when is_binary(B) ->
B;
-cast(B, binary, latin1, true) when is_binary(B) ->
- unicode:characters_to_binary(B, unicode, latin1);
-cast(L, binary, latin1, false) ->
- erlang:iolist_to_binary(L);
-cast(L, binary, latin1, true) ->
- case unicode:characters_to_binary(
- erlang:iolist_to_binary(L),unicode,latin1) of % may fail
- {error,_,_} -> exit({no_translation, unicode, latin1});
- Else -> Else
+cast(L, binary, latin1, latin1) ->
+ case catch erlang:iolist_to_binary(L) of
+ Bin when is_binary(Bin) -> Bin;
+ _ -> exit({no_translation, latin1, latin1})
+ end;
+cast(Data, binary, unicode, latin1) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_binary(Data, unicode, latin1) of
+ Bin when is_binary(Bin) -> Bin;
+ _ -> exit({no_translation, unicode, latin1})
+ end;
+cast(Data, binary, latin1, unicode) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_binary(Data, latin1, unicode) of
+ Bin when is_binary(Bin) -> Bin;
+ _ -> exit({no_translation, latin1, unicode})
end;
-cast(B, binary, unicode, true) when is_binary(B) ->
+cast(B, binary, unicode, unicode) when is_binary(B) ->
B;
-cast(B, binary, unicode, false) when is_binary(B) ->
- unicode:characters_to_binary(B,latin1,unicode);
-cast(L, binary, unicode, true) ->
- % possibly a list containing UTF-8 encoded characters
- unicode:characters_to_binary(erlang:iolist_to_binary(L));
-cast(L, binary, unicode, false) ->
- unicode:characters_to_binary(L, latin1, unicode);
-cast(L, list, latin1, UniTerm) ->
- case UniTerm of
- true -> % Convert input characters to protocol format (i.e latin1)
- case unicode:characters_to_list(
- erlang:iolist_to_binary(L),unicode) of % may fail
- {error,_,_} -> exit({no_translation, unicode, latin1});
- Else -> [ case X of
- High when High > 255 ->
- exit({no_translation, unicode, latin1});
- Low ->
- Low
- end || X <- Else ]
- end;
- _ ->
- binary_to_list(erlang:iolist_to_binary(L))
+cast(L, binary, unicode, unicode) ->
+ case catch unicode:characters_to_binary(L, unicode) of
+ Bin when is_binary(Bin) -> Bin;
+ _ -> exit({no_translation, unicode, unicode})
end;
-cast(L, list, unicode, UniTerm) ->
- unicode:characters_to_list(erlang:iolist_to_binary(L),
- case UniTerm of
- true -> unicode;
- _ -> latin1
- end);
-cast(Other, _, _,_) ->
- Other.
+cast(B, list, latin1, latin1) when is_binary(B) ->
+ binary_to_list(B);
+cast(L, list, latin1, latin1) ->
+ case catch erlang:iolist_to_binary(L) of
+ Bin when is_binary(Bin) -> binary_to_list(Bin);
+ _ -> exit({no_translation, latin1, latin1})
+ end;
+cast(Data, list, unicode, latin1) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_list(Data, unicode) of
+ Chars when is_list(Chars) ->
+ [ case X of
+ High when High > 255 ->
+ exit({no_translation, unicode, latin1});
+ Low ->
+ Low
+ end || X <- Chars ];
+ _ ->
+ exit({no_translation, unicode, latin1})
+ end;
+cast(Data, list, latin1, unicode) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_list(Data, latin1) of
+ Chars when is_list(Chars) -> Chars;
+ _ -> exit({no_translation, latin1, unicode})
+ end;
+cast(Data, list, unicode, unicode) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_list(Data, unicode) of
+ Chars when is_list(Chars) -> Chars;
+ _ -> exit({no_translation, unicode, unicode})
+ end.
wrap_characters_to_binary(Chars,unicode,latin1) ->
case unicode:characters_to_binary(Chars,unicode,latin1) of
diff --git a/lib/kernel/src/wrap_log_reader.erl b/lib/kernel/src/wrap_log_reader.erl
index c41e0091e4..689269fc28 100644
--- a/lib/kernel/src/wrap_log_reader.erl
+++ b/lib/kernel/src/wrap_log_reader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -30,6 +30,8 @@
-export([open/1, open/2, chunk/1, chunk/2, close/1]).
+-export_type([continuation/0]).
+
-include("disk_log.hrl").
-record(wrap_reader,
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index 8eca37029d..8d2d55777b 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -48,6 +48,7 @@ MODULES= \
erl_distribution_SUITE \
erl_distribution_wb_SUITE \
erl_prim_loader_SUITE \
+ error_handler_SUITE \
error_logger_SUITE \
error_logger_warn_SUITE \
file_SUITE \
@@ -73,6 +74,7 @@ MODULES= \
seq_trace_SUITE \
wrap_log_reader_SUITE \
cleanup \
+ ignore_cores \
zlib_SUITE \
loose_node \
sendfile_SUITE
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index f469a0af98..2ca8840e1f 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -27,7 +27,7 @@
otp_1586/1, otp_2078/1, otp_2012/1, otp_2718/1, otp_2973/1,
otp_3002/1, otp_3184/1, otp_4066/1, otp_4227/1, otp_5363/1,
otp_5606/1,
- start_phases/1, get_key/1,
+ start_phases/1, get_key/1, get_env/1,
permit_false_start_local/1, permit_false_start_dist/1, script_start/1,
nodedown_start/1, init2973/0, loop2973/0, loop5606/1]).
@@ -49,7 +49,7 @@ all() ->
[failover, failover_comp, permissions, load,
load_use_cache, {group, reported_bugs}, start_phases,
script_start, nodedown_start, permit_false_start_local,
- permit_false_start_dist, get_key,
+ permit_false_start_dist, get_key, get_env,
{group, distr_changed}, config_change, shutdown_func, shutdown_timeout].
groups() ->
@@ -1503,6 +1503,15 @@ loop5606(Pid) ->
Pid ! {self(), Res}
end.
+get_env(suite) -> [];
+get_env(doc) ->
+ ["Tests get_env/* functions"];
+get_env(Conf) when is_list(Conf) ->
+ {ok, _} = application:get_env(kernel, error_logger),
+ undefined = application:get_env(undefined_app, a),
+ undefined = application:get_env(kernel, error_logger_xyz),
+ default = application:get_env(kernel, error_logger_xyz, default),
+ ok.
%%-----------------------------------------------------------------
%% Should be started in a CC view with:
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 5e0300639e..d7424c0c9a 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -684,8 +684,8 @@ ext_mod_dep(Config) when is_list(Config) ->
xref:set_default(s, [{verbose,false},{warnings,false},
{builtins,true},{recurse,true}]),
xref:set_library_path(s, code:get_path()),
- xref:add_directory(s, filename:dirname(code:which(kernel))),
- xref:add_directory(s, filename:dirname(code:which(lists))),
+ xref:add_directory(s, filename:join(code:lib_dir(kernel),"ebin")),
+ xref:add_directory(s, filename:join(code:lib_dir(stdlib),"ebin")),
case catch ext_mod_dep2() of
{'EXIT', Reason} ->
xref:stop(s),
diff --git a/lib/kernel/test/error_handler_SUITE.erl b/lib/kernel/test/error_handler_SUITE.erl
new file mode 100644
index 0000000000..2a86d39b74
--- /dev/null
+++ b/lib/kernel/test/error_handler_SUITE.erl
@@ -0,0 +1,68 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(error_handler_SUITE).
+
+-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ undefined_function_handler/1]).
+
+%% Callback from error_handler.
+-export(['$handle_undefined_function'/2]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [undefined_function_handler].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%%-----------------------------------------------------------------
+
+undefined_function_handler(_) ->
+ 42 = ?MODULE:forty_two(),
+ 42 = (id(?MODULE)):forty_two(),
+ {ok,{a,b,c}} = ?MODULE:one_arg({a,b,c}),
+ {ok,{a,b,c}} = (id(?MODULE)):one_arg({a,b,c}),
+ {'EXIT',{undef,[{?MODULE,undef_and_not_handled,[[1,2,3]],[]}|_]}} =
+ (catch ?MODULE:undef_and_not_handled([1,2,3])),
+ ok.
+
+'$handle_undefined_function'(forty_two, []) ->
+ 42;
+'$handle_undefined_function'(one_arg, [Arg]) ->
+ {ok,Arg};
+'$handle_undefined_function'(Func, Args) ->
+ error_handler:raise_undef_exception(?MODULE, Func, Args).
+
+id(I) ->
+ I.
diff --git a/lib/kernel/test/error_logger_warn_SUITE.erl b/lib/kernel/test/error_logger_warn_SUITE.erl
index 265e1ae4c8..2bf467610e 100644
--- a/lib/kernel/test/error_logger_warn_SUITE.erl
+++ b/lib/kernel/test/error_logger_warn_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -310,7 +310,7 @@ nice_stop_node(Name) ->
{nodedown,Name} -> ok
end.
-%rensa rd() f�re varje rapport-test s� man bara f�r en fil...
+%clean out rd() before each report test in order to get only one file...
clean_rd() ->
{ok,L} = file:list_dir(rd()),
lists:foreach(fun(F) ->
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 9c507fd437..914f0d6127 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -84,6 +84,8 @@
-export([advise/1]).
+-export([allocate/1]).
+
-export([standard_io/1,mini_server/1]).
%% Debug exports
@@ -116,7 +118,7 @@ groups() ->
{files, [],
[{group, open}, {group, pos}, {group, file_info},
{group, consult}, {group, eval}, {group, script},
- truncate, sync, datasync, advise]},
+ truncate, sync, datasync, advise, allocate]},
{open, [],
[open1, old_modes, new_modes, path_open, close, access,
read_write, pread_write, append, open_errors,
@@ -1617,6 +1619,74 @@ advise(Config) when is_list(Config) ->
?line test_server:timetrap_cancel(Dog),
ok.
+allocate(suite) -> [];
+allocate(doc) -> "Tests that ?FILE_MODULE:allocate/3 at least doesn't crash.";
+allocate(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(5)),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Allocate = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_allocate.fil"),
+
+ Line1 = "Hello\n",
+ Line2 = "World!\n",
+
+ ?line {ok, Fd} = ?FILE_MODULE:open(Allocate, [write, binary]),
+ allocate_and_assert(Fd, 1, iolist_size([Line1, Line2])),
+ ?line ok = io:format(Fd, "~s", [Line1]),
+ ?line ok = io:format(Fd, "~s", [Line2]),
+ ?line ok = ?FILE_MODULE:close(Fd),
+
+ ?line {ok, Fd2} = ?FILE_MODULE:open(Allocate, [write, binary]),
+ allocate_and_assert(Fd2, 1, iolist_size(Line1)),
+ ?line ok = io:format(Fd2, "~s", [Line1]),
+ ?line ok = io:format(Fd2, "~s", [Line2]),
+ ?line ok = ?FILE_MODULE:close(Fd2),
+
+ ?line {ok, Fd3} = ?FILE_MODULE:open(Allocate, [write, binary]),
+ allocate_and_assert(Fd3, 1, iolist_size(Line1) + 1),
+ ?line ok = io:format(Fd3, "~s", [Line1]),
+ ?line ok = io:format(Fd3, "~s", [Line2]),
+ ?line ok = ?FILE_MODULE:close(Fd3),
+
+ ?line {ok, Fd4} = ?FILE_MODULE:open(Allocate, [write, binary]),
+ allocate_and_assert(Fd4, 1, 4 * iolist_size([Line1, Line2])),
+ ?line ok = io:format(Fd4, "~s", [Line1]),
+ ?line ok = io:format(Fd4, "~s", [Line2]),
+ ?line ok = ?FILE_MODULE:close(Fd4),
+
+ ?line [] = flush(),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+allocate_and_assert(Fd, Offset, Length) ->
+ % Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have
+ % any other negative side effect. We can't really asssert against a
+ % specific return value, because support for file space pre-allocation
+ % depends on the OS, OS version and underlying filesystem.
+ %
+ % The Linux kernel added support for fallocate() in version 2.6.23,
+ % which currently works only for the ext4, ocfs2, xfs and btrfs file
+ % systems. posix_fallocate() is available in glibc as of version
+ % 2.1.94, but it was buggy until glibc version 2.7.
+ %
+ % Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE.
+ %
+ % Solaris supports posix_fallocate() but only for the UFS file system
+ % apparently (not supported for ZFS).
+ %
+ % FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate().
+ %
+ % For Windows there's apparently no way to pre-allocate file space, at
+ % least with same semantics as posix_fallocate(), fallocate() and
+ % fcntl F_PREALLOCATE.
+ Result = ?FILE_MODULE:allocate(Fd, Offset, Length),
+ case os:type() of
+ {win32, _} ->
+ ?line {error, enotsup} = Result;
+ _ ->
+ ?line _ = Result
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index 3aa010a708..40bde8a736 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -1,4 +1,5 @@
-module(file_name_SUITE).
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -336,7 +337,7 @@ check_normal(Mod) ->
check_icky(Mod) ->
{ok,Dir} = Mod:get_cwd(),
try
- ?line true=(length("���") =:= 3),
+ ?line true=(length("åäö") =:= 3),
?line UniMode = file:native_name_encoding() =/= latin1,
?line make_icky_dir(Mod),
?line {ok, L0} = Mod:list_dir("."),
@@ -357,42 +358,42 @@ check_icky(Mod) ->
|| {T,S,Targ} <- icky_dir(), T =:= symlink ],
?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
?line [ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ],
- ?line chk_cre_dir(Mod,[{directory,"���_dir",icky_dir()}]),
+ ?line chk_cre_dir(Mod,[{directory,"åäö_dir",icky_dir()}]),
?line {ok,BeginAt} = Mod:get_cwd(),
?line true = is_list(BeginAt),
- ?line {error,enoent} = Mod:set_cwd("��_dir"),
- ?line ok = Mod:set_cwd("���_dir"),
+ ?line {error,enoent} = Mod:set_cwd("åä_dir"),
+ ?line ok = Mod:set_cwd("åäö_dir"),
?line {ok, NowAt} = Mod:get_cwd(),
?line true = is_list(NowAt),
?line true = BeginAt =/= NowAt,
?line ok = Mod:set_cwd(".."),
?line {ok,BeginAt} = Mod:get_cwd(),
- ?line rm_r2(Mod,"���_dir"),
+ ?line rm_r2(Mod,"åäö_dir"),
{OS,TYPE} = os:type(),
% Check that treat_icky really converts to the same as the OS
case UniMode of
true ->
- ?line chk_cre_dir(Mod,[{directory,"���_dir",[]}]),
- ?line ok = Mod:set_cwd("���_dir"),
- ?line ok = Mod:write_file(<<"���">>,<<"hello">>),
- ?line Treated = treat_icky(<<"���">>),
+ ?line chk_cre_dir(Mod,[{directory,"åäö_dir",[]}]),
+ ?line ok = Mod:set_cwd("åäö_dir"),
+ ?line ok = Mod:write_file(<<"ååå">>,<<"hello">>),
+ ?line Treated = treat_icky(<<"ååå">>),
?line {ok,[Treated]} = Mod:list_dir("."),
- ?line ok = Mod:delete(<<"���">>),
+ ?line ok = Mod:delete(<<"ååå">>),
?line {ok,[]} = Mod:list_dir("."),
?line ok = Mod:set_cwd(".."),
- ?line rm_r2(Mod,"���_dir");
+ ?line rm_r2(Mod,"åäö_dir");
false ->
ok
end,
- ?line chk_cre_dir(Mod,[{directory,treat_icky(<<"���_dir">>),icky_dir()}]),
+ ?line chk_cre_dir(Mod,[{directory,treat_icky(<<"åäö_dir">>),icky_dir()}]),
if
UniMode and (OS =/= win32) ->
- ?line {error,enoent} = Mod:set_cwd("���_dir");
+ ?line {error,enoent} = Mod:set_cwd("åäö_dir");
true ->
ok
end,
- ?line ok = Mod:set_cwd(treat_icky(<<"���_dir">>)),
+ ?line ok = Mod:set_cwd(treat_icky(<<"åäö_dir">>)),
?line {ok, NowAt2} = Mod:get_cwd(),
io:format("~p~n",[NowAt2]),
% Cannot create raw unicode-breaking filenames on windows or macos
@@ -400,22 +401,22 @@ check_icky(Mod) ->
?line true = BeginAt =/= NowAt2,
?line ok = Mod:set_cwd(".."),
?line {ok,BeginAt} = Mod:get_cwd(),
- ?line rm_r2(Mod,conv(treat_icky(<<"���_dir">>))),
+ ?line rm_r2(Mod,conv(treat_icky(<<"åäö_dir">>))),
case has_links() of
true ->
- ?line ok = Mod:make_link("fil1","nisse�"),
- ?line {ok, <<"fil1">>} = Mod:read_file("nisse�"),
- ?line {ok, #file_info{type = regular}} = Mod:read_link_info("nisse�"),
- ?line ok = Mod:delete("nisse�"),
- ?line ok = Mod:make_link("fil1",treat_icky(<<"nisse�">>)),
- ?line {ok, <<"fil1">>} = Mod:read_file(treat_icky(<<"nisse�">>)),
- ?line {ok, #file_info{type = regular}} = Mod:read_link_info(treat_icky(<<"nisse�">>)),
- ?line ok = Mod:delete(treat_icky(<<"nisse�">>)),
+ ?line ok = Mod:make_link("fil1","nisseö"),
+ ?line {ok, <<"fil1">>} = Mod:read_file("nisseö"),
+ ?line {ok, #file_info{type = regular}} = Mod:read_link_info("nisseö"),
+ ?line ok = Mod:delete("nisseö"),
+ ?line ok = Mod:make_link("fil1",treat_icky(<<"nisseö">>)),
+ ?line {ok, <<"fil1">>} = Mod:read_file(treat_icky(<<"nisseö">>)),
+ ?line {ok, #file_info{type = regular}} = Mod:read_link_info(treat_icky(<<"nisseö">>)),
+ ?line ok = Mod:delete(treat_icky(<<"nisseö">>)),
?line {ok, <<"fil1">>} = Mod:read_file("fil1"),
- ?line {error,enoent} = Mod:read_file("nisse�"),
- ?line {error,enoent} = Mod:read_link_info("nisse�"),
- ?line {error,enoent} = Mod:read_file(treat_icky(<<"nisse�">>)),
- ?line {error,enoent} = Mod:read_link_info(treat_icky(<<"nisse�">>));
+ ?line {error,enoent} = Mod:read_file("nisseö"),
+ ?line {error,enoent} = Mod:read_link_info("nisseö"),
+ ?line {error,enoent} = Mod:read_file(treat_icky(<<"nisseö">>)),
+ ?line {error,enoent} = Mod:read_link_info(treat_icky(<<"nisseö">>));
false ->
ok
end,
@@ -430,42 +431,42 @@ check_icky(Mod) ->
?line {ok, BC} = Mod:read(FD,1024),
?line ok = file:close(FD)
end || {regular,Name,Content} <- icky_dir() ],
- ?line Mod:rename("���2","���_fil1"),
- ?line {ok, <<"���2">>} = Mod:read_file("���_fil1"),
- ?line {error,enoent} = Mod:read_file("���2"),
- ?line Mod:rename("���_fil1","���2"),
- ?line {ok, <<"���2">>} = Mod:read_file("���2"),
- ?line {error,enoent} = Mod:read_file("���_fil1"),
+ ?line Mod:rename("åäö2","åäö_fil1"),
+ ?line {ok, <<"åäö2">>} = Mod:read_file("åäö_fil1"),
+ ?line {error,enoent} = Mod:read_file("åäö2"),
+ ?line Mod:rename("åäö_fil1","åäö2"),
+ ?line {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
+ ?line {error,enoent} = Mod:read_file("åäö_fil1"),
- ?line Mod:rename("���2",treat_icky(<<"���_fil1">>)),
- ?line {ok, <<"���2">>} = Mod:read_file(treat_icky(<<"���_fil1">>)),
+ ?line Mod:rename("åäö2",treat_icky(<<"åäö_fil1">>)),
+ ?line {ok, <<"åäö2">>} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
if
UniMode and (OS =/= win32) ->
- {error,enoent} = Mod:read_file("���_fil1");
+ {error,enoent} = Mod:read_file("åäö_fil1");
true ->
ok
end,
- ?line {error,enoent} = Mod:read_file("���2"),
- ?line Mod:rename(treat_icky(<<"���_fil1">>),"���2"),
- ?line {ok, <<"���2">>} = Mod:read_file("���2"),
- ?line {error,enoent} = Mod:read_file("���_fil1"),
- ?line {error,enoent} = Mod:read_file(treat_icky(<<"���_fil1">>)),
+ ?line {error,enoent} = Mod:read_file("åäö2"),
+ ?line Mod:rename(treat_icky(<<"åäö_fil1">>),"åäö2"),
+ ?line {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
+ ?line {error,enoent} = Mod:read_file("åäö_fil1"),
+ ?line {error,enoent} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
- ?line {ok,FI} = Mod:read_file_info("���2"),
+ ?line {ok,FI} = Mod:read_file_info("åäö2"),
?line NewMode = FI#file_info.mode band (bnot 8#333),
?line NewMode2 = NewMode bor 8#222,
?line true = NewMode2 =/= NewMode,
- ?line ok = Mod:write_file_info("���2",FI#file_info{mode = NewMode}),
- ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info("���2"),
- ?line ok = Mod:write_file_info("���2",FI#file_info{mode = NewMode2}),
- ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("���2"),
+ ?line ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode}),
+ ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info("åäö2"),
+ ?line ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode2}),
+ ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("åäö2"),
- ?line {ok,FII} = Mod:read_file_info(treat_icky(<<"���5">>)),
+ ?line {ok,FII} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
?line true = NewMode2 =/= NewMode,
- ?line ok = Mod:write_file_info(treat_icky(<<"���5">>),FII#file_info{mode = NewMode}),
- ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info(treat_icky(<<"���5">>)),
- ?line ok = Mod:write_file_info(<<"���5">>,FII#file_info{mode = NewMode2}),
- ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info(treat_icky(<<"���5">>)),
+ ?line ok = Mod:write_file_info(treat_icky(<<"åäö5">>),FII#file_info{mode = NewMode}),
+ ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
+ ?line ok = Mod:write_file_info(<<"åäö5">>,FII#file_info{mode = NewMode2}),
+ ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
ok
after
Mod:set_cwd(Dir),
@@ -475,7 +476,7 @@ check_icky(Mod) ->
check_very_icky(Mod) ->
{ok,Dir} = Mod:get_cwd(),
try
- ?line true=(length("���") =:= 3),
+ ?line true=(length("åäö") =:= 3),
?line UniMode = file:native_name_encoding() =/= latin1,
if
not UniMode ->
@@ -497,7 +498,7 @@ check_very_icky(Mod) ->
?line chk_cre_dir(Mod,[{directory,[1088,1079,1091]++"_dir",very_icky_dir()}]),
?line {ok,BeginAt} = Mod:get_cwd(),
?line true = is_list(BeginAt),
- ?line {error,enoent} = Mod:set_cwd("��_dir"),
+ ?line {error,enoent} = Mod:set_cwd("åä_dir"),
?line ok = Mod:set_cwd([1088,1079,1091]++"_dir"),
?line {ok, NowAt} = Mod:get_cwd(),
?line true = is_list(NowAt),
@@ -514,16 +515,16 @@ check_very_icky(Mod) ->
?line {ok, #file_info{type = regular}} =
Mod:read_link_info("nisse"++[1088,1079,1091]),
?line ok = Mod:delete("nisse"++[1088,1079,1091]),
- ?line ok = Mod:make_link("fil1",<<"nisse�">>),
- ?line {ok, <<"fil1">>} = Mod:read_file(<<"nisse�">>),
+ ?line ok = Mod:make_link("fil1",<<"nisseö">>),
+ ?line {ok, <<"fil1">>} = Mod:read_file(<<"nisseö">>),
?line {ok, #file_info{type = regular}} =
- Mod:read_link_info(<<"nisse�">>),
- ?line ok = Mod:delete(<<"nisse�">>),
+ Mod:read_link_info(<<"nisseö">>),
+ ?line ok = Mod:delete(<<"nisseö">>),
?line {ok, <<"fil1">>} = Mod:read_file("fil1"),
?line {error,enoent} = Mod:read_file("nisse"++[1088,1079,1091]),
?line {error,enoent} = Mod:read_link_info("nisse"++[1088,1079,1091]),
- ?line {error,enoent} = Mod:read_file(<<"nisse�">>),
- ?line {error,enoent} = Mod:read_link_info(<<"nisse�">>);
+ ?line {error,enoent} = Mod:read_file(<<"nisseö">>),
+ ?line {error,enoent} = Mod:read_link_info(<<"nisseö">>);
false ->
ok
end,
@@ -540,10 +541,10 @@ check_very_icky(Mod) ->
end || {regular,Name,Content} <- very_icky_dir() ],
?line Mod:rename([956,965,963,954,959,49],
[956,965,963,954,959]++"_fil1"),
- ?line {ok, <<"���2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"),
+ ?line {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"),
?line {error,enoent} = Mod:read_file([956,965,963,954,959,49]),
?line Mod:rename([956,965,963,954,959]++"_fil1",[956,965,963,954,959,49]),
- ?line {ok, <<"���2">>} = Mod:read_file([956,965,963,954,959,49]),
+ ?line {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959,49]),
?line {error,enoent} = Mod:read_file([956,965,963,954,959]++"_fil1"),
?line {ok,FI} = Mod:read_file_info([956,965,963,954,959,49]),
@@ -574,9 +575,9 @@ check_very_icky(Mod) ->
end,
?line {NumOK,NumNOK} = filelib:fold_files(".",".*",true,fun(_F,{N,M}) when is_list(_F) -> io:format("~ts~n",[_F]),{N+1,M}; (_F,{N,M}) -> io:format("~p~n",[_F]),{N,M+1} end,{0,0}),
?line ok = filelib:fold_files(".",[1076,1089,1072,124,46,42],true,fun(_F,_) -> ok end,false),
- ?line SF3 = unicode:characters_to_binary("���subfil3",
+ ?line SF3 = unicode:characters_to_binary("åäösubfil3",
file:native_name_encoding()),
- ?line SF2 = case treat_icky(<<"���subfil2">>) of
+ ?line SF2 = case treat_icky(<<"åäösubfil2">>) of
LF2 when is_list(LF2) ->
unicode:characters_to_binary(LF2,
file:native_name_encoding());
@@ -584,7 +585,7 @@ check_very_icky(Mod) ->
BF2
end,
?line Sorted = lists:sort([SF3,SF2]),
- ?line Sorted = lists:sort(filelib:wildcard("*",<<"���subdir2">>)),
+ ?line Sorted = lists:sort(filelib:wildcard("*",<<"åäösubdir2">>)),
ok
catch
throw:need_unicode_mode ->
@@ -744,26 +745,26 @@ hopeless_darwin() ->
icky_dir() ->
[{regular,"fil1","fil1"},
- {regular,"���2","���2"}] ++
+ {regular,"åäö2","åäö2"}] ++
case has_links() of
true ->
- [{regular,"���3","���2"},
- {symlink,"���4","���2"}];
+ [{regular,"åäö3","åäö2"},
+ {symlink,"åäö4","åäö2"}];
false ->
[]
end ++
- [{regular,treat_icky(<<"���5">>),"���5"}] ++
+ [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++
case has_links() of
true ->
- [{symlink,treat_icky(<<"���6">>),treat_icky(<<"���5">>)}];
+ [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}];
false ->
[]
end ++
- [{directory,treat_icky(<<"���subdir2">>),
- [{regular,treat_icky(<<"���subfil2">>),"���subfil12"},
- {regular,"���subfil3","���subfil13"}]},
- {directory,"���subdir",
- [{regular,"���subfil1","���subfil1"}]}].
+ [{directory,treat_icky(<<"åäösubdir2">>),
+ [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
+ {regular,"åäösubfil3","åäösubfil13"}]},
+ {directory,"åäösubdir",
+ [{regular,"åäösubfil1","åäösubfil1"}]}].
make_very_icky_dir(Mod) ->
rm_rf(Mod,"very_icky_dir"),
@@ -774,26 +775,26 @@ make_very_icky_dir(Mod) ->
very_icky_dir() ->
[{regular,"fil1","fil1"},
- {regular,[956,965,963,954,959,49],"���2"}] ++
+ {regular,[956,965,963,954,959,49],"åäö2"}] ++
case has_links() of
true ->
- [{regular,[956,965,963,954,959,50],"���2"},
+ [{regular,[956,965,963,954,959,50],"åäö2"},
{symlink,[956,965,963,954,959,51],[956,965,963,954,959,49]}];
false ->
[]
end ++
- [{regular,treat_icky(<<"���5">>),"���5"}] ++
+ [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++
case has_links() of
true ->
- [{symlink,treat_icky(<<"���6">>),treat_icky(<<"���5">>)}];
+ [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}];
false ->
[]
end ++
- [{directory,treat_icky(<<"���subdir2">>),
- [{regular,treat_icky(<<"���subfil2">>),"���subfil12"},
- {regular,"���subfil3","���subfil13"}]},
+ [{directory,treat_icky(<<"åäösubdir2">>),
+ [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
+ {regular,"åäösubfil3","åäösubfil13"}]},
{directory,[956,965,963,954,959]++"subdir1",
- [{regular,[956,965,963,954,959]++"subfil1","���subfil1"}]}].
+ [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}].
%% Some OS'es simply do not allow non UTF8 filenames
treat_icky(Bin) ->
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index bcc2f0b840..2a886b2efc 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -31,22 +31,24 @@
[basic/1,
api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1,
- basic_stream/1, xfer_stream_min/1, peeloff/1, buffers/1,
open_multihoming_ipv4_socket/1,
open_unihoming_ipv6_socket/1,
open_multihoming_ipv6_socket/1,
- open_multihoming_ipv4_and_ipv6_socket/1]).
+ open_multihoming_ipv4_and_ipv6_socket/1,
+ basic_stream/1, xfer_stream_min/1, peeloff_active_once/1,
+ peeloff_active_true/1, buffers/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, api_open_close, api_listen, api_connect_init,
api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6,
- basic_stream, xfer_stream_min, peeloff, buffers,
open_multihoming_ipv4_socket,
open_unihoming_ipv6_socket,
open_multihoming_ipv6_socket,
- open_multihoming_ipv4_and_ipv6_socket].
+ open_multihoming_ipv4_and_ipv6_socket,
+ basic_stream, xfer_stream_min, peeloff_active_once,
+ peeloff_active_true, buffers].
groups() ->
[].
@@ -923,23 +925,34 @@ do_from_other_process(Fun) ->
end.
+peeloff_active_once(doc) ->
+ "Peel off an SCTP stream socket ({active,once})";
+peeloff_active_once(suite) ->
+ [];
+
+peeloff_active_once(Config) ->
+ peeloff(Config, [{active,once}]).
-peeloff(doc) ->
- "Peel off an SCTP stream socket";
-peeloff(suite) ->
+peeloff_active_true(doc) ->
+ "Peel off an SCTP stream socket ({active,true})";
+peeloff_active_true(suite) ->
[];
-peeloff(Config) when is_list(Config) ->
+
+peeloff_active_true(Config) ->
+ peeloff(Config, [{active,true}]).
+
+peeloff(Config, SockOpts) when is_list(Config) ->
?line Addr = {127,0,0,1},
?line Stream = 0,
?line Timeout = 333,
- ?line S1 = socket_open([{ifaddr,Addr}], Timeout),
+ ?line S1 = socket_open([{ifaddr,Addr}|SockOpts], Timeout),
?line ?LOGVAR(S1),
?line P1 = socket_call(S1, get_port),
?line ?LOGVAR(P1),
?line Socket1 = socket_call(S1, get_socket),
?line ?LOGVAR(Socket1),
?line socket_call(S1, {listen,true}),
- ?line S2 = socket_open([{ifaddr,Addr}], Timeout),
+ ?line S2 = socket_open([{ifaddr,Addr}|SockOpts], Timeout),
?line ?LOGVAR(S2),
?line P2 = socket_call(S2, get_port),
?line ?LOGVAR(P2),
@@ -983,7 +996,7 @@ peeloff(Config) when is_list(Config) ->
socket_bailout([S1,S2])
end,
%%
- ?line S3 = socket_peeloff(Socket1, S1Ai, Timeout),
+ ?line S3 = socket_peeloff(Socket1, S1Ai, SockOpts, Timeout),
?line ?LOGVAR(S3),
?line P3_X = socket_call(S3, get_port),
?line ?LOGVAR(P3_X),
@@ -1302,8 +1315,15 @@ recv_comm_up_eventually(S) ->
%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% socket gen_server ultra light
-socket_open(SocketOpts, Timeout) ->
- Opts = [{type,seqpacket},{active,once},binary|SocketOpts],
+socket_open(SockOpts0, Timeout) ->
+ SockOpts =
+ case lists:keyfind(active,1,SockOpts0) of
+ false ->
+ [{active,once}|SockOpts0];
+ _ ->
+ SockOpts0
+ end,
+ Opts = [{type,seqpacket},binary|SockOpts],
Starter =
fun () ->
{ok,Socket} =
@@ -1312,8 +1332,8 @@ socket_open(SocketOpts, Timeout) ->
end,
s_start(Starter, Timeout).
-socket_peeloff(Socket, AssocId, Timeout) ->
- Opts = [{active,once},binary],
+socket_peeloff(Socket, AssocId, SocketOpts, Timeout) ->
+ Opts = [binary|SocketOpts],
Starter =
fun () ->
{ok,NewSocket} =
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index 2354f8accd..cd768813cf 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -442,7 +443,7 @@ open_fd(suite) ->
open_fd(doc) ->
["Test that the 'fd' option works"];
open_fd(Config) when is_list(Config) ->
- Msg = "Det g�r ont n�r knoppar brista. Varf�r skulle annars v�ren tveka?",
+ Msg = "Det gör ont när knoppar brista. Varför skulle annars våren tveka?",
Addr = {127,0,0,1},
{ok,S1} = gen_udp:open(0),
{ok,P2} = inet:port(S1),
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 60035b50a0..9428a38660 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,27 +91,9 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_suite(Config) ->
-
- %% Copied from test_server_ctrl ln 647, we have to do this here as
- %% the test_server only does this when run without common_test
- global:sync(),
- case global:whereis_name(test_server) of
- undefined ->
- io:format(user, "Registering test_server globally!~n",[]),
- global:register_name(test_server, whereis(test_server_ctrl));
- Pid ->
- case node() of
- N when N == node(Pid) ->
- io:format(user, "Warning: test_server already running!\n", []),
- global:re_register_name(test_server,self());
- _ ->
- ok
- end
- end,
Config.
end_per_suite(_Config) ->
- global:unregister_name(test_server),
ok.
@@ -135,8 +117,7 @@ end_per_testcase(_Case, Config) ->
?line write_high_level_trace(Config),
?line _ =
gen_server:call(global_name_server, high_level_trace_stop, infinity),
- ?line[global:unregister_name(N) || N <- global:registered_names(),
- N =/= test_server],
+ [global:unregister_name(N) || N <- global:registered_names()],
?line InitRegistered = ?registered,
?line Registered = registered(),
?line [io:format("~s local names: ~p~n", [What, N]) ||
@@ -168,7 +149,7 @@ end_per_testcase(_Case, Config) ->
register_1(suite) -> [];
register_1(Config) when is_list(Config) ->
Timeout = 15,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
P = spawn_link(?MODULE, lock_global, [self(), Config]),
@@ -195,7 +176,6 @@ register_1(Config) when is_list(Config) ->
?line _ = global:unregister_name(foo),
write_high_level_trace(Config),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
lock_global(Parent, Config) ->
@@ -238,7 +218,7 @@ lock_global(Parent, Config) ->
both_known_1(suite) -> [];
both_known_1(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
@@ -316,7 +296,6 @@ both_known_1(Config) when is_list(Config) ->
stop_node(Cp3),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
lost_unregister(suite) -> [];
@@ -324,7 +303,7 @@ lost_unregister(doc) ->
["OTP-6428. An unregistered name reappears."];
lost_unregister(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
@@ -361,7 +340,6 @@ lost_unregister(Config) when is_list(Config) ->
stop_node(B),
stop_node(C),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
-define(UNTIL_LOOP, 300).
@@ -448,7 +426,7 @@ lock_global2(Id, Parent) ->
names(suite) -> [];
names(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -532,7 +510,6 @@ names(Config) when is_list(Config) ->
?line ?UNTIL(undefined =:= global:whereis_name(test)),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
names_hidden(suite) -> [];
@@ -541,7 +518,7 @@ names_hidden(doc) ->
"visible nodes."];
names_hidden(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -639,13 +616,12 @@ names_hidden(Config) when is_list(Config) ->
stop_node(Cp3),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
locks(suite) -> [];
locks(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line {ok, Cp1} = start_node(cp1, Config),
@@ -750,7 +726,6 @@ locks(Config) when is_list(Config) ->
?line test_server:sleep(10),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
@@ -760,7 +735,7 @@ locks_hidden(doc) ->
"visible nodes."];
locks_hidden(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNodes = nodes(),
@@ -833,14 +808,13 @@ locks_hidden(Config) when is_list(Config) ->
stop_node(Cp3),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
bad_input(suite) -> [];
bad_input(Config) when is_list(Config) ->
Timeout = 15,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
Pid = whereis(global_name_server),
@@ -854,13 +828,12 @@ bad_input(Config) when is_list(Config) ->
?line {'EXIT', _} = (catch global:trans({id, self()}, {m,f}, [node()], -1)),
?line Pid = whereis(global_name_server),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
names_and_locks(suite) -> [];
names_and_locks(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -922,7 +895,6 @@ names_and_locks(Config) when is_list(Config) ->
stop_node(Cp3),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
lock_die(suite) -> [];
@@ -930,7 +902,7 @@ lock_die(doc) ->
["OTP-6341. Remove locks using monitors."];
lock_die(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -964,7 +936,6 @@ lock_die(Config) when is_list(Config) ->
stop_node(Cp1),
stop_node(Cp2),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
name_die(suite) -> [];
@@ -972,7 +943,7 @@ name_die(doc) ->
["OTP-6341. Remove names using monitors."];
name_die(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -1027,7 +998,6 @@ name_die(Config) when is_list(Config) ->
write_high_level_trace(Config),
stop_nodes(Cps),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
kill_pid(Pid, File, Config) ->
@@ -1040,7 +1010,7 @@ basic_partition(doc) ->
["Tests that two partitioned networks exchange correct info."];
basic_partition(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -1088,7 +1058,6 @@ basic_partition(Config) when is_list(Config) ->
stop_node(Cp2),
stop_node(Cp3),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
basic_name_partition(suite) ->
@@ -1099,7 +1068,7 @@ basic_name_partition(doc) ->
"during connect phase are handled correctly."];
basic_name_partition(Config) when is_list(Config) ->
Timeout = 60,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -1167,7 +1136,6 @@ basic_name_partition(Config) when is_list(Config) ->
stop_node(Cp2),
stop_node(Cp3),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
%Peer nodes cp0 - cp6 are started. Break apart the connections from
@@ -1190,7 +1158,7 @@ advanced_partition(doc) ->
"partitioned networks connect."];
advanced_partition(Config) when is_list(Config) ->
Timeout = 60,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -1278,7 +1246,6 @@ advanced_partition(Config) when is_list(Config) ->
stop_node(Cp5),
stop_node(Cp6),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
%Peer nodes cp0 - cp6 are started, and partitioned just like in
@@ -1297,7 +1264,7 @@ stress_partition(doc) ->
"go up/down a bit."];
stress_partition(Config) when is_list(Config) ->
Timeout = 90,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -1377,7 +1344,6 @@ stress_partition(Config) when is_list(Config) ->
stop_node(Cp7),
stop_node(Cp8),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
@@ -1408,7 +1374,7 @@ ring(doc) ->
"Make sure that there's just one winner."];
ring(Config) when is_list(Config) ->
Timeout = 60,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -1486,7 +1452,6 @@ ring(Config) when is_list(Config) ->
stop_node(Cp7),
stop_node(Cp8),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
simple_ring(suite) ->
@@ -1499,7 +1464,7 @@ simple_ring(doc) ->
"Make sure that there's just one winner."];
simple_ring(Config) when is_list(Config) ->
Timeout = 60,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -1565,7 +1530,6 @@ simple_ring(Config) when is_list(Config) ->
stop_node(Cp4),
stop_node(Cp5),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
line(suite) ->
@@ -1576,7 +1540,7 @@ line(doc) ->
"Make sure that there's just one winner."];
line(Config) when is_list(Config) ->
Timeout = 60,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -1655,7 +1619,6 @@ line(Config) when is_list(Config) ->
stop_node(Cp7),
stop_node(Cp8),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
@@ -1669,7 +1632,7 @@ simple_line(doc) ->
"Make sure that there's just one winner."];
simple_line(Config) when is_list(Config) ->
Timeout = 60,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -1735,7 +1698,6 @@ simple_line(Config) when is_list(Config) ->
stop_node(Cp4),
stop_node(Cp5),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
otp_1849(suite) -> [];
@@ -1743,7 +1705,7 @@ otp_1849(doc) ->
["Test ticket: Global should keep track of all pids that set the same lock."];
otp_1849(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line {ok, Cp1} = start_node(cp1, Config),
@@ -1822,7 +1784,6 @@ otp_1849(Config) when is_list(Config) ->
stop_node(Cp2),
stop_node(Cp3),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
@@ -1840,7 +1801,7 @@ otp_3162(Config) when is_list(Config) ->
do_otp_3162(StartFun, Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line [Cp1, Cp2, Cp3] = StartFun(),
@@ -1860,16 +1821,16 @@ do_otp_3162(StartFun, Config) ->
?line ?UNTIL
([Cp3] =:= lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([kalle, test_server, vera] =:=
+ ?UNTIL([kalle, vera] =:=
lists:sort(rpc:call(Cp1, global, registered_names, []))),
?line ?UNTIL
([Cp3] =:= lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([stina, test_server, vera] =:=
+ ?UNTIL([stina, vera] =:=
lists:sort(rpc:call(Cp2, global, registered_names, []))),
?line ?UNTIL
([Cp1, Cp2] =:=
lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([kalle, stina, test_server, vera] =:=
+ ?UNTIL([kalle, stina, vera] =:=
lists:sort(rpc:call(Cp3, global, registered_names, []))),
?line pong = rpc:call(Cp2, net_adm, ping, [Cp1]),
@@ -1880,17 +1841,17 @@ do_otp_3162(StartFun, Config) ->
?line
?UNTIL(begin
NN = lists:sort(rpc:call(Cp1, global, registered_names, [])),
- [kalle, stina, test_server, vera] =:= NN
+ [kalle, stina, vera] =:= NN
end),
?line ?UNTIL
([Cp1, Cp3] =:=
lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([kalle, stina, test_server, vera] =:=
+ ?UNTIL([kalle, stina, vera] =:=
lists:sort(rpc:call(Cp2, global, registered_names, []))),
?line ?UNTIL
([Cp1, Cp2] =:=
lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
- ?line ?UNTIL([kalle, stina, test_server, vera] =:=
+ ?UNTIL([kalle, stina, vera] =:=
lists:sort(rpc:call(Cp3, global, registered_names, []))),
write_high_level_trace(Config),
@@ -1898,7 +1859,6 @@ do_otp_3162(StartFun, Config) ->
stop_node(Cp2),
stop_node(Cp3),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
@@ -1907,7 +1867,7 @@ otp_5640(doc) ->
["OTP-5640. 'allow' multiple names for registered processes."];
otp_5640(Config) when is_list(Config) ->
Timeout = 25,
- ?line Dog = test_server:timetrap(test_server:seconds(Timeout)),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
init_condition(Config),
?line {ok, B} = start_node(b, Config),
@@ -1965,7 +1925,6 @@ otp_5640(Config) when is_list(Config) ->
write_high_level_trace(Config),
stop_node(B),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
otp_5640_proc(_Parent) ->
@@ -1979,7 +1938,7 @@ otp_5737(doc) ->
["OTP-5737. set_lock/3 and trans/4 accept Retries = 0."];
otp_5737(Config) when is_list(Config) ->
Timeout = 25,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
@@ -2000,7 +1959,6 @@ otp_5737(Config) when is_list(Config) ->
write_high_level_trace(Config),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
otp_6931(suite) -> [];
@@ -2025,7 +1983,7 @@ simple_disconnect(suite) -> [];
simple_disconnect(doc) -> ["OTP-5563. Disconnected nodes (not partitions)"];
simple_disconnect(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -2075,7 +2033,6 @@ simple_disconnect(Config) when is_list(Config) ->
write_high_level_trace(Config),
stop_nodes(Cps),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
%% Not used right now.
@@ -2118,7 +2075,7 @@ simple_resolve(suite) -> [];
simple_resolve(doc) -> ["OTP-5563. Partitions and names."];
simple_resolve(Config) when is_list(Config) ->
Timeout = 360,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -2245,7 +2202,6 @@ simple_resolve(Config) when is_list(Config) ->
write_high_level_trace(Config),
stop_nodes(Cps),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
simple_resolve2(suite) -> [];
@@ -2255,7 +2211,7 @@ simple_resolve2(Config) when is_list(Config) ->
%% always work to re-start z_2. "Cannot be a global bug."
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -2283,7 +2239,6 @@ simple_resolve2(Config) when is_list(Config) ->
write_high_level_trace(Config),
stop_nodes(Cps), % Not all nodes may be present, but it works anyway.
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
simple_resolve3(suite) -> [];
@@ -2292,7 +2247,7 @@ simple_resolve3(Config) when is_list(Config) ->
%% Continuation of simple_resolve.
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -2320,7 +2275,6 @@ simple_resolve3(Config) when is_list(Config) ->
write_high_level_trace(Config),
stop_nodes(Cps), % Not all nodes may be present, but it works anyway.
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
res({Res,Resolver}, [N1, A2, Z2], Cf) ->
@@ -2504,7 +2458,7 @@ leftover_name(suite) -> [];
leftover_name(doc) -> ["OTP-5563. Bug: nodedown while synching."];
leftover_name(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -2565,7 +2519,6 @@ leftover_name(Config) when is_list(Config) ->
write_high_level_trace(Config),
stop_nodes(Cps),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
%% Runs on n_1
@@ -2604,7 +2557,7 @@ re_register_name(Config) when is_list(Config) ->
%% occupied by links, that's all.
%% Later: now monitors are checked.
Timeout = 15,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
Me = self(),
@@ -2618,7 +2571,6 @@ re_register_name(Config) when is_list(Config) ->
receive {Pid2, MonitoredBy2} -> [_] = MonitoredBy2 end,
?line _ = global:unregister_name(name),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
proc(Parent) ->
@@ -2652,7 +2604,7 @@ do_name_exit(StartFun, Version, Config) ->
%% The current release uses monitors so this test is not so relevant.
Timeout = 60,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -2692,7 +2644,6 @@ do_name_exit(StartFun, Version, Config) ->
write_high_level_trace(Config),
stop_nodes(Cps),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
long_lock(Parent) ->
@@ -2709,7 +2660,7 @@ external_nodes(suite) -> [];
external_nodes(doc) -> ["OTP-5563. External nodes (cnodes)."];
external_nodes(Config) when is_list(Config) ->
Timeout = 30,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -2793,7 +2744,6 @@ external_nodes(Config) when is_list(Config) ->
?line ?UNTIL(length(get_ext_names()) =:= 0),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
get_ext_names() ->
@@ -2845,8 +2795,8 @@ many_nodes(suite) ->
many_nodes(doc) ->
["OTP-5770. Start many nodes. Make them connect at the same time."];
many_nodes(Config) when is_list(Config) ->
- Timeout = 180,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ Timeout = 240,
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -2902,7 +2852,6 @@ many_nodes(Config) when is_list(Config) ->
write_high_level_trace(Config),
?line stop_nodes(Cps),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
Diff = Time2 - Time,
Return = lists:flatten(io_lib:format("~w nodes took ~w ms",
[N_cps, Diff])),
@@ -2988,7 +2937,7 @@ sync_0(doc) ->
["OTP-5770. sync/0."];
sync_0(Config) when is_list(Config) ->
Timeout = 180,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
@@ -3013,7 +2962,6 @@ sync_0(Config) when is_list(Config) ->
stop_nodes(Cps),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
start_and_sync([]) ->
@@ -3031,7 +2979,7 @@ global_groups_change(suite) -> [];
global_groups_change(doc) -> ["Test change of global_groups parameter."];
global_groups_change(Config) ->
Timeout = 90,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line M = from($@, atom_to_list(node())),
@@ -3376,7 +3324,6 @@ global_groups_change(Config) ->
stop_node(CpE),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
sync_and_wait(Node) ->
@@ -3855,7 +3802,7 @@ start_node_rel(Name0, Rel, Config) ->
Name = node_name(Name0, Config),
{Release, Compat} = case Rel of
this ->
- {[this], "+R8"};
+ {[this], ""};
Rel when is_atom(Rel) ->
{[{release, atom_to_list(Rel)}], ""};
RelList ->
@@ -3919,7 +3866,7 @@ global_lost_nodes(doc) ->
["Tests that locally loaded nodes do not loose contact with other nodes."];
global_lost_nodes(Config) when is_list(Config) ->
Timeout = 60,
- Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
@@ -3943,7 +3890,6 @@ global_lost_nodes(Config) when is_list(Config) ->
?line stop_node(Node1),
?line stop_node(Node2),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
global_load(MyName, OtherNode, OtherName) ->
@@ -3994,7 +3940,7 @@ mass_death(doc) ->
["Tests the simultaneous death of many processes with registered names"];
mass_death(Config) when is_list(Config) ->
Timeout = 90,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line OrigNames = global:registered_names(),
@@ -4023,9 +3969,9 @@ mass_death(Config) when is_list(Config) ->
{H,M,S} = time(),
io:format("Started probing: ~.4.0w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w~n",
[YYYY,MM,DD,H,M,S]),
- wait_mass_death(Dog, Nodes, OrigNames, erlang:now(), Config).
+ wait_mass_death(Nodes, OrigNames, erlang:now(), Config).
-wait_mass_death(Dog, Nodes, OrigNames, Then, Config) ->
+wait_mass_death(Nodes, OrigNames, Then, Config) ->
?line Names = global:registered_names(),
?line
case Names--OrigNames of
@@ -4036,12 +3982,11 @@ wait_mass_death(Dog, Nodes, OrigNames, Then, Config) ->
stop_node(Node)
end, Nodes),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
{comment,lists:flatten(io_lib:format("~.3f s~n", [T/1000.0]))};
Ndiff ->
?line io:format("Ndiff: ~p~n", [Ndiff]),
?line test_server:sleep(1000),
- ?line wait_mass_death(Dog, Nodes, OrigNames, Then, Config)
+ ?line wait_mass_death(Nodes, OrigNames, Then, Config)
end.
mass_spawn([]) ->
@@ -4190,7 +4135,7 @@ init_condition(Config) ->
{"Global Locks (ETS)", global_locks},
{"Global Pid Names (ETS)", global_pid_names},
{"Global Pid Ids (ETS)", global_pid_ids}]],
- ?UNTIL([test_server] =:= global:registered_names()),
+ ?UNTIL([] =:= global:registered_names()),
?UNTIL([] =:= nodes()),
?UNTIL([node()] =:= get_known(node())),
ok.
@@ -4213,7 +4158,7 @@ garbage_messages(suite) ->
[];
garbage_messages(Config) when is_list(Config) ->
Timeout = 25,
- ?line Dog = test_server:timetrap({seconds,Timeout}),
+ ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
?line init_condition(Config),
?line [Slave] = start_nodes([garbage_messages], slave, Config),
@@ -4233,7 +4178,6 @@ garbage_messages(Config) when is_list(Config) ->
write_high_level_trace(Config),
?line stop_node(Slave),
?line init_condition(Config),
- ?line test_server:timetrap_cancel(Dog),
ok.
wait_for_ready_net(Config) ->
diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl
index 31005a01e2..320b23bea1 100644
--- a/lib/kernel/test/heart_SUITE.erl
+++ b/lib/kernel/test/heart_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,7 +22,10 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2, start/1, restart/1,
- reboot/1, set_cmd/1, clear_cmd/1, get_cmd/1,
+ reboot/1,
+ node_start_immediately_after_crash/1,
+ node_start_soon_after_crash/1,
+ set_cmd/1, clear_cmd/1, get_cmd/1,
dont_drop/1, kill_pid/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -38,15 +41,15 @@ init_per_testcase(_Func, Config) ->
end_per_testcase(_Func, Config) ->
Nodes = nodes(),
lists:foreach(fun(X) ->
- NNam = list_to_atom(hd(string:tokens(atom_to_list(X),"@"))),
- case NNam of
- heart_test ->
- ?t:format(1, "WARNING: Killed ~p~n", [X]),
- rpc:cast(X, erlang, halt, []);
- _ ->
- ok
- end
- end, Nodes),
+ NNam = list_to_atom(hd(string:tokens(atom_to_list(X),"@"))),
+ case NNam of
+ heart_test ->
+ ?t:format(1, "WARNING: Killed ~p~n", [X]),
+ rpc:cast(X, erlang, halt, []);
+ _ ->
+ ok
+ end
+ end, Nodes),
Dog=?config(watchdog, Config),
test_server:timetrap_cancel(Dog).
@@ -57,8 +60,13 @@ end_per_testcase(_Func, Config) ->
%%-----------------------------------------------------------------
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
- [start, restart, reboot, set_cmd, clear_cmd, get_cmd, kill_pid].
+all() -> [
+ start, restart, reboot,
+ node_start_immediately_after_crash,
+ node_start_soon_after_crash,
+ set_cmd, clear_cmd, get_cmd,
+ kill_pid
+ ].
groups() ->
[].
@@ -75,22 +83,27 @@ init_per_suite(Config) when is_list(Config) ->
{win32, windows} ->
{skipped, "No use to run on Windows 95/98"};
_ ->
- Config
+ ignore_cores:init(Config)
end.
end_per_suite(Config) when is_list(Config) ->
- Config.
+ ignore_cores:fini(Config).
+
start_check(Type, Name) ->
+ start_check(Type, Name, []).
+start_check(Type, Name, Envs) ->
Args = case ?t:os_type() of
- {win32,_} -> "-heart -env HEART_COMMAND no_reboot";
- _ -> "-heart"
- end,
+ {win32,_} ->
+ "-heart " ++ env_encode([{"HEART_COMMAND", no_reboot}|Envs]);
+ _ ->
+ "-heart " ++ env_encode(Envs)
+ end,
{ok, Node} = case Type of
- loose ->
- loose_node:start(Name, Args, ?DEFAULT_TIMEOUT_SECS);
- _ ->
- ?t:start_node(Name, Type, [{args, Args}])
- end,
+ loose ->
+ loose_node:start(Name, Args, ?DEFAULT_TIMEOUT_SECS);
+ _ ->
+ ?t:start_node(Name, Type, [{args, Args}])
+ end,
erlang:monitor_node(Node, true),
case rpc:call(Node, erlang, whereis, [heart]) of
Pid when is_pid(Pid) ->
@@ -103,21 +116,19 @@ start_check(Type, Name) ->
start(doc) -> [];
start(suite) -> {req, [{time, 10}]};
start(Config) when is_list(Config) ->
- ?line {ok, Node} = start_check(slave, heart_test),
- ?line rpc:call(Node, init, reboot, []),
+ {ok, Node} = start_check(slave, heart_test),
+ rpc:call(Node, init, reboot, []),
receive
- {nodedown, Node} ->
- ok
- after 2000 ->
- test_server:fail(node_not_closed)
+ {nodedown, Node} -> ok
+ after 2000 -> test_server:fail(node_not_closed)
end,
test_server:sleep(5000),
- ?line case net_adm:ping(Node) of
- pang ->
- ok;
- _ ->
- test_server:fail(node_rebooted)
- end,
+ case net_adm:ping(Node) of
+ pang ->
+ ok;
+ _ ->
+ test_server:fail(node_rebooted)
+ end,
test_server:stop_node(Node).
%% Also test fixed bug in R1B (it was not possible to
@@ -125,6 +136,10 @@ start(Config) when is_list(Config) ->
%% Slave executes erlang:halt() on master nodedown.
%% Therefore the slave process has to be killed
%% before restart.
+
+%% restart
+%% Purpose:
+%% Check that a node is up and running after a init:restart/0
restart(doc) -> [];
restart(suite) ->
case ?t:os_type() of
@@ -134,8 +149,8 @@ restart(suite) ->
{skip, "Only run on unix and win32"}
end;
restart(Config) when is_list(Config) ->
- ?line {ok, Node} = start_check(loose, heart_test),
- ?line rpc:call(Node, init, restart, []),
+ {ok, Node} = start_check(loose, heart_test),
+ rpc:call(Node, init, restart, []),
receive
{nodedown, Node} ->
ok
@@ -143,32 +158,21 @@ restart(Config) when is_list(Config) ->
test_server:fail(node_not_closed)
end,
test_server:sleep(5000),
-
- ?line case net_adm:ping(Node) of
- pong ->
- erlang:monitor_node(Node, true),
- ?line rpc:call(Node, init, stop, []),
- receive
- {nodedown, Node} ->
- ok
- after 2000 ->
- test_server:fail(node_not_closed2)
- end,
- ok;
- _ ->
- test_server:fail(node_not_restarted)
- end,
+ node_check_up_down(Node, 2000),
loose_node:stop(Node).
+%% reboot
+%% Purpose:
+%% Check that a node is up and running after a init:reboot/0
reboot(doc) -> [];
reboot(suite) -> {req, [{time, 10}]};
reboot(Config) when is_list(Config) ->
{ok, Node} = start_check(slave, heart_test),
- ?line ok = rpc:call(Node, heart, set_cmd,
+ ok = rpc:call(Node, heart, set_cmd,
[atom_to_list(lib:progname()) ++
" -noshell -heart " ++ name(Node) ++ "&"]),
- ?line rpc:call(Node, init, reboot, []),
+ rpc:call(Node, init, reboot, []),
receive
{nodedown, Node} ->
ok
@@ -176,44 +180,142 @@ reboot(Config) when is_list(Config) ->
test_server:fail(node_not_closed)
end,
test_server:sleep(5000),
- ?line case net_adm:ping(Node) of
- pong ->
- erlang:monitor_node(Node, true),
- ?line rpc:call(Node, init, reboot, []),
- receive
- {nodedown, Node} ->
- ok
- after 2000 ->
- test_server:fail(node_not_closed2)
- end,
- ok;
- _ ->
- test_server:fail(node_not_rebooted)
- end,
+ node_check_up_down(Node, 2000),
ok.
+%% node_start_immediately_after_crash
+%% Purpose:
+%% Check that a node is up and running after a crash.
+%% This test exhausts the atom table on the remote node.
+%% ERL_CRASH_DUMP_SECONDS=0 will force beam not to dump an erl_crash.dump.
+%% May currently dump core in beam debug build due to lock-order violation
+%% This should be removed when a non-lockad information retriever is implemented
+%% for crash dumps
+node_start_immediately_after_crash(suite) -> {req, [{time, 10}]};
+node_start_immediately_after_crash(Config) when is_list(Config) ->
+ Config2 = ignore_cores:setup(?MODULE, node_start_immediately_after_crash, Config, true),
+ try
+ node_start_immediately_after_crash_test(Config2)
+ after
+ ignore_cores:restore(Config2)
+ end.
+
+
+node_start_immediately_after_crash_test(Config) when is_list(Config) ->
+ {ok, Node} = start_check(loose, heart_test_imm, [{"ERL_CRASH_DUMP_SECONDS", "0"}]),
+
+ ok = rpc:call(Node, heart, set_cmd,
+ [atom_to_list(lib:progname()) ++
+ " -noshell -heart " ++ name(Node) ++ "&"]),
+
+ Mod = exhaust_atoms,
+
+ Code = generate(Mod, [], [
+ "do() -> "
+ " Set = lists:seq($a,$z), "
+ " [ list_to_atom([A,B,C,D,E]) || "
+ " A <- Set, B <- Set, C <- Set, E <- Set, D <- Set ]."
+ ]),
+
+ %% crash it with atom exhaustion
+ rpc:call(Node, erlang, load_module, [Mod, Code]),
+ rpc:cast(Node, Mod, do, []),
+
+ T0 = now(),
+
+ receive {nodedown, Node} ->
+ test_server:format("Took ~.2f s. for node to go down~n", [timer:now_diff(now(), T0)/1000000]),
+ ok
+ %% timeout is very liberal here. nodedown is received in about 1 s. on linux (palantir)
+ %% and in about 10 s. on solaris (carcharoth)
+ after (15000*test_server:timetrap_scale_factor()) -> test_server:fail(node_not_closed)
+ end,
+ test_server:sleep(3000),
+ node_check_up_down(Node, 2000),
+ loose_node:stop(Node).
+
+%% node_start_soon_after_crash
+%% Purpose:
+%% Check that a node is up and running after a crash.
+%% This test exhausts the atom table on the remote node.
+%% ERL_CRASH_DUMP_SECONDS=10 will force beam
+%% to only dump an erl_crash.dump for 10 seconds.
+%% May currently dump core in beam debug build due to lock-order violation
+%% This should be removed when a non-lockad information retriever is implemented
+%% for crash dumps
+node_start_soon_after_crash(suite) -> {req, [{time, 10}]};
+node_start_soon_after_crash(Config) when is_list(Config) ->
+ Config2 = ignore_cores:setup(?MODULE, node_start_soon_after_crash, Config, true),
+ try
+ node_start_soon_after_crash_test(Config2)
+ after
+ ignore_cores:restore(Config2)
+ end.
+
+node_start_soon_after_crash_test(Config) when is_list(Config) ->
+ {ok, Node} = start_check(loose, heart_test_soon, [{"ERL_CRASH_DUMP_SECONDS", "10"}]),
+
+ ok = rpc:call(Node, heart, set_cmd,
+ [atom_to_list(lib:progname()) ++
+ " -noshell -heart " ++ name(Node) ++ "&"]),
+
+ Mod = exhaust_atoms,
+
+ Code = generate(Mod, [], [
+ "do() -> "
+ " Set = lists:seq($a,$z), "
+ " [ list_to_atom([A,B,C,D,E]) || "
+ " A <- Set, B <- Set, C <- Set, E <- Set, D <- Set ]."
+ ]),
+
+ %% crash it with atom exhaustion
+ rpc:call(Node, erlang, load_module, [Mod, Code]),
+ rpc:cast(Node, Mod, do, []),
+
+ receive {nodedown, Node} -> ok
+ after (15000*test_server:timetrap_scale_factor()) -> test_server:fail(node_not_closed)
+ end,
+ test_server:sleep(20000),
+ node_check_up_down(Node, 15000),
+ loose_node:stop(Node).
+
+
+node_check_up_down(Node, Tmo) ->
+ case net_adm:ping(Node) of
+ pong ->
+ erlang:monitor_node(Node, true),
+ rpc:call(Node, init, reboot, []),
+ receive
+ {nodedown, Node} -> ok
+ after Tmo ->
+ test_server:fail(node_not_closed2)
+ end;
+ _ ->
+ test_server:fail(node_not_rebooted)
+ end.
+
%% Only tests bad command, correct behaviour is tested in reboot/1.
set_cmd(suite) -> [];
set_cmd(Config) when is_list(Config) ->
- ?line {ok, Node} = start_check(slave, heart_test),
+ {ok, Node} = start_check(slave, heart_test),
Cmd = wrong_atom,
- ?line {error, {bad_cmd, Cmd}} = rpc:call(Node, heart, set_cmd, [Cmd]),
+ {error, {bad_cmd, Cmd}} = rpc:call(Node, heart, set_cmd, [Cmd]),
Cmd1 = lists:duplicate(2047, $a),
- ?line {error, {bad_cmd, Cmd1}} = rpc:call(Node, heart, set_cmd, [Cmd1]),
+ {error, {bad_cmd, Cmd1}} = rpc:call(Node, heart, set_cmd, [Cmd1]),
Cmd2 = lists:duplicate(28, $a),
- ?line ok = rpc:call(Node, heart, set_cmd, [Cmd2]),
+ ok = rpc:call(Node, heart, set_cmd, [Cmd2]),
Cmd3 = lists:duplicate(2000, $a),
- ?line ok = rpc:call(Node, heart, set_cmd, [Cmd3]),
+ ok = rpc:call(Node, heart, set_cmd, [Cmd3]),
stop_node(Node),
ok.
clear_cmd(suite) -> {req,[{time,15}]};
clear_cmd(Config) when is_list(Config) ->
- ?line {ok, Node} = start_check(slave, heart_test),
- ?line ok = rpc:call(Node, heart, set_cmd,
+ {ok, Node} = start_check(slave, heart_test),
+ ok = rpc:call(Node, heart, set_cmd,
[atom_to_list(lib:progname()) ++
" -noshell -heart " ++ name(Node) ++ "&"]),
- ?line rpc:call(Node, init, reboot, []),
+ rpc:call(Node, init, reboot, []),
receive
{nodedown, Node} ->
ok
@@ -221,16 +323,16 @@ clear_cmd(Config) when is_list(Config) ->
test_server:fail(node_not_closed)
end,
test_server:sleep(5000),
- ?line case net_adm:ping(Node) of
- pong ->
- erlang:monitor_node(Node, true);
- _ ->
- test_server:fail(node_not_rebooted)
- end,
- ?line ok = rpc:call(Node, heart, set_cmd,
+ case net_adm:ping(Node) of
+ pong ->
+ erlang:monitor_node(Node, true);
+ _ ->
+ test_server:fail(node_not_rebooted)
+ end,
+ ok = rpc:call(Node, heart, set_cmd,
["erl -noshell -heart " ++ name(Node) ++ "&"]),
- ?line ok = rpc:call(Node, heart, clear_cmd, []),
- ?line rpc:call(Node, init, reboot, []),
+ ok = rpc:call(Node, heart, clear_cmd, []),
+ rpc:call(Node, init, reboot, []),
receive
{nodedown, Node} ->
ok
@@ -238,20 +340,20 @@ clear_cmd(Config) when is_list(Config) ->
test_server:fail(node_not_closed)
end,
test_server:sleep(5000),
- ?line case net_adm:ping(Node) of
- pang ->
- ok;
- _ ->
- test_server:fail(node_rebooted)
- end,
+ case net_adm:ping(Node) of
+ pang ->
+ ok;
+ _ ->
+ test_server:fail(node_rebooted)
+ end,
ok.
get_cmd(suite) -> [];
get_cmd(Config) when is_list(Config) ->
- ?line {ok, Node} = start_check(slave, heart_test),
+ {ok, Node} = start_check(slave, heart_test),
Cmd = "test",
- ?line ok = rpc:call(Node, heart, set_cmd, [Cmd]),
- ?line {ok, Cmd} = rpc:call(Node, heart, get_cmd, []),
+ ok = rpc:call(Node, heart, set_cmd, [Cmd]),
+ {ok, Cmd} = rpc:call(Node, heart, get_cmd, []),
stop_node(Node),
ok.
@@ -269,57 +371,53 @@ dont_drop(Config) when is_list(Config) ->
[ok,ok,ok,ok,ok,ok,ok,ok,ok,ok] = do_dont_drop(Config,10),
ok.
-do_dont_drop(_,0) ->
- [];
+do_dont_drop(_,0) -> [];
do_dont_drop(Config,N) ->
%% Name of first slave node
- ?line NN1 = atom_to_list(?MODULE) ++ "slave_1",
+ NN1 = atom_to_list(?MODULE) ++ "slave_1",
%% Name of node started by heart on failure
- ?line NN2 = atom_to_list(?MODULE) ++ "slave_2",
+ NN2 = atom_to_list(?MODULE) ++ "slave_2",
%% Name of node started by heart on success
- ?line NN3 = atom_to_list(?MODULE) ++ "slave_3",
- ?line Host = hd(tl(string:tokens(atom_to_list(node()),"@"))),
+ NN3 = atom_to_list(?MODULE) ++ "slave_3",
+ Host = hd(tl(string:tokens(atom_to_list(node()),"@"))),
%% The initial heart command
- ?line FirstCmd = erl() ++ name(NN2 ++ "@" ++ Host),
+ FirstCmd = erl() ++ name(NN2 ++ "@" ++ Host),
%% Separated the parameters to start_node_run for clarity...
- ?line Name = list_to_atom(NN1),
- ?line Env = [{"HEART_COMMAND", FirstCmd}],
- ?line Func = "start_heart_stress",
- ?line Arg = NN3 ++ "@" ++ Host ++ " " ++
+ Name = list_to_atom(NN1),
+ Env = [{"HEART_COMMAND", FirstCmd}],
+ Func = "start_heart_stress",
+ Arg = NN3 ++ "@" ++ Host ++ " " ++
filename:join(?config(data_dir, Config), "simple_echo"),
- ?line start_node_run(Name,Env,Func,Arg),
- ?line case wait_for_any_of(list_to_atom(NN2 ++ "@" ++ Host),
- list_to_atom(NN3 ++ "@" ++ Host)) of
- 2 ->
- ?line [ok | do_dont_drop(Config,N-1)];
- _ ->
- ?line false
- end.
+ start_node_run(Name,Env,Func,Arg),
+ case wait_for_any_of(list_to_atom(NN2 ++ "@" ++ Host),
+ list_to_atom(NN3 ++ "@" ++ Host)) of
+ 2 ->
+ [ok | do_dont_drop(Config,N-1)];
+ _ ->
+ false
+ end.
wait_for_any_of(N1,N2) ->
- ?line wait_for_any_of(N1,N2,45).
+ wait_for_any_of(N1,N2,45).
wait_for_any_of(_N1,_N2,0) ->
- ?line false;
+ false;
wait_for_any_of(N1,N2,Times) ->
- ?line receive
- after 1000 ->
- ?line ok
- end,
- ?line case net_adm:ping(N1) of
- pang ->
- ?line case net_adm:ping(N2) of
- pang ->
- ?line wait_for_any_of(N1,N2,Times - 1);
- pong ->
- ?line rpc:call(N2,init,stop,[]),
- ?line 2
- end;
- pong ->
- ?line rpc:call(N1,init,stop,[]),
- ?line 1
- end.
+ receive after 1000 -> ok end,
+ case net_adm:ping(N1) of
+ pang ->
+ case net_adm:ping(N2) of
+ pang ->
+ wait_for_any_of(N1,N2,Times - 1);
+ pong ->
+ rpc:call(N2,init,stop,[]),
+ 2
+ end;
+ pong ->
+ rpc:call(N1,init,stop,[]),
+ 1
+ end.
kill_pid(suite) ->
@@ -336,9 +434,7 @@ do_kill_pid(_Config) ->
{ok,Node} = start_node_run(Name,Env,suicide_by_heart,[]),
ok = wait_for_node(Node,15),
erlang:monitor_node(Node, true),
- receive
- {nodedown,Node} ->
- ok
+ receive {nodedown,Node} -> ok
after 30000 ->
false
end.
@@ -346,23 +442,16 @@ do_kill_pid(_Config) ->
wait_for_node(_,0) ->
false;
wait_for_node(Node,N) ->
- receive
- after 1000 ->
- ok
- end,
+ receive after 1000 -> ok end,
case net_adm:ping(Node) of
- pong ->
- ok;
- pang ->
- wait_for_node(Node,N-1)
+ pong -> ok;
+ pang -> wait_for_node(Node,N-1)
end.
erl() ->
case os:type() of
- {win32,_} ->
- "werl ";
- _ ->
- "erl "
+ {win32,_} -> "werl ";
+ _ -> "erl "
end.
name(Node) when is_list(Node) -> name(Node,[]);
@@ -379,15 +468,13 @@ name([H|T], Name) ->
name(T, [H|Name]).
-atom_conv(A) when is_atom(A) ->
- atom_to_list(A);
-atom_conv(A) when is_list(A) ->
- A.
+enc(A) when is_atom(A) -> atom_to_list(A);
+enc(A) when is_binary(A) -> binary_to_list(A);
+enc(A) when is_list(A) -> A.
-env_conv([]) ->
- [];
-env_conv([{X,Y}|T]) ->
- atom_conv(X) ++ " \"" ++ atom_conv(Y) ++ "\" " ++ env_conv(T).
+env_encode([]) -> [];
+env_encode([{X,Y}|T]) ->
+ "-env " ++ enc(X) ++ " \"" ++ enc(Y) ++ "\" " ++ env_encode(T).
%%%
%%% Starts a node and runs a function in this
@@ -398,12 +485,12 @@ env_conv([{X,Y}|T]) ->
%%% Argument is the argument(s) to send through erl -s
%%%
start_node_run(Name, Env, Function, Argument) ->
- ?line PA = filename:dirname(code:which(?MODULE)),
- ?line Params = "-heart -env " ++ env_conv(Env) ++ " -pa " ++ PA ++
- " -s " ++
- atom_conv(?MODULE) ++ " " ++ atom_conv(Function) ++ " " ++
- atom_conv(Argument),
- ?line start_node(Name, Params).
+ PA = filename:dirname(code:which(?MODULE)),
+ Params = "-heart " ++ env_encode(Env) ++ " -pa " ++ PA ++
+ " -s " ++
+ enc(?MODULE) ++ " " ++ enc(Function) ++ " " ++
+ enc(Argument),
+ start_node(Name, Params).
start_node(Name, Param) ->
test_server:start_node(Name, slave, [{args, Param}]).
@@ -469,3 +556,24 @@ suicide_by_heart() ->
{makaronipudding} ->
sallad
end.
+
+
+%% generate a module from binary
+generate(Module, Attributes, FunStrings) ->
+ FunForms = function_forms(FunStrings),
+ Forms = [
+ {attribute,1,module,Module},
+ {attribute,2,export,[FA || {FA,_} <- FunForms]}
+ ] ++ [{attribute, 3, A, V}|| {A, V} <- Attributes] ++
+ [ Function || {_, Function} <- FunForms],
+ {ok, Module, Bin} = compile:forms(Forms),
+ Bin.
+
+
+function_forms([]) -> [];
+function_forms([S|Ss]) ->
+ {ok, Ts,_} = erl_scan:string(S),
+ {ok, Form} = erl_parse:parse_form(Ts),
+ Fun = element(3, Form),
+ Arity = element(4, Form),
+ [{{Fun,Arity}, Form}|function_forms(Ss)].
diff --git a/lib/kernel/test/ignore_cores.erl b/lib/kernel/test/ignore_cores.erl
new file mode 100644
index 0000000000..8b1ac0fe6c
--- /dev/null
+++ b/lib/kernel/test/ignore_cores.erl
@@ -0,0 +1,158 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : ignore_cores.erl
+%%% Author : Rickard Green <[email protected]>
+%%% Description :
+%%%
+%%% Created : 11 Feb 2008 by Rickard Green <[email protected]>
+%%%-------------------------------------------------------------------
+
+-module(ignore_cores).
+
+-include_lib("test_server/include/test_server.hrl").
+
+-export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]).
+
+-record(ignore_cores, {org_cwd,
+ org_path,
+ org_pwd_env,
+ ign_dir = false,
+ cores_dir = false}).
+
+%%
+%% Takes a testcase config
+%%
+
+init(Config) ->
+ {ok, OrgCWD} = file:get_cwd(),
+ [{ignore_cores,
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = code:get_path(),
+ org_pwd_env = os:getenv("PWD")}}
+ | lists:keydelete(ignore_cores, 1, Config)].
+
+fini(Config) ->
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ ok = file:set_cwd(OrgCWD),
+ true = code:set_path(OrgPath),
+ case OrgPWD of
+ false -> ok;
+ _ -> true = os:putenv("PWD", OrgPWD)
+ end,
+ lists:keydelete(ignore_cores, 1, Config).
+
+setup(Suite, Testcase, Config) ->
+ setup(Suite, Testcase, Config, false).
+
+setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite),
+ is_atom(Testcase),
+ is_list(Config) ->
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ Path = lists:map(fun (".") -> OrgCWD; (Dir) -> Dir end, OrgPath),
+ true = code:set_path(Path),
+ PrivDir = ?config(priv_dir, Config),
+ IgnDir = filename:join([PrivDir,
+ atom_to_list(Suite)
+ ++ "_"
+ ++ atom_to_list(Testcase)
+ ++ "_wd"]),
+ ok = file:make_dir(IgnDir),
+ case SetCwd of
+ false ->
+ ok;
+ _ ->
+ ok = file:set_cwd(IgnDir),
+ OrgPWD = case os:getenv("PWD") of
+ false -> false;
+ PWD ->
+ os:putenv("PWD", IgnDir),
+ PWD
+ end
+ end,
+ ok = file:write_file(filename:join([IgnDir, "ignore_core_files"]), <<>>),
+ %% cores are dumped in /cores on MacOS X
+ CoresDir = case {?t:os_type(), filelib:is_dir("/cores")} of
+ {{unix,darwin}, true} ->
+ filelib:fold_files("/cores",
+ "^core.*$",
+ false,
+ fun (C,Cs) -> [C|Cs] end,
+ []);
+ _ ->
+ false
+ end,
+ lists:keyreplace(ignore_cores,
+ 1,
+ Config,
+ {ignore_cores,
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD,
+ ign_dir = IgnDir,
+ cores_dir = CoresDir}}).
+
+restore(Config) ->
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD,
+ ign_dir = IgnDir,
+ cores_dir = CoresDir} = ?config(ignore_cores, Config),
+ try
+ case CoresDir of
+ false ->
+ ok;
+ _ ->
+ %% Move cores dumped by these testcases in /cores
+ %% to cwd.
+ lists:foreach(fun (C) ->
+ case lists:member(C, CoresDir) of
+ true -> ok;
+ _ ->
+ Dst = filename:join(
+ [IgnDir,
+ filename:basename(C)]),
+ {ok, _} = file:copy(C, Dst),
+ file:delete(C)
+ end
+ end,
+ filelib:fold_files("/cores",
+ "^core.*$",
+ false,
+ fun (C,Cs) -> [C|Cs] end,
+ []))
+ end
+ after
+ catch file:set_cwd(OrgCWD),
+ catch code:set_path(OrgPath),
+ case OrgPWD of
+ false -> ok;
+ _ -> catch os:putenv("PWD", OrgPWD)
+ end
+ end.
+
+
+dir(Config) ->
+ #ignore_cores{ign_dir = Dir} = ?config(ignore_cores, Config),
+ Dir.
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index ce138b6804..e5e1794514 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -37,7 +37,8 @@
gethostnative_soft_restart/0, gethostnative_soft_restart/1,
gethostnative_debug_level/0, gethostnative_debug_level/1,
getif/1,
- getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1]).
+ getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1,
+ parse_strict_address/1]).
-export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1,
kill_gethost/0, parallell_gethost/0]).
@@ -52,7 +53,7 @@ all() ->
t_gethostnative, gethostnative_parallell, cname_loop,
gethostnative_debug_level, gethostnative_soft_restart,
getif, getif_ifr_name_overflow, getservbyname_overflow,
- getifaddrs].
+ getifaddrs, parse_strict_address].
groups() ->
[{parse, [], [parse_hosts, parse_address]}].
@@ -582,16 +583,16 @@ parse_address(Config) when is_list(Config) ->
"fe80::198.168.0.",
"fec0::fFfF:127.0.0.1."],
t_parse_address
- (ipv6_address,
+ (parse_ipv6_address,
V6Strict++V6Sloppy++V6Err++V4Err),
t_parse_address
- (ipv6strict_address,
+ (parse_ipv6strict_address,
V6Strict++V6Err++V4Err++[S || {_,S} <- V6Sloppy]),
t_parse_address
- (ipv4_address,
+ (parse_ipv4_address,
V4Strict++V4Sloppy++V4Err++V6Err++[S || {_,S} <- V6Strict]),
t_parse_address
- (ipv4strict_address,
+ (parse_ipv4strict_address,
V4Strict++V4Err++V6Err++[S || {_,S} <- V4Sloppy++V6Strict]).
t_parse_address(Func, []) ->
@@ -599,14 +600,16 @@ t_parse_address(Func, []) ->
ok;
t_parse_address(Func, [{Addr,String}|L]) ->
io:format("~p = ~p.~n", [Addr,String]),
- {ok,Addr} = inet_parse:Func(String),
+ {ok,Addr} = inet:Func(String),
t_parse_address(Func, L);
t_parse_address(Func, [String|L]) ->
io:format("~p.~n", [String]),
- {error,einval} = inet_parse:Func(String),
+ {error,einval} = inet:Func(String),
t_parse_address(Func, L).
-
+parse_strict_address(Config) when is_list(Config) ->
+ {ok, Ipv4} = inet:parse_strict_address("127.0.0.1"),
+ {ok, Ipv6} = inet:parse_strict_address("c11:0c22:5c33:c440:55c0:c66c:77:0088").
t_gethostnative(suite) ->[];
t_gethostnative(doc) ->[];
diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl
index 087ae6055b..75496ce745 100644
--- a/lib/kernel/test/inet_sockopt_SUITE.erl
+++ b/lib/kernel/test/inet_sockopt_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -53,6 +53,8 @@
simple/1, loop_all/1, simple_raw/1, simple_raw_getbin/1,
doc_examples_raw/1,doc_examples_raw_getbin/1,
large_raw/1,large_raw_getbin/1,combined/1,combined_getbin/1,
+ ipv6_v6only_udp/1, ipv6_v6only_tcp/1, ipv6_v6only_sctp/1,
+ use_ipv6_v6only_udp/1,
type_errors/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -64,6 +66,8 @@ all() ->
[simple, loop_all, simple_raw, simple_raw_getbin,
doc_examples_raw, doc_examples_raw_getbin, large_raw,
large_raw_getbin, combined, combined_getbin,
+ ipv6_v6only_udp, ipv6_v6only_tcp, ipv6_v6only_sctp,
+ use_ipv6_v6only_udp,
type_errors].
groups() ->
@@ -127,7 +131,7 @@ loop_all(Config) when is_list(Config) ->
io_lib:format("Non mandatory failed:~w",
[Failed]))}
end.
-
+
simple_raw(suite) -> [];
@@ -461,6 +465,153 @@ do_combined(Config,Binary) when is_list(Config) ->
ok
end.
+
+
+ipv6_v6only_udp(suite) -> [];
+ipv6_v6only_udp(doc) -> "Test socket option ipv6_v6only for UDP";
+ipv6_v6only_udp(Config) when is_list(Config) ->
+ ipv6_v6only(Config, gen_udp).
+
+ipv6_v6only_tcp(suite) -> [];
+ipv6_v6only_tcp(doc) -> "Test socket option ipv6_v6only for TCP";
+ipv6_v6only_tcp(Config) when is_list(Config) ->
+ ipv6_v6only(Config, gen_tcp).
+
+ipv6_v6only_sctp(suite) -> [];
+ipv6_v6only_sctp(doc) -> "Test socket option ipv6_v6only for SCTP";
+ipv6_v6only_sctp(Config) when is_list(Config) ->
+ ipv6_v6only(Config, gen_sctp).
+
+ipv6_v6only(Config, Module) when is_list(Config) ->
+ ?line case ipv6_v6only_open(Module, []) of
+ {ok,S1} ->
+ ?line case inet:getopts(S1, [ipv6_v6only]) of
+ {ok,[{ipv6_v6only,Default}]}
+ when is_boolean(Default) ->
+ ?line ok =
+ ipv6_v6only_close(Module, S1),
+ ?line ipv6_v6only(Config, Module, Default);
+ {ok,[]} ->
+ ?line io:format("Not implemented.~n", []),
+ %% This list of OS:es where the option is
+ %% supposed to be not implemented is just
+ %% a guess, and may grow with time.
+ ?line case {os:type(),os:version()} of
+ {{unix,linux},{2,M,_}}
+ when M =< 4 -> ok
+ end,
+ %% At least this should work
+ ?line {ok,S2} =
+ ipv6_v6only_open(
+ Module,
+ [{ipv6_v6only,true}]),
+ ?line ok =
+ ipv6_v6only_close(Module, S2)
+ end;
+ {error,_} ->
+ {skipped,"Socket type not supported"}
+ end.
+
+ipv6_v6only(Config, Module, Default) when is_list(Config) ->
+ ?line io:format("Default ~w.~n", [Default]),
+ ?line {ok,S1} =
+ ipv6_v6only_open(Module, [{ipv6_v6only,Default}]),
+ ?line {ok,[{ipv6_v6only,Default}]} =
+ inet:getopts(S1, [ipv6_v6only]),
+ ?line ok =
+ ipv6_v6only_close(Module, S1),
+ ?line NotDefault = not Default,
+ ?line case ipv6_v6only_open(Module, [{ipv6_v6only,NotDefault}]) of
+ {ok,S2} ->
+ ?line io:format("Read-write.~n", []),
+ ?line {ok,[{ipv6_v6only,NotDefault}]} =
+ inet:getopts(S2, [ipv6_v6only]),
+ ok;
+ {error,einval} ->
+ ?line io:format("Read-only.~n", []),
+ %% This option is known to be read-only and true
+ %% on Windows and OpenBSD
+ ?line case os:type() of
+ {unix,openbsd} when Default =:= true -> ok;
+ {win32,_} when Default =:= true -> ok
+ end
+ end.
+
+ipv6_v6only_open(Module, Opts) ->
+ Module:case Module of
+ gen_tcp -> listen;
+ _ -> open
+ end(0, [inet6|Opts]).
+
+ipv6_v6only_close(Module, Socket) ->
+ Module:close(Socket).
+
+
+use_ipv6_v6only_udp(suite) -> [];
+use_ipv6_v6only_udp(doc) -> "Test using socket option ipv6_v6only for UDP";
+use_ipv6_v6only_udp(Config) when is_list(Config) ->
+ ?line case gen_udp:open(0, [inet6,{ipv6_v6only,true}]) of
+ {ok,S6} ->
+ ?line case inet:getopts(S6, [ipv6_v6only]) of
+ {ok,[{ipv6_v6only,true}]} ->
+ use_ipv6_v6only_udp(Config, S6);
+ {ok,Other} ->
+ {skipped,{getopts,Other}}
+ end;
+ {error,_} ->
+ {skipped,"Socket type not supported"}
+ end.
+
+use_ipv6_v6only_udp(_Config, S6) ->
+ ?line {ok,Port} = inet:port(S6),
+ ?line {ok,S4} = gen_udp:open(Port, [inet]),
+ ?line E6 = " IPv6-echo.",
+ ?line E4 = " IPv4-echo.",
+ ?line Sender =
+ spawn_link(fun () -> use_ipv6_v6only_udp_sender(Port, E6, E4) end),
+ ?line use_ipv6_v6only_udp_listener(
+ S6, S4, E6, E4, monitor(process, Sender)).
+
+use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref) ->
+ ?line receive
+ {udp,S6,IP,P,Data} ->
+ ?line ok = gen_udp:send(S6, IP, P, [Data|E6]),
+ ?line use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref);
+ {udp,S4,IP,P,Data} ->
+ ?line ok = gen_udp:send(S4, IP, P, [Data|E4]),
+ ?line use_ipv6_v6only_udp_listener(S6, S4, E6, E4, Mref);
+ {'DOWN',Mref,_,_,normal} ->
+ ok;
+ {'DOWN',Mref,_,_,Result} ->
+ %% Since we are linked we will never arrive here
+ Result;
+ Other ->
+ ?line exit({failed,{listener_unexpected,Other}})
+ end.
+
+use_ipv6_v6only_udp_sender(Port, E6, E4) ->
+ D6 = "IPv6-send.",
+ D4 = "IPv4-send.",
+ R6 = D6 ++ E6,
+ R4 = D4 ++ E4,
+ R6 = sndrcv({0,0,0,0,0,0,0,1}, Port, [inet6], D6),
+ R4 = sndrcv({127,0,0,1}, Port, [inet], D4),
+ ok.
+
+sndrcv(Ip, Port, Opts, Data) ->
+ {ok,S} = gen_udp:open(0, Opts),
+ io:format("[~w:~w] ! ~s~n", [Ip,Port,Data]),
+ ok = gen_udp:send(S, Ip, Port, Data),
+ receive
+ {udp,S,Ip,Port,RecData} ->
+ io:format("[~w:~w] : ~s~n", [Ip,Port,RecData]),
+ RecData;
+ Other ->
+ exit({failed,{sndrcv_unexpectec,Other}})
+ end.
+
+
+
type_errors(suite) ->
[];
type_errors(doc) ->
diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl
index 4787f19250..36e13cec26 100644
--- a/lib/kernel/test/interactive_shell_SUITE.erl
+++ b/lib/kernel/test/interactive_shell_SUITE.erl
@@ -29,20 +29,11 @@
-export([toerl_server/3]).
init_per_testcase(_Func, Config) ->
- Dog = test_server:timetrap(test_server:seconds(60)),
- Term = case os:getenv("TERM") of
- List when is_list(List) ->
- List;
- _ ->
- "dumb"
- end,
- os:putenv("TERM","vt100"),
- [{watchdog,Dog},{term,Term}|Config].
+ Dog = test_server:timetrap(test_server:minutes(3)),
+ [{watchdog,Dog}|Config].
end_per_testcase(_Func, Config) ->
Dog = ?config(watchdog, Config),
- Term = ?config(term,Config),
- os:putenv("TERM",Term),
test_server:timetrap_cancel(Dog).
@@ -56,9 +47,19 @@ groups() ->
[].
init_per_suite(Config) ->
- Config.
+ Term = case os:getenv("TERM") of
+ List when is_list(List) ->
+ List;
+ _ ->
+ "dumb"
+ end,
+ os:putenv("TERM","vt100"),
+ DefShell = get_default_shell(),
+ [{default_shell,DefShell},{term,Term}|Config].
-end_per_suite(_Config) ->
+end_per_suite(Config) ->
+ Term = ?config(term,Config),
+ os:putenv("TERM",Term),
ok.
init_per_group(_GroupName, Config) ->
@@ -78,70 +79,118 @@ end_per_group(_GroupName, Config) ->
get_columns_and_rows(suite) -> [];
get_columns_and_rows(doc) -> ["Test that the shell can access columns and rows"];
get_columns_and_rows(Config) when is_list(Config) ->
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
-%% Behaviour change in R12B-5, returns 80
-%% {getline,"{error,enotsup}"},
- {getline,"{ok,80}"},
- {putline,"io:rows()."},
-%% Behaviour change in R12B-5, returns 24
-%% {getline,"{error,enotsup}"}
- {getline,"{ok,24}"}
- ],[]),
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
- {getline,"{ok,90}"},
- {putline,"io:rows()."},
- {getline,"{ok,40}"}],
- [],
- "stty rows 40; stty columns 90; ").
+ case proplists:get_value(default_shell,Config) of
+ old ->
+ %% Old shell tests
+ ?dbg(old_shell),
+ ?line rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,"io:columns()."},
+ {getline_re,".*{error,enotsup}"},
+ {putline,"io:rows()."},
+ {getline_re,".*{error,enotsup}"}
+
+ ],[]),
+ ?line rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,"io:columns()."},
+ {getline_re,".*{ok,90}"},
+ {putline,"io:rows()."},
+ {getline_re,".*{ok,40}"}],
+ [],
+ "stty rows 40; stty columns 90; ");
+ new ->
+ % New shell tests
+ ?dbg(new_shell),
+ ?line rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,"io:columns()."},
+ %% Behaviour change in R12B-5, returns 80
+ %% {getline,"{error,enotsup}"},
+ {getline,"{ok,80}"},
+ {putline,"io:rows()."},
+ %% Behaviour change in R12B-5, returns 24
+ %% {getline,"{error,enotsup}"}
+ {getline,"{ok,24}"}
+ ],[]),
+ ?line rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,"io:columns()."},
+ {getline,"{ok,90}"},
+ {putline,"io:rows()."},
+ {getline,"{ok,40}"}],
+ [],
+ "stty rows 40; stty columns 90; ")
+ end.
exit_initial(suite) -> [];
exit_initial(doc) -> ["Tests that exit of initial shell restarts shell"];
exit_initial(Config) when is_list(Config) ->
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"exit()."},
- {getline,""},
- {getline,"Eshell"},
- {putline,""},
- {putline,"35."},
- {getline,"35"}],[]).
+ case proplists:get_value(default_shell,Config) of
+ old ->
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline_re, ".*2"},
+ {putline,"exit()."},
+ {getline,""},
+ {getline,"Eshell"},
+ {putline,""},
+ {putline,"35."},
+ {getline_re,".*35"}],[]);
+ new ->
+ rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,"exit()."},
+ {getline,""},
+ {getline,"Eshell"},
+ {putline,""},
+ {putline,"35."},
+ {getline_re,"35"}],[])
+ end.
job_control_local(suite) -> [];
job_control_local(doc) -> [ "Tests that local shell can be "
"started by means of job control" ];
job_control_local(Config) when is_list(Config) ->
- ?line rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,[7]},
- {sleep,timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"s"},
- {putline,"c"},
- {putline_raw,""},
- {getline,"Eshell"},
- {putline_raw,""},
- {getline,"1>"},
- {putline,"35."},
- {getline,"35"}],[]).
+ case proplists:get_value(default_shell,Config) of
+ old ->
+ %% Old shell tests
+ {skip,"No new shell found"};
+ new ->
+ %% New shell tests
+ ?line rtnode([{putline,""},
+ {putline, "2."},
+ {getline, "2"},
+ {putline,[7]},
+ {sleep,timeout(short)},
+ {putline,""},
+ {getline," -->"},
+ {putline,"s"},
+ {putline,"c"},
+ {putline_raw,""},
+ {getline,"Eshell"},
+ {putline_raw,""},
+ {getline,"1>"},
+ {putline,"35."},
+ {getline,"35"}],[])
+ end.
job_control_remote(suite) -> [];
job_control_remote(doc) -> [ "Tests that remote shell can be "
"started by means of job control" ];
job_control_remote(Config) when is_list(Config) ->
- case node() of
- nonode@nohost ->
+ case {node(),proplists:get_value(default_shell,Config)} of
+ {nonode@nohost,_} ->
?line exit(not_distributed);
+ {_,old} ->
+ {skip,"No new shell found"};
_ ->
?line RNode = create_nodename(),
?line MyNode = atom_to_list(node()),
@@ -190,9 +239,11 @@ job_control_remote_noshell(doc) ->
[ "Tests that remote shell can be "
"started by means of job control to -noshell node" ];
job_control_remote_noshell(Config) when is_list(Config) ->
- case node() of
- nonode@nohost ->
+ case {node(),proplists:get_value(default_shell,Config)} of
+ {nonode@nohost,_} ->
?line exit(not_distributed);
+ {_,old} ->
+ {skip,"No new shell found"};
_ ->
?line RNode = create_nodename(),
?line NSNode = start_noshell_node(interactive_shell_noshell),
@@ -351,6 +402,33 @@ get_and_put(CPid, [{getline, Match}|T],N) ->
end
end;
+%% Hey ho copy paste from stdlib/io_proto_SUITE
+get_and_put(CPid, [{getline_re, Match}|T],N) ->
+ ?dbg({getline_re, Match}),
+ CPid ! {self(), {get_line, timeout(normal)}},
+ receive
+ {get_line, timeout} ->
+ error_logger:error_msg("~p: getline_re timeout waiting for \"~s\" "
+ "(command number ~p, skipped: ~p)~n",
+ [?MODULE, Match,N,get(getline_skipped)]),
+ {error, timeout};
+ {get_line, Data} ->
+ ?dbg({data,Data}),
+ case re:run(Data, Match,[{capture,none}]) of
+ match ->
+ erase(getline_skipped),
+ get_and_put(CPid, T,N+1);
+ _ ->
+ case get(getline_skipped) of
+ undefined ->
+ put(getline_skipped,[Data]);
+ List ->
+ put(getline_skipped,List ++ [Data])
+ end,
+ get_and_put(CPid, [{getline_re, Match}|T],N)
+ end
+ end;
+
get_and_put(CPid, [{putline_raw, Line}|T],N) ->
?dbg({putline_raw, Line}),
CPid ! {self(), {send_line, Line}},
@@ -631,6 +709,13 @@ get_data_within(Port, Timeout, Acc) ->
timeout
end.
-
-
-
+get_default_shell() ->
+ try
+ rtnode([{putline,""},
+ {putline, "whereis(user_drv)."},
+ {getline, "undefined"}],[]),
+ old
+ catch E:R ->
+ ?dbg({E,R}),
+ new
+ end.
diff --git a/lib/kernel/test/kernel.cover b/lib/kernel/test/kernel.cover
index f6967ca651..af1dd7eaad 100644
--- a/lib/kernel/test/kernel.cover
+++ b/lib/kernel/test/kernel.cover
@@ -1,3 +1,3 @@
%% -*- erlang -*-
-{incl_mods,[gen_udp,inet6_udp,inet_res,inet_dns]}.
+{incl_app,kernel,details}.
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index a56746bbc4..4e93a593b3 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -57,6 +57,8 @@
%% System probe functions that might be handy to check from the shell
-export([unix_free/1]).
+-export([allocate/1]).
+
-include_lib("test_server/include/test_server.hrl").
-include_lib("kernel/include/file.hrl").
@@ -87,7 +89,7 @@ groups() ->
cur_dir_1a, cur_dir_1b]},
{files, [],
[{group, open}, {group, pos}, {group, file_info},
- truncate, sync, datasync, advise, large_write]},
+ truncate, sync, datasync, advise, large_write, allocate]},
{open, [],
[open1, modes, close, access, read_write, pread_write,
append, exclusive]},
@@ -1359,6 +1361,76 @@ check_large_write(Dog, Fd, _, _, []) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+allocate(suite) -> [];
+allocate(doc) -> "Tests that ?PRIM_FILE:allocate/3 at least doesn't crash.";
+allocate(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(5)),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Allocate = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_allocate.fil"),
+
+ Line1 = "Hello\n",
+ Line2 = "World!\n",
+
+ ?line {ok, Fd} = ?PRIM_FILE:open(Allocate, [write, binary]),
+ allocate_and_assert(Fd, 1, iolist_size([Line1, Line2])),
+ ?line ok = ?PRIM_FILE:write(Fd, Line1),
+ ?line ok = ?PRIM_FILE:write(Fd, Line2),
+ ?line ok = ?PRIM_FILE:close(Fd),
+
+ ?line {ok, Fd2} = ?PRIM_FILE:open(Allocate, [write, binary]),
+ allocate_and_assert(Fd2, 1, iolist_size(Line1)),
+ ?line ok = ?PRIM_FILE:write(Fd2, Line1),
+ ?line ok = ?PRIM_FILE:write(Fd2, Line2),
+ ?line ok = ?PRIM_FILE:close(Fd2),
+
+ ?line {ok, Fd3} = ?PRIM_FILE:open(Allocate, [write, binary]),
+ allocate_and_assert(Fd3, 1, iolist_size(Line1) + 1),
+ ?line ok = ?PRIM_FILE:write(Fd3, Line1),
+ ?line ok = ?PRIM_FILE:write(Fd3, Line2),
+ ?line ok = ?PRIM_FILE:close(Fd3),
+
+ ?line {ok, Fd4} = ?PRIM_FILE:open(Allocate, [write, binary]),
+ allocate_and_assert(Fd4, 1, 4 * iolist_size([Line1, Line2])),
+ ?line ok = ?PRIM_FILE:write(Fd4, Line1),
+ ?line ok = ?PRIM_FILE:write(Fd4, Line2),
+ ?line ok = ?PRIM_FILE:close(Fd4),
+
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+allocate_and_assert(Fd, Offset, Length) ->
+ % Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have
+ % any other negative side effect. We can't really asssert against a
+ % specific return value, because support for file space pre-allocation
+ % depends on the OS, OS version and underlying filesystem.
+ %
+ % The Linux kernel added support for fallocate() in version 2.6.23,
+ % which currently works only for the ext4, ocfs2, xfs and btrfs file
+ % systems. posix_fallocate() is available in glibc as of version
+ % 2.1.94, but it was buggy until glibc version 2.7.
+ %
+ % Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE.
+ %
+ % Solaris supports posix_fallocate() but only for the UFS file system
+ % apparently (not supported for ZFS).
+ %
+ % FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate().
+ %
+ % For Windows there's apparently no way to pre-allocate file space, at
+ % least with similar API/semantics as posix_fallocate(), fallocate() or
+ % fcntl F_PREALLOCATE.
+ Result = ?PRIM_FILE:allocate(Fd, Offset, Length),
+ case os:type() of
+ {win32, _} ->
+ ?line {error, enotsup} = Result;
+ _ ->
+ ?line _ = Result
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
delete_a(suite) -> [];
delete_a(doc) -> [];
delete_a(Config) when is_list(Config) ->
diff --git a/lib/kernel/test/ram_file_SUITE.erl b/lib/kernel/test/ram_file_SUITE.erl
index ab95a3ff5f..5c4437d4d3 100644
--- a/lib/kernel/test/ram_file_SUITE.erl
+++ b/lib/kernel/test/ram_file_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -167,7 +168,7 @@ pread_pwrite(suite) ->
pread_pwrite(doc) ->
["Test that pread/2,3 and pwrite/2,3 works."];
pread_pwrite(Config) when is_list(Config) ->
- ?line Str = "Flygande b�ckaziner s�ka hwila p� mjuqa tuvor x",
+ ?line Str = "Flygande bäckaziner söka hwila på mjuqa tuvor x",
?line Bin = list_to_binary(Str),
%%
pread_pwrite_test(?FILE_MODULE, Str, [ram, read, write]),
@@ -206,7 +207,7 @@ position(suite) ->
position(doc) ->
["Test that position/2 works."];
position(Config) when is_list(Config) ->
- ?line Str = "Att vara eller icke vara, det �r fr�gan. ",
+ ?line Str = "Att vara eller icke vara, det är frågan. ",
?line Bin = list_to_binary(Str),
%%
position_test(?FILE_MODULE, Str, [ram, read]),
@@ -287,8 +288,8 @@ truncate(suite) ->
truncate(doc) ->
["Test that truncate/1 works."];
truncate(Config) when is_list(Config) ->
- ?line Str = "M�n �dlare att lida och f�rdraga "
- ++ "ett bittert �des stygn av pilar, ",
+ ?line Str = "Mån ädlare att lida och fördraga "
+ ++ "ett bittert ödes stygn av pilar, ",
?line Bin = list_to_binary(Str),
%%
ok = truncate_test(?FILE_MODULE, Str, [ram, read, write]),
@@ -331,7 +332,7 @@ sync(suite) ->
sync(doc) ->
["Test that sync/1 at least does not crash."];
sync(Config) when is_list(Config) ->
- ?line Str = "�n att ta till vapen mot ett hav av kval. ",
+ ?line Str = "än att ta till vapen mot ett hav av kval. ",
?line Bin = list_to_binary(Str),
%%
sync_test(?FILE_MODULE, Str, [ram, read, write]),
@@ -365,8 +366,8 @@ get_set_file(doc) ->
["Tests get_file/1, set_file/2, get_file_close/1 and get_size/1."];
get_set_file(Config) when is_list(Config) ->
%% These two strings should not be of equal length.
- ?line Str = "N�r h�gan nord blir sn�bet�ckt, ",
- ?line Str2 = "f�r alla harar byta dr�kt. ",
+ ?line Str = "När högan nord blir snöbetäckt, ",
+ ?line Str2 = "får alla harar byta dräkt. ",
?line Bin = list_to_binary(Str),
?line Bin2 = list_to_binary(Str2),
%%
diff --git a/lib/kernel/test/wrap_log_reader_SUITE.erl b/lib/kernel/test/wrap_log_reader_SUITE.erl
index 96dc3e6d33..16b3a7cc1e 100644
--- a/lib/kernel/test/wrap_log_reader_SUITE.erl
+++ b/lib/kernel/test/wrap_log_reader_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -557,7 +557,7 @@ rec(M, Where) ->
M ->
ok;
Else -> ?t:fail({error, {Where, Else}})
- after 1000 -> ?t:fail({error, {Where, time_out}})
+ after 5000 -> ?t:fail({error, {Where, time_out}})
end.
pps() ->