diff options
Diffstat (limited to 'lib/kernel')
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>, [recv_avg, recv_cnt, recv_dvi, recv_max, recv_oct, send_avg, send_cnt, send_dvi, send_max, 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() -> |