diff options
Diffstat (limited to 'lib/kernel')
34 files changed, 656 insertions, 206 deletions
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile index 214e994889..78e5f7bc26 100644 --- a/lib/kernel/doc/src/Makefile +++ b/lib/kernel/doc/src/Makefile @@ -155,18 +155,18 @@ $(SPECDIR)/specs_zlib_stub.xml: include $(ERL_TOP)/make/otp_release_targets.mk release_docs_spec: docs - $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf - $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf - $(INSTALL_DIR) $(RELSYSDIR)/doc/html + $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf" + $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf" + $(INSTALL_DIR) "$(RELSYSDIR)/doc/html" $(INSTALL_DATA) $(HTMLDIR)/* \ - $(RELSYSDIR)/doc/html - $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR) - $(INSTALL_DIR) $(RELEASE_PATH)/man/man3 - $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3 - $(INSTALL_DIR) $(RELEASE_PATH)/man/man4 - $(INSTALL_DATA) $(MAN4_FILES) $(RELEASE_PATH)/man/man4 - $(INSTALL_DIR) $(RELEASE_PATH)/man/man6 - $(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6 + "$(RELSYSDIR)/doc/html" + $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)" + $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3" + $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3" + $(INSTALL_DIR) "$(RELEASE_PATH)/man/man4" + $(INSTALL_DATA) $(MAN4_FILES) "$(RELEASE_PATH)/man/man4" + $(INSTALL_DIR) "$(RELEASE_PATH)/man/man6" + $(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6" release_spec: diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index ee687511a3..214e61cc00 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -91,7 +91,7 @@ of the additional library directories will override modules with the same name in OTP, except for modules in Kernel and STDLIB.</p> - <p>The environment variable <c>ERL_LIBS</c> (if defined) shold contain + <p>The environment variable <c>ERL_LIBS</c> (if defined) should contain a colon-separated (for Unix-like systems) or semicolon-separated (for Windows) list of additional libraries.</p> <p>Example: On an Unix-like system, <c>ERL_LIBS</c> could be set to diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml index 579b7f1f74..e327a4f907 100644 --- a/lib/kernel/doc/src/gen_sctp.xml +++ b/lib/kernel/doc/src/gen_sctp.xml @@ -123,7 +123,7 @@ <p>Completely closes the socket and all associations on it. The unsent data is flushed as in <c>eof/2</c>. The <c>close/1</c> call is blocking or otherwise depending of the value of - the <seealso marker="#option-linger">linger</seealso> socket + the <seealso marker="inet#option-linger">linger</seealso> socket <seealso marker="#options">option</seealso>. If <c>close</c> does not linger or linger timeout expires, the call returns and the data is flushed in the background.</p> @@ -309,8 +309,8 @@ <seealso marker="#option-active">passive</seealso> mode, with <anno>SockType</anno> <c>seqpacket</c>, and with reasonably large - <seealso marker="#option-sndbuf">kernel</seealso> and driver - <seealso marker="#option-buffer">buffers.</seealso></p> + <seealso marker="inet#option-sndbuf">kernel</seealso> and driver + <seealso marker="inet#option-buffer">buffers.</seealso></p> </desc> </func> <func> @@ -530,19 +530,8 @@ SCTP data interleaved with other inter-process messages.</p> </item> </list> - <marker id="option-buffer"></marker> </item> - <tag><c>{buffer, integer()}</c></tag> - <item> - <p>Determines the size of the user-level software buffer used by - the SCTP driver. Not to be confused with <c>sndbuf</c> - and <c>recbuf</c> options which correspond to - the kernel socket buffers. It is recommended - to have <c>val(buffer) >= max(val(sndbuf),val(recbuf))</c>. - In fact, the <c>val(buffer)</c> is automatically set to - the above maximum when <c>sndbuf</c> or <c>recbuf</c> values are set.</p> - </item> - <tag><c>{tos, integer()}</c></tag> + <tag><c>{tos, integer()}</c></tag> <item> <p>Sets the Type-Of-Service field on the IP datagrams being sent, to the given value, which effectively determines a prioritization @@ -567,19 +556,8 @@ <c>{IP,Port}</c> of the socket can be re-used immediately: no waiting in the CLOSE_WAIT state is performed (may be required for high-throughput servers).</p> - <marker id="option-linger"></marker> - </item> - <tag><c>{linger, {true|false, integer()}</c></tag> - <item> - <p>Determines the timeout in seconds for flushing unsent data in the - <c>gen_sctp:close/1</c> socket call. If the 1st component of the value - tuple is <c>false</c>, the 2nd one is ignored, which means that - <c>gen_sctp:close/1</c> returns immediately not waiting - for data to be flushed. Otherwise, the 2nd component is - the flushing time-out in seconds.</p> - <marker id="option-sndbuf"></marker> </item> - <tag><c>{sndbuf, integer()}</c></tag> + <tag><c>{sndbuf, integer()}</c></tag> <item> <p>The size, in bytes, of the *kernel* send buffer for this socket. Sending errors would occur for datagrams larger than @@ -593,6 +571,15 @@ <c>val(sndbuf)</c>. Setting this option also adjusts the size of the driver buffer (see <c>buffer</c> above).</p> </item> + + <tag><c>{sctp_module, module()}</c></tag> + <item> <p> + Override which callback module is used. Defaults to + <c>inet_sctp</c> for IPv4 and <c>inet6_sctp</c> for IPv6. + </p> + </item> + + <tag><c>{sctp_rtoinfo, #sctp_rtoinfo{}}</c></tag> <item> <pre> #sctp_rtoinfo{ diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index cf97607af1..11a0843c10 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -96,37 +96,47 @@ do_recv(Sock, Bs) -> can be either a hostname, or an IP address.</p> <p>The available options are:</p> <taglist> - <tag><c>list</c></tag> - <item> - <p>Received <c>Packet</c> is delivered as a list.</p> - </item> - <tag><c>binary</c></tag> - <item> - <p>Received <c>Packet</c> is delivered as a binary.</p> - </item> - <tag><c>{ip, ip_address()}</c></tag> + <tag><c>{ip, ip_address()}</c></tag> <item> <p>If the host has several network interfaces, this option specifies which one to use.</p> </item> - <tag><c>{port, Port}</c></tag> + + <tag><c>{ifaddr, ip_address()}</c></tag> <item> - <p>Specify which local port number to use.</p> - </item> + <p>Same as <c>{ip, ip_address()}</c>. If the host has several network interfaces, this option + specifies which one to use.</p> + </item> + <tag><c>{fd, integer() >= 0}</c></tag> <item> <p>If a socket has somehow been connected without using <c>gen_tcp</c>, use this option to pass the file descriptor for it.</p> </item> - <tag><c>inet6</c></tag> + + <tag><c>inet</c></tag> <item> + <p>Set up the socket for IPv4.</p> + </item> + + <tag><c>inet6</c></tag> + <item> <p>Set up the socket for IPv6.</p> </item> - <tag><c>inet</c></tag> + + <tag><c>{port, Port}</c></tag> <item> - <p>Set up the socket for IPv4.</p> + <p>Specify which local port number to use.</p> </item> + + <tag><c>{tcp_module, module()}</c></tag> + <item> <p> + Override which callback module is used. Defaults to + <c>inet_tcp</c> for IPv4 and <c>inet6_tcp</c> for IPv6. + </p> + </item> + <tag><c>Opt</c></tag> <item> <p>See @@ -197,6 +207,13 @@ do_recv(Sock, Bs) -> <c>gen_tcp</c>, use this option to pass the file descriptor for it.</p> </item> + + <tag><c>{ifaddr, ip_address()}</c></tag> + <item> + <p>Same as <c>{ip, ip_address()}</c>. If the host has several network interfaces, this option + specifies which one to use.</p> + </item> + <tag><c>inet6</c></tag> <item> <p>Set up the socket for IPv6.</p> @@ -205,6 +222,14 @@ do_recv(Sock, Bs) -> <item> <p>Set up the socket for IPv4.</p> </item> + + <tag><c>{tcp_module, module()}</c></tag> + <item> <p> + Override which callback module is used. Defaults to + <c>inet_tcp</c> for IPv4 and <c>inet6_tcp</c> for IPv6. + </p> + </item> + <tag><c>Opt</c></tag> <item> <p>See @@ -299,7 +324,7 @@ do_recv(Sock, Bs) -> <c><anno>Socket</anno></c>. The controlling process is the process which receives messages from the socket. If called by any other process than the current controlling process, - <c>{error, eperm}</c> is returned.</p> + <c>{error, not_owner}</c> is returned.</p> </desc> </func> <func> diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml index daa9b7d887..726dc30546 100644 --- a/lib/kernel/doc/src/gen_udp.xml +++ b/lib/kernel/doc/src/gen_udp.xml @@ -72,6 +72,14 @@ <p>If the host has several network interfaces, this option specifies which one to use.</p> </item> + + <tag><c>{ifaddr, ip_address()}</c></tag> + <item> + <p>Same as <c>{ip, ip_address()}</c>. If the host has several network interfaces, this option + specifies which one to use.</p> + </item> + + <tag><c>{fd, integer() >= 0}</c></tag> <item> <p>If a socket has somehow been opened without using @@ -86,6 +94,51 @@ <item> <p>Set up the socket for IPv4.</p> </item> + + <tag><c>{udp_module, module()}</c></tag> + <item> <p> + Override which callback module is used. Defaults to + <c>inet_udp</c> for IPv4 and <c>inet6_udp</c> for IPv6. + </p> + </item> + + <tag><c>{multicast_if, Address}</c></tag> + <item> + <p>Set the local device for a multicast socket.</p> + </item> + + <tag><c>{multicast_loop, true | false}</c></tag> + <item> + <p> + When <c>true</c> sent multicast packets will be looped back to the local + sockets. + </p> + </item> + + <tag><c>{multicast_ttl, Integer}</c></tag> + <item> + <p> + The <c>multicast_ttl</c> option changes the time-to-live (TTL) for + outgoing multicast datagrams in order to control the scope of the + multicasts. + </p> + <p> + Datagrams with a TTL of 1 are not forwarded beyond the local + network. + <br />Default: 1 + </p> + </item> + + <tag><c>{add_membership, {MultiAddress, InterfaceAddress}}</c></tag> + <item> + <p>Join a multicast group. </p> + </item> + + <tag><c>{drop_membership, {MultiAddress, InterfaceAddress}}</c></tag> + <item> + <p>Leave multicast group.</p> + </item> + <tag><c>Opt</c></tag> <item> <p>See @@ -136,7 +189,9 @@ <desc> <p>Assigns a new controlling process <c><anno>Pid</anno></c> to <c><anno>Socket</anno></c>. The controlling process is the process which - receives messages from the socket.</p> + receives messages from the socket. If called by any other + process than the current controlling process, + <c>{error, not_owner}</c> is returned.</p> </desc> </func> <func> diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index bf6c4cfb1a..b727960d96 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -445,10 +445,34 @@ fe80::204:acff:fe17:bf38 flow control; the other side will not be able send faster than the receiver can read.</p> </item> + + <tag><c>{bit8, clear | set | on | off}</c></tag> + <item> + <p> + Scans every byte in received data-packets and checks if the 8 bit + is set in any of them. Information is retrieved with + <c>inet:getopts/2</c>. + </p> + <p>Note that the <c>bit8</c> option is deprecated and will be removed in Erlang/OTP R16.</p> + </item> + <tag><c>{broadcast, Boolean}</c>(UDP sockets)</tag> <item> <p>Enable/disable permission to send broadcasts.</p> + <marker id="option-buffer"></marker> </item> + + <tag><c>{buffer, Size}</c></tag> + <item> + <p>Determines the size of the user-level software buffer used by + the driver. Not to be confused with <c>sndbuf</c> + and <c>recbuf</c> options which correspond to + the kernel socket buffers. It is recommended + to have <c>val(buffer) >= max(val(sndbuf),val(recbuf))</c>. + In fact, the <c>val(buffer)</c> is automatically set to + the above maximum when <c>sndbuf</c> or <c>recbuf</c> values are set.</p> + </item> + <tag><c>{delay_send, Boolean}</c></tag> <item> <p>Normally, when an Erlang process sends to a socket, @@ -463,10 +487,19 @@ fe80::204:acff:fe17:bf38 real property of the socket. Needless to say it is an implementation specific option. Default is <c>false</c>.</p> </item> + + <tag><c>{deliver, port | term}</c></tag> + <item> <p> When <c>{active, true}</c> delivers data on the forms + <c>port</c> : <c>{S, {data, [H1,..Hsz | Data]}}</c> or + <c>term</c> : <c>{tcp, S, [H1..Hsz | Data]}</c>. + </p> + </item> + <tag><c>{dontroute, Boolean}</c></tag> <item> <p>Enable/disable routing bypass for outgoing messages.</p> </item> + <tag><c>{exit_on_close, Boolean}</c></tag> <item> <p>By default this option is set to <c>true</c>.</p> @@ -476,6 +509,7 @@ fe80::204:acff:fe17:bf38 <seealso marker="gen_tcp#shutdown/2">gen_tcp:shutdown/2</seealso> to shutdown the write side.</p> </item> + <tag><c>{header, Size}</c></tag> <item> <p>This option is only meaningful if the <c>binary</c> @@ -487,6 +521,15 @@ fe80::204:acff:fe17:bf38 example <c>Size == 2</c>, the data received will match <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>{keepalive, Boolean}</c>(TCP/IP sockets)</tag> <item> <p>Enables/disables periodic transmission on a connected @@ -494,7 +537,43 @@ fe80::204:acff:fe17:bf38 the other end does not respond, the connection is considered broken and an error message will be sent to the controlling process. Default disabled.</p> + <marker id="option-linger"></marker> </item> + + <tag><c>{linger, {true|false, Seconds}}</c></tag> + <item> + <p>Determines the timeout in seconds for flushing unsent data in the + <c>close/1</c> socket call. If the 1st component of the value + tuple is <c>false</c>, the 2nd one is ignored, which means that + <c>close/1</c> returns immediately not waiting + for data to be flushed. Otherwise, the 2nd component is + 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>{mode, Mode :: binary | list}</c></tag> + <item> + <p>Received <c>Packet</c> is delivered as defined by Mode.</p> + </item> + + <tag><c>list</c></tag> + <item> + <p>Received <c>Packet</c> is delivered as a list.</p> + </item> + + <tag><c>binary</c></tag> + <item> + <p>Received <c>Packet</c> is delivered as a binary.</p> + </item> + <tag><c>{nodelay, Boolean}</c>(TCP/IP sockets)</tag> <item> <p>If <c>Boolean == true</c>, the <c>TCP_NODELAY</c> option @@ -578,6 +657,16 @@ fe80::204:acff:fe17:bf38 indicated length are accepted and not considered invalid due to internal buffer limitations.</p> </item> + + <tag><c>{priority, Priority}</c></tag> + <item> <p>Set the protocol-defined priority for all packets to be sent + on this socket.</p> + </item> + + <tag><c>{raw, Protocol, OptionNum, ValueBin}</c></tag> + <item> <p>See below.</p> + </item> + <tag><c>{read_packets, Integer}</c>(UDP sockets)</tag> <item> <p>Sets the max number of UDP packets to read without @@ -589,7 +678,7 @@ fe80::204:acff:fe17:bf38 high the system can become unresponsive due to UDP packet flooding.</p> </item> - <tag><c>{recbuf, Integer}</c></tag> + <tag><c>{recbuf, Size}</c></tag> <item> <p>Gives the size of the receive buffer to use for the socket.</p> @@ -618,9 +707,10 @@ fe80::204:acff:fe17:bf38 returns <c>{error,timeout}</c>. The recommended setting is <c>true</c> which will automatically close the socket. Default is <c>false</c> due to backward compatibility.</p> + <marker id="option-sndbuf"></marker> </item> - <tag><c>{sndbuf, Integer}</c></tag> + <tag><c>{sndbuf, Size}</c></tag> <item> <p>Gives the size of the send buffer to use for the socket.</p> </item> @@ -639,6 +729,7 @@ fe80::204:acff:fe17:bf38 not implemented. Use with caution.</p> </item> </taglist> + <p>In addition to the options mentioned above, <em>raw</em> option specifications can be used. The raw options are specified as a tuple of arity four, beginning with the tag diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml index e94119845a..09c525b376 100644 --- a/lib/kernel/doc/src/os.xml +++ b/lib/kernel/doc/src/os.xml @@ -80,6 +80,10 @@ DirOut = os:cmd("dir"), % on Win32 platform</code> Each environment variable is given as a single string on the format <c>"VarName=Value"</c>, where <c>VarName</c> is the name of the variable and <c>Value</c> its value.</p> + <p>If Unicode file name encoding is in effect (see the <seealso + marker="erts:erl#file_name_encoding">erl manual + page</seealso>), the strings may contain characters with + codepoints > 255.</p> </desc> </func> <func> @@ -93,6 +97,10 @@ DirOut = os:cmd("dir"), % on Win32 platform</code> <p>Returns the <c>Value</c> of the environment variable <c>VarName</c>, or <c>false</c> if the environment variable is undefined.</p> + <p>If Unicode file name encoding is in effect (see the <seealso + marker="erts:erl#file_name_encoding">erl manual + page</seealso>), the strings (both <c>VarName</c> and + <c>Value</c>) may contain characters with codepoints > 255.</p> </desc> </func> <func> @@ -123,6 +131,13 @@ DirOut = os:cmd("dir"), % on Win32 platform</code> <desc> <p>Sets a new <c>Value</c> for the environment variable <c>VarName</c>.</p> + <p>If Unicode filename encoding is in effect (see the <seealso + marker="erts:erl#file_name_encoding">erl manual + page</seealso>), the strings (both <c>VarName</c> and + <c>Value</c>) may contain characters with codepoints > 255.</p> + <p>On Unix platforms, the environment will be set using UTF-8 encoding + if Unicode file name translation is in effect. On Windows the + environment is set using wide character interfaces.</p> </desc> </func> <func> diff --git a/lib/kernel/doc/src/packages.xml b/lib/kernel/doc/src/packages.xml index 80de2e05fc..81b8693baa 100644 --- a/lib/kernel/doc/src/packages.xml +++ b/lib/kernel/doc/src/packages.xml @@ -204,11 +204,5 @@ ok Explicitly declaring each use of a module makes for safe code.</p> </description> - <funcs> - <func> - <name>no functions exported</name> - <fsummary>x</fsummary> - </func> - </funcs> </erlref> diff --git a/lib/kernel/examples/Makefile b/lib/kernel/examples/Makefile index fb27f8d438..21dfd0ec0e 100644 --- a/lib/kernel/examples/Makefile +++ b/lib/kernel/examples/Makefile @@ -47,8 +47,8 @@ RELSYSDIR = $(RELEASE_PATH)/lib/kernel-$(KERNEL_VSN)/examples EXAMPLES = uds_dist release_spec: - $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DIR) "$(RELSYSDIR)" tar cf - $(EXAMPLES) | \ - (cd $(RELSYSDIR); tar xf - ; chmod -R ug+w $(EXAMPLES) ) + (cd "$(RELSYSDIR)"; tar xf - ; chmod -R ug+w $(EXAMPLES) ) release_docs_spec: diff --git a/lib/kernel/examples/uds_dist/c_src/uds_drv.c b/lib/kernel/examples/uds_dist/c_src/uds_drv.c index 9327ab19dc..9ad6b85a0f 100644 --- a/lib/kernel/examples/uds_dist/c_src/uds_drv.c +++ b/lib/kernel/examples/uds_dist/c_src/uds_drv.c @@ -967,7 +967,7 @@ static void *my_malloc(size_t size) void *ptr; if ((ptr = driver_alloc(size)) == NULL) { - erl_exit(1,"Could not allocate %d bytes of memory",(int) size); + erl_exit(1,"Could not allocate %lu bytes of memory",(unsigned long) size); } return ptr; } @@ -977,7 +977,7 @@ static void *my_realloc(void *ptr, size_t size) void erl_exit(int, char *, ...); void *nptr; if ((nptr = driver_realloc(ptr, size)) == NULL) { - erl_exit(1,"Could not reallocate %d bytes of memory",(int) size); + erl_exit(1,"Could not reallocate %lu bytes of memory",(unsigned long) size); } return nptr; } diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile index 54f21eb2b8..a39864d6b7 100644 --- a/lib/kernel/src/Makefile +++ b/lib/kernel/src/Makefile @@ -198,13 +198,13 @@ $(EBIN)/erl_epmd.beam: $(ESRC)/erl_epmd.erl include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt - $(INSTALL_DIR) $(RELSYSDIR)/src - $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src - $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src - $(INSTALL_DIR) $(RELSYSDIR)/include - $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include - $(INSTALL_DIR) $(RELSYSDIR)/ebin - $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin + $(INSTALL_DIR) "$(RELSYSDIR)/src" + $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)/src" + $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src" + $(INSTALL_DIR) "$(RELSYSDIR)/include" + $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include" + $(INSTALL_DIR) "$(RELSYSDIR)/ebin" + $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin" release_docs_spec: diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index b7fda69ce0..363072951e 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -63,7 +63,7 @@ which/1, where_is_file/1, where_is_file/2, - set_primary_archive/3, + set_primary_archive/4, clash/0]). -export_type([load_error_rsn/0, load_ret/0]). @@ -107,7 +107,7 @@ %% unstick_mod(Module) -> true %% is_sticky(Module) -> boolean() %% which(Module) -> Filename | loaded_ret_atoms() | non_existing -%% set_primary_archive((FileName, Bin, FileInfo) -> ok | {error, Reason} +%% set_primary_archive((FileName, ArchiveBin, FileInfo, ParserFun) -> ok | {error, Reason} %% clash() -> ok prints out number of clashes %%---------------------------------------------------------------------------- @@ -481,13 +481,16 @@ where_is_file(Path, File) when is_list(Path), is_list(File) -> -spec set_primary_archive(ArchiveFile :: file:filename(), ArchiveBin :: binary(), - FileInfo :: file:file_info()) + FileInfo :: file:file_info(), + ParserFun :: fun()) -> 'ok' | {'error', atom()}. -set_primary_archive(ArchiveFile0, ArchiveBin, #file_info{} = FileInfo) +set_primary_archive(ArchiveFile0, ArchiveBin, #file_info{} = FileInfo, + ParserFun) when is_list(ArchiveFile0), is_binary(ArchiveBin) -> ArchiveFile = filename:absname(ArchiveFile0), - case call({set_primary_archive, ArchiveFile, ArchiveBin, FileInfo}) of + case call({set_primary_archive, ArchiveFile, ArchiveBin, FileInfo, + ParserFun}) of {ok, []} -> ok; {ok, _Mode, Ebins} -> diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index a2db7c9790..00ad923466 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -394,8 +394,8 @@ handle_call(stop,{_From,_Tag}, S) -> handle_call({is_cached,_File}, {_From,_Tag}, S=#state{cache=no_cache}) -> {reply, no, S}; -handle_call({set_primary_archive, File, ArchiveBin, FileInfo}, {_From,_Tag}, S=#state{mode=Mode}) -> - case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo) of +handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From,_Tag}, S=#state{mode=Mode}) -> + case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo, ParserFun) of {ok, Files} -> {reply, {ok, Mode, Files}, S}; {error, _Reason} = Error -> diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index f5f972c112..5b1efcd395 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -282,7 +282,8 @@ change_notify(Log, Pid, NewNotify) -> -spec change_header(Log, Header) -> 'ok' | {'error', Reason} when Log :: log(), - Header :: {head, dlog_head_opt()} | {head_func, mfa()}, + Header :: {head, dlog_head_opt()} + | {head_func, MFA :: {atom(), atom(), list()}}, Reason :: no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {badarg, head}. change_header(Log, NewHead) -> @@ -336,7 +337,9 @@ format_error(Error) -> ok | {blocked, QueueLogRecords :: boolean()}} | {node, Node :: node()} | {distributed, Dist :: local | [node()]} - | {head, Head :: none | {head, term()} | mfa()} + | {head, Head :: none + | {head, term()} + | (MFA :: {atom(), atom(), list()})} | {no_written_items, NoWrittenItems ::non_neg_integer()} | {full, Full :: boolean} | {no_current_bytes, non_neg_integer()} diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index 259967650f..242a25a7a6 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.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 @@ -74,7 +74,7 @@ | {distributed, Nodes :: [node()]} | {notify, boolean()} | {head, Head :: dlog_head_opt()} - | {head_func, mfa()} + | {head_func, MFA :: {atom(), atom(), list()}} | {mode, Mode :: dlog_mode()}. -type dlog_options() :: [dlog_option()]. -type dlog_repair() :: 'truncate' | boolean(). diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index d8033ee192..cdb984c333 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -1258,7 +1258,7 @@ sendfile_fallback_int(File, Sock, Bytes, ChunkSize, BytesSent) when Bytes > BytesSent; Bytes == 0 -> Size = if Bytes == 0 -> ChunkSize; - (Bytes - BytesSent + ChunkSize) > 0 -> + (Bytes - BytesSent) < ChunkSize -> Bytes - BytesSent; true -> ChunkSize diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl index d8954f0cf7..8fa963ec78 100644 --- a/lib/kernel/src/gen_sctp.erl +++ b/lib/kernel/src/gen_sctp.erl @@ -425,9 +425,10 @@ error_string(X) -> erlang:error(badarg, [X]). --spec controlling_process(Socket, Pid) -> ok when +-spec controlling_process(Socket, Pid) -> ok | {error, Reason} when Socket :: sctp_socket(), - Pid :: pid(). + Pid :: pid(), + Reason :: closed | not_owner | inet:posix(). controlling_process(S, Pid) when is_port(S), is_pid(Pid) -> inet:udp_controlling_process(S, Pid); diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl index ef6bfdf7f4..e6dfdadb03 100644 --- a/lib/kernel/src/gen_tcp.erl +++ b/lib/kernel/src/gen_tcp.erl @@ -31,7 +31,6 @@ -type option() :: {active, true | false | once} | - {bit8, clear | set | on | off} | {buffer, non_neg_integer()} | {delay_send, boolean()} | {deliver, port | term} | @@ -61,7 +60,6 @@ {tos, non_neg_integer()}. -type option_name() :: active | - bit8 | buffer | delay_send | deliver | diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl index 8688799ae9..914854c65c 100644 --- a/lib/kernel/src/gen_udp.erl +++ b/lib/kernel/src/gen_udp.erl @@ -185,9 +185,10 @@ connect(S, Address, Port) when is_port(S) -> Error end. --spec controlling_process(Socket, Pid) -> ok when +-spec controlling_process(Socket, Pid) -> ok | {error, Reason} when Socket :: socket(), - Pid :: pid(). + Pid :: pid(), + Reason :: closed | not_owner | inet:posix(). controlling_process(S, NewOwner) -> inet:udp_controlling_process(S, NewOwner). diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl index 255ae4e51b..218be964a0 100644 --- a/lib/kernel/src/heart.erl +++ b/lib/kernel/src/heart.erl @@ -18,6 +18,10 @@ %% -module(heart). +-compile(no_native). +% 'no_native' as part of a crude fix to make init:restart/0 work by clearing +% all hipe inter-module information (hipe_mfa_info's in hipe_bif0.c). + %%%-------------------------------------------------------------------- %%% This is a rewrite of pre_heart from BS.3. %%% diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 8b3aa0286d..514c002d87 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -34,6 +34,13 @@ -module(hipe_unified_loader). +-compile(no_native). +% 'no_native' is a workaround to avoid "The code server called unloaded module" +% caused by Mod:module_info(exports) in patch_to_emu_step1() called by post_beam_load. +% Reproducable with hipelibs and asn1_SUITE. +% I think the real solution would be to let BIF erlang:load_module/2 redirect all +% hipe calls to the module and thereby remove post_beam_load. + -export([chunk_name/1, %% Only the code and code_server modules may call the entries below! load_native_code/2, diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index abaf4486dc..1a03424f88 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -763,8 +763,12 @@ sctp_opt([Opt|Opts], Mod, R, As) -> {Name,Val} -> sctp_opt (Opts, Mod, R, As, Name, Val); _ -> {error,badarg} end; -sctp_opt([], _Mod, R, _SockOpts) -> - {ok, R}. +sctp_opt([], _Mod, #sctp_opts{ifaddr=IfAddr}=R, _SockOpts) -> + if is_list(IfAddr) -> + {ok, R#sctp_opts{ifaddr=lists:reverse(IfAddr)}}; + true -> + {ok, R} + end. sctp_opt(Opts, Mod, R, As, Name, Val) -> case add_opt(Name, Val, R#sctp_opts.opts, As) of @@ -1015,11 +1019,7 @@ open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 -> case prim_inet:setopts(S, Opts) of ok -> case if is_list(Addr) -> - prim_inet:bind(S, add, - [case A of - {_,_} -> A; - _ -> {A,Port} - end || A <- Addr]); + bindx(S, Addr, Port); true -> prim_inet:bind(S, Addr, Port) end of @@ -1040,6 +1040,34 @@ open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 -> open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module) -> fdopen(Fd, Opts, Protocol, Family, Type, Module). +bindx(S, [Addr], Port0) -> + {IP, Port} = set_bindx_port(Addr, Port0), + prim_inet:bind(S, IP, Port); +bindx(S, Addrs, Port0) -> + [{IP, Port} | Rest] = [set_bindx_port(Addr, Port0) || Addr <- Addrs], + case prim_inet:bind(S, IP, Port) of + {ok, AssignedPort} when Port =:= 0 -> + %% On newer Linux kernels, Solaris and FreeBSD, calling + %% bindx with port 0 is ok, but on SuSE 10, it results in einval + Rest2 = [change_bindx_0_port(Addr, AssignedPort) || Addr <- Rest], + prim_inet:bind(S, add, Rest2); + {ok, _} -> + prim_inet:bind(S, add, Rest); + Error -> + Error + end. + +set_bindx_port({_IP, _Port}=Addr, _OtherPort) -> + Addr; +set_bindx_port(IP, Port) -> + {IP, Port}. + +change_bindx_0_port({IP, 0}, AssignedPort) -> + {IP, AssignedPort}; +change_bindx_0_port({_IP, _Port}=Addr, _AssignedPort) -> + Addr. + + -spec fdopen(Fd :: non_neg_integer(), Opts :: [socket_setopt()], Protocol :: socket_protocol(), @@ -1246,6 +1274,8 @@ udp_close(S) when is_port(S) -> %% Set controlling process for TCP socket. tcp_controlling_process(S, NewOwner) when is_port(S), is_pid(NewOwner) -> case erlang:port_info(S, connected) of + {connected, NewOwner} -> + ok; {connected, Pid} when Pid =/= self() -> {error, not_owner}; undefined -> @@ -1297,6 +1327,8 @@ tcp_sync_input(S, Owner, Flag) -> %% Set controlling process for UDP or SCTP socket. udp_controlling_process(S, NewOwner) when is_port(S), is_pid(NewOwner) -> case erlang:port_info(S, connected) of + {connected, NewOwner} -> + ok; {connected, Pid} when Pid =/= self() -> {error, not_owner}; _ -> diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl index e214ffa404..a3fc57a124 100644 --- a/lib/kernel/src/rpc.erl +++ b/lib/kernel/src/rpc.erl @@ -286,7 +286,7 @@ call(N,M,F,A) -> Reason :: term(), Timeout :: timeout(). -call(N,M,F,A,_Timeout) when node() =:= N -> %% Optimize local call +call(N,M,F,A,infinity) when node() =:= N -> %% Optimize local call local_call(M,F,A); call(N,M,F,A,infinity) -> do_call(N, {call,M,F,A,group_leader()}, infinity); diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index 5dcaad3f5e..7bb3e3a365 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -140,12 +140,12 @@ include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt release_tests_spec: make_emakefile - $(INSTALL_DIR) $(RELSYSDIR) - $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR) - $(INSTALL_DATA) $(APP_FILES) $(RELSYSDIR) + $(INSTALL_DIR) "$(RELSYSDIR)" + $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)" + $(INSTALL_DATA) $(APP_FILES) "$(RELSYSDIR)" $(INSTALL_DATA) kernel.spec $(EMAKEFILE)\ - $(COVERFILE) $(RELSYSDIR) - chmod -R u+w $(RELSYSDIR) - @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + $(COVERFILE) "$(RELSYSDIR)" + chmod -R u+w "$(RELSYSDIR)" + @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) release_docs_spec: diff --git a/lib/kernel/test/bif_SUITE.erl b/lib/kernel/test/bif_SUITE.erl index 6276270d20..a2826f34df 100644 --- a/lib/kernel/test/bif_SUITE.erl +++ b/lib/kernel/test/bif_SUITE.erl @@ -260,23 +260,15 @@ spawn_opt2(Config) when is_list(Config) -> ?line P1 = spawn_opt(fun() -> Parent ! {self(), fetch_proc_vals(self())} end, - case heap_type() of - separate -> - [{fullsweep_after, 0},{min_heap_size, 1000}]; - shared -> - [] - end - ++ [link, {priority, max}]), + [{fullsweep_after, 0},{min_heap_size, 1000}, + link, {priority, max}]), ?line receive {P1, PV1} -> ?line Node = node(P1), ?line check_proc_vals(true, max, 0, 1000, PV1) end, ?line P2 = spawn_opt(fun() -> Parent ! {self(), fetch_proc_vals(self())} end, - case heap_type() of - separate -> [{min_heap_size, 10}]; - shared -> [] - end), + [{min_heap_size, 10}]), ?line receive {P2, PV2} -> ?line Node = node(P2), @@ -295,13 +287,8 @@ spawn_opt3(Config) when is_list(Config) -> fun() -> Parent ! {self(), fetch_proc_vals(self())} end, - case heap_type() of - separate -> - [{fullsweep_after,0}, {min_heap_size,1000}]; - shared -> - [] - end - ++ [link, {priority, max}]), + [{fullsweep_after,0}, {min_heap_size,1000}, + link, {priority, max}]), ?line receive {P1, PV1} -> ?line Node = node(P1), @@ -309,10 +296,7 @@ spawn_opt3(Config) when is_list(Config) -> end, ?line P2 = spawn_opt(Node, fun() -> Parent ! {self(), fetch_proc_vals(self())} end, - case heap_type() of - separate -> [{min_heap_size, 10}]; - shared -> [] - end), + [{min_heap_size, 10}]), ?line receive {P2, PV2} -> ?line Node = node(P2), @@ -333,13 +317,8 @@ spawn_opt4(Config) when is_list(Config) -> [fun() -> Parent ! {self(), fetch_proc_vals(self())} end], - case heap_type() of - separate -> - [{fullsweep_after,0}, {min_heap_size,1000}]; - shared -> - [] - end - ++ [link, {priority, max}]), + [{fullsweep_after,0}, {min_heap_size,1000}, + link, {priority, max}]), ?line receive {P1, PV1} -> ?line Node = node(P1), @@ -350,10 +329,7 @@ spawn_opt4(Config) when is_list(Config) -> [fun() -> Parent ! {self(), fetch_proc_vals(self())} end], - case heap_type() of - separate -> [{min_heap_size, 10}]; - shared -> [] - end), + [{min_heap_size, 10}]), ?line receive {P2, PV2} -> ?line Node = node(P2), @@ -374,13 +350,8 @@ spawn_opt5(Config) when is_list(Config) -> [fun() -> Parent ! {self(), fetch_proc_vals(self())} end], - case heap_type() of - separate -> - [{fullsweep_after,0}, {min_heap_size,1000}]; - shared -> - [] - end - ++ [link, {priority, max}]), + [{fullsweep_after,0}, {min_heap_size,1000}, + link, {priority, max}]), ?line receive {P1, PV1} -> ?line Node = node(P1), @@ -392,10 +363,7 @@ spawn_opt5(Config) when is_list(Config) -> [fun() -> Parent ! {self(), fetch_proc_vals(self())} end], - case heap_type() of - separate -> [{min_heap_size, 10}]; - shared -> [] - end), + [{min_heap_size, 10}]), ?line receive {P2, PV2} -> ?line Node = node(P2), @@ -532,34 +500,19 @@ spawn_failures(Config) when is_list(Config) -> check_proc_vals(Link, Priority, FullsweepAfter, MinHeapSize, {Ls, P, FA, HS}) -> ?line Link = lists:member(self(), Ls), ?line Priority = P, - ?line case heap_type() of - separate -> - ?line FullsweepAfter = FA, - ?line true = (HS >= MinHeapSize); - shared -> - ?line ok - end, + FullsweepAfter = FA, + true = (HS >= MinHeapSize), ?line ok. fetch_proc_vals(Pid) -> ?line PI = process_info(Pid), ?line {value,{links, Ls}} = lists:keysearch(links, 1, PI), ?line {value,{priority,P}} = lists:keysearch(priority, 1, PI), - ?line {FA, HS} - = case heap_type() of - separate -> - ?line {value, - {garbage_collection, - Gs}} = lists:keysearch(garbage_collection, 1, PI), - ?line {value, - {fullsweep_after, - Fa}} = lists:keysearch(fullsweep_after, 1, Gs), - ?line {value, - {heap_size,Hs}} = lists:keysearch(heap_size, 1, PI), - ?line {Fa, Hs}; - shared -> - {undefined, undefined} - end, + {value,{garbage_collection,Gs}} = + lists:keysearch(garbage_collection, 1, PI), + {value,{fullsweep_after,FA}} = + lists:keysearch(fullsweep_after, 1, Gs), + {value,{heap_size,HS}} = lists:keysearch(heap_size, 1, PI), ?line {Ls, P, FA, HS}. % This testcase should probably be moved somewhere else @@ -650,12 +603,3 @@ stop_node(Node) -> run_fun(Fun) -> Fun(). - -heap_type() -> - case catch erlang:system_info(heap_type) of - shared -> shared; - unified -> shared; - _ -> separate - end. - - diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 2c59351600..827208b048 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -501,7 +501,7 @@ sticky_dir(doc) -> ["Test that a module with the same name as a module in ", "a sticky directory cannot be loaded."]; sticky_dir(Config) when is_list(Config) -> MyDir=filename:dirname(code:which(?MODULE)), - ?line {ok, Node}=?t:start_node(sticky_dir, slave,[{args, "-pa "++MyDir}]), + ?line {ok, Node}=?t:start_node(sticky_dir, slave,[{args, "-pa \""++MyDir++"\""}]), File=filename:join([?config(data_dir, Config), "calendar"]), ?line Ret=rpc:call(Node, ?MODULE, sticky_compiler, [File]), case Ret of @@ -822,7 +822,7 @@ load_cached(Config) when is_list(Config) -> ?line WD = filename:dirname(code:which(?MODULE)), ?line {ok,Node} = ?t:start_node(code_cache_node, peer, [{args, - "-pa " ++ WD}, + "-pa \"" ++ WD ++ "\""}, {erl, [this]}]), CCTabCreated = fun(Tab) -> case ets:info(Tab, name) of @@ -907,7 +907,7 @@ add_and_rehash(Config) when is_list(Config) -> ?line WD = filename:dirname(code:which(?MODULE)), ?line {ok,Node} = ?t:start_node(code_cache_node, peer, [{args, - "-pa " ++ WD}, + "-pa \"" ++ WD ++ "\""}, {erl, [this]}]), CCTabCreated = fun(Tab) -> case ets:info(Tab, name) of @@ -1550,7 +1550,8 @@ native_early_modules_1(Architecture) -> true -> ?line true = lists:all(fun code:is_module_native/1, [ets,file,filename,gb_sets,gb_trees, - hipe_unified_loader,lists,os,packages]), + %%hipe_unified_loader, no_native as workaround + lists,os,packages]), ok end. diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index ad987fe7a7..0c3f5c3514 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_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 @@ -90,7 +90,7 @@ evil/1, - otp_6278/1]). + otp_6278/1, otp_10131/1]). -export([head_fun/1, hf/0, lserv/1, measure/0, init_m/1, xx/0, head_exit/0, slow_header/1]). @@ -124,7 +124,7 @@ [halt_int, wrap_int, halt_ext, wrap_ext, read_mode, head, notif, new_idx_vsn, reopen, block, unblock, open, close, error, chunk, truncate, many_users, info, change_size, - change_attribute, distribution, evil, otp_6278]). + change_attribute, distribution, evil, otp_6278, otp_10131]). %% The following two lists should be mutually exclusive. To skip a case %% on VxWorks altogether, use the kernel.spec.vxworks file instead. @@ -153,7 +153,7 @@ all() -> {group, open}, {group, close}, {group, error}, chunk, truncate, many_users, {group, info}, {group, change_size}, change_attribute, - {group, distribution}, evil, otp_6278]. + {group, distribution}, evil, otp_6278, otp_10131]. groups() -> [{halt_int, [], [halt_int_inf, {group, halt_int_sz}]}, @@ -4915,6 +4915,22 @@ otp_6278(Conf) when is_list(Conf) -> end, ?line error_logger:delete_report_handler(?MODULE). +otp_10131(suite) -> []; +otp_10131(doc) -> ["OTP-10131. head_func type."]; +otp_10131(Conf) when is_list(Conf) -> + Dir = ?privdir(Conf), + Log = otp_10131, + File = filename:join(Dir, lists:concat([Log, ".LOG"])), + HeadFunc = {?MODULE, head_fun, [{ok,"head"}]}, + {ok, Log} = disk_log:open([{name,Log},{file,File}, + {head_func, HeadFunc}]), + HeadFunc = info(Log, head, undef), + HeadFunc2 = {?MODULE, head_fun, [{ok,"head2"}]}, + ok = disk_log:change_header(Log, {head_func, HeadFunc2}), + HeadFunc2 = info(Log, head, undef), + ok = disk_log:close(Log), + ok. + mark(FileName, What) -> {ok,Fd} = file:open(FileName, [raw, binary, read, write]), {ok,_} = file:position(Fd, 4), diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index 6f4f27d594..72239641e9 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -426,7 +426,9 @@ primary_archive(Config) when is_list(Config) -> ExpectedEbins = [Archive, DictDir ++ "/ebin", DummyDir ++ "/ebin"], io:format("ExpectedEbins: ~p\n", [ExpectedEbins]), ?line {ok, FileInfo} = prim_file:read_file_info(Archive), - ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive, [Archive, ArchiveBin, FileInfo]), + ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive, + [Archive, ArchiveBin, FileInfo, + fun escript:parse_file/1]), ?line ExpectedEbins = lists:sort(Ebins), % assert ?line {ok, TopFiles2} = rpc:call(Node, erl_prim_loader, list_dir, [Archive]), @@ -435,7 +437,9 @@ primary_archive(Config) when is_list(Config) -> ?line ok = test_archive(Node, Archive, DictDir, BeamName), %% Cleanup - ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive, [undefined, undefined, undefined]), + ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive, + [undefined, undefined, undefined, + fun escript:parse_file/1]), ?line stop_node(Node), ?line ok = file:delete(Archive), ok. diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl index 53bcb1162d..be33ec2c06 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -74,7 +74,7 @@ init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]). --export([normal/1,icky/1,very_icky/1,normalize/1]). +-export([normal/1,icky/1,very_icky/1,normalize/1,home_dir/1]). init_per_testcase(_Func, Config) -> @@ -88,7 +88,7 @@ end_per_testcase(_Func, Config) -> suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [normal, icky, very_icky, normalize]. + [normal, icky, very_icky, normalize, home_dir]. groups() -> []. @@ -105,6 +105,54 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +home_dir(suite) -> + []; +home_dir(doc) -> + ["Check that Erlang can be started with unicode named home directory"]; +home_dir(Config) when is_list(Config) -> + try + Name=[960,945,964,961,953,954], + Priv = ?config(priv_dir, Config), + UniMode = file:native_name_encoding() =/= latin1, + if + not UniMode -> + throw(need_unicode_mode); + true -> + ok + end, + NewHome=filename:join(Priv,Name), + file:make_dir(NewHome), + {SaveOldName,SaveOldValue} = case os:type() of + {win32,nt} -> + HomePath=re:replace(filename:nativename(NewHome),"^[a-zA-Z]:","",[{return,list},unicode]), + Save = os:getenv("HOMEPATH"), + os:putenv("HOMEPATH",HomePath), + {"HOMEPATH",Save}; + {unix,_} -> + Save = os:getenv("HOME"), + os:putenv("HOME",NewHome), + {"HOME",Save}; + _ -> + rm_rf(prim_file,NewHome), + throw(unsupported_os) + end, + try + {ok,Node} = test_server:start_node(test_unicode_homedir,slave,[{args,"-setcookie "++atom_to_list(erlang:get_cookie())}]), + test_server:stop_node(Node), + ok + after + os:putenv(SaveOldName,SaveOldValue), + rm_rf(prim_file,NewHome) + end + catch + throw:need_unicode_mode -> + io:format("Sorry, can only run in unicode mode.~n"), + {skipped,"VM needs to be started in Unicode filename mode"}; + throw:unsupported_os -> + io:format("Sorry, can only run on Unix/Windows.~n"), + {skipped,"Runs only on Unix/Windows"} + end. + normalize(suite) -> []; normalize(doc) -> diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl index 8f490b6643..f4bf6e719e 100644 --- a/lib/kernel/test/gen_sctp_SUITE.erl +++ b/lib/kernel/test/gen_sctp_SUITE.erl @@ -31,14 +31,22 @@ [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]). + 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]). 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]. + 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]. groups() -> []. @@ -1105,6 +1113,192 @@ mk_data(N, Bytes, Bin) when N < Bytes -> mk_data(_, _, Bin) -> Bin. + + +open_multihoming_ipv4_socket(doc) -> + "Test opening a multihoming ipv4 socket"; +open_multihoming_ipv4_socket(suite) -> + []; +open_multihoming_ipv4_socket(Config) when is_list(Config) -> + ?line case get_addrs_by_family(inet, 2) of + {ok, [Addr1, Addr2]} -> + ?line do_open_and_connect([Addr1, Addr2], Addr1); + {error, Reason} -> + {skip, Reason} + end. + +open_unihoming_ipv6_socket(doc) -> + %% This test is mostly aimed to indicate + %% whether host has a non-working ipv6 setup + "Test opening a unihoming (non-multihoming) ipv6 socket"; +open_unihoming_ipv6_socket(suite) -> + []; +open_unihoming_ipv6_socket(Config) when is_list(Config) -> + ?line case get_addrs_by_family(inet6, 1) of + {ok, [Addr]} -> + ?line do_open_and_connect([Addr], Addr); + {error, Reason} -> + {skip, Reason} + end. + + +open_multihoming_ipv6_socket(doc) -> + "Test opening a multihoming ipv6 socket"; +open_multihoming_ipv6_socket(suite) -> + []; +open_multihoming_ipv6_socket(Config) when is_list(Config) -> + ?line case get_addrs_by_family(inet6, 2) of + {ok, [Addr1, Addr2]} -> + ?line do_open_and_connect([Addr1, Addr2], Addr1); + {error, Reason} -> + {skip, Reason} + end. + +open_multihoming_ipv4_and_ipv6_socket(doc) -> + "Test opening a multihoming ipv6 socket with ipv4 and ipv6 addresses"; +open_multihoming_ipv4_and_ipv6_socket(suite) -> + []; +open_multihoming_ipv4_and_ipv6_socket(Config) when is_list(Config) -> + ?line case get_addrs_by_family(inet_and_inet6, 2) of + {ok, [[InetAddr1, InetAddr2], [Inet6Addr1, Inet6Addr2]]} -> + %% Connect to the first address to test bind + ?line do_open_and_connect([InetAddr1, Inet6Addr1, InetAddr2], + InetAddr1), + ?line do_open_and_connect([Inet6Addr1, InetAddr1], + Inet6Addr1), + + %% Connect an address, not the first, + %% to test sctp_bindx + ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1], + Inet6Addr2), + ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1], + InetAddr1); + {error, Reason} -> + {skip, Reason} + end. + + +get_addrs_by_family(Family, NumAddrs) -> + case os:type() of + {unix,linux} -> + get_addrs_by_family_aux(Family, NumAddrs); + {unix,freebsd} -> + get_addrs_by_family_aux(Family, NumAddrs); + {unix,sunos} -> + case get_addrs_by_family_aux(Family, NumAddrs) of + {ok, [InetAddrs, Inet6Addrs]} when Family =:= inet_and_inet6 -> + %% Man page for sctp_bindx on Solaris says: "If sock is an + %% Internet Protocol Version 6 (IPv6) socket, addrs should + %% be an array of sockaddr_in6 structures containing IPv6 + %% or IPv4-mapped IPv6 addresses." + {ok, [ipv4_map_addrs(InetAddrs), Inet6Addrs]}; + {ok, Addrs} -> + {ok, Addrs}; + {error, Reason} -> + {error, Reason} + end; + Os -> + Reason = if Family =:= inet_and_inet6 -> + f("Mixing ipv4 and ipv6 addresses for multihoming " + " has not been verified on ~p", [Os]); + true -> + f("Multihoming for ~p has not been verified on ~p", + [Family, Os]) + end, + {error, Reason} + end. + +get_addrs_by_family_aux(Family, NumAddrs) when Family =:= inet; + Family =:= inet6 -> + ?line + case inet:getaddr(localhost, Family) of + {error,eafnosupport} -> + {skip, f("No support for ~p", Family)}; + {ok, _} -> + ?line IfAddrs = ok(inet:getifaddrs()), + ?line case filter_addrs_by_family(IfAddrs, Family) of + Addrs when length(Addrs) >= NumAddrs -> + {ok, lists:sublist(Addrs, NumAddrs)}; + [] -> + {error, f("Need ~p ~p address(es) found none~n", + [NumAddrs, Family])}; + Addrs -> + {error, + f("Need ~p ~p address(es) found only ~p: ~p~n", + [NumAddrs, Family, length(Addrs), Addrs])} + end + end; +get_addrs_by_family_aux(inet_and_inet6, NumAddrs) -> + ?line catch {ok, [case get_addrs_by_family_aux(Family, NumAddrs) of + {ok, Addrs} -> Addrs; + {error, Reason} -> throw({error, Reason}) + end || Family <- [inet, inet6]]}. + +filter_addrs_by_family(IfAddrs, Family) -> + lists:flatten([[Addr || {addr, Addr} <- Info, + is_good_addr(Addr, Family)] + || {_IfName, Info} <- IfAddrs]). + +is_good_addr(Addr, inet) when tuple_size(Addr) =:= 4 -> + true; +is_good_addr({0,0,0,0,0,16#ffff,_,_}, inet6) -> + false; %% ipv4 mapped +is_good_addr({16#fe80,_,_,_,_,_,_,_}, inet6) -> + false; %% link-local +is_good_addr(Addr, inet6) when tuple_size(Addr) =:= 8 -> + true; +is_good_addr(_Addr, _Family) -> + false. + +ipv4_map_addrs(InetAddrs) -> + [begin + <<AB:16>> = <<A,B>>, + <<CD:16>> = <<C,D>>, + {0, 0, 0, 0, 0, 16#ffff, AB, CD} + end || {A,B,C,D} <- InetAddrs]. + +f(F, A) -> + lists:flatten(io_lib:format(F, A)). + +do_open_and_connect(ServerAddresses, AddressToConnectTo) -> + ?line ServerFamily = get_family_by_addrs(ServerAddresses), + ?line io:format("Serving ~p addresses: ~p~n", + [ServerFamily, ServerAddresses]), + ?line S1 = ok(gen_sctp:open(0, [{ip,Addr} || Addr <- ServerAddresses] ++ + [ServerFamily])), + ?line ok = gen_sctp:listen(S1, true), + ?line P1 = ok(inet:port(S1)), + ?line ClientFamily = get_family_by_addr(AddressToConnectTo), + ?line io:format("Connecting to ~p ~p~n", + [ClientFamily, AddressToConnectTo]), + ?line S2 = ok(gen_sctp:open(0, [ClientFamily])), + %% Verify client can connect + ?line #sctp_assoc_change{state=comm_up} = + ok(gen_sctp:connect(S2, AddressToConnectTo, P1, [])), + %% verify server side also receives comm_up from client + ?line recv_comm_up_eventually(S1), + ?line ok = gen_sctp:close(S2), + ?line ok = gen_sctp:close(S1). + +%% If at least one of the addresses is an ipv6 address, return inet6, else inet. +get_family_by_addrs(Addresses) -> + ?line case lists:usort([get_family_by_addr(Addr) || Addr <- Addresses]) of + [inet, inet6] -> inet6; + [inet] -> inet; + [inet6] -> inet6 + end. + +get_family_by_addr(Addr) when tuple_size(Addr) =:= 4 -> inet; +get_family_by_addr(Addr) when tuple_size(Addr) =:= 8 -> inet6. + +recv_comm_up_eventually(S) -> + ?line case ok(gen_sctp:recv(S)) of + {_Addr, _Port, _Info, #sctp_assoc_change{state=comm_up}} -> + ok; + {_Addr, _Port, _Info, _OtherSctpMsg} -> + ?line recv_comm_up_eventually(S) + end. + %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% socket gen_server ultra light diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index c74a258af9..1592399996 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -24,7 +24,8 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - controlling_process/1, no_accept/1, close_with_pending_output/1, + controlling_process/1, controlling_process_self/1, + no_accept/1, close_with_pending_output/1, data_before_close/1, iter_max_socks/1, get_status/1, passive_sockets/1, accept_closed_by_other_process/1, init_per_testcase/2, end_per_testcase/2, @@ -58,7 +59,7 @@ end_per_testcase(_Func, Config) -> suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [controlling_process, no_accept, + [controlling_process, controlling_process_self, no_accept, close_with_pending_output, data_before_close, iter_max_socks, passive_sockets, accept_closed_by_other_process, otp_3924, closed_socket, @@ -307,6 +308,32 @@ not_owner(S) -> ok end. +controlling_process_self(doc) -> + ["Open a listen port and assign the controlling process to " + "it self, then exit and make sure the port is closed properly."]; +controlling_process_self(Config) when is_list(Config) -> + S = self(), + process_flag(trap_exit,true), + spawn_link(fun() -> + {ok,Sock} = gen_tcp:listen(0,[]), + S ! {socket, Sock}, + ok = gen_tcp:controlling_process(Sock,self()), + S ! done + end), + receive + done -> + receive + {socket,Sock} -> + process_flag(trap_exit,false), + %% Make sure the port is invalid after process crash + {error,einval} = inet:port(Sock) + end; + Msg when element(1,Msg) /= socket -> + process_flag(trap_exit,false), + exit({unknown_msg,Msg}) + end. + + no_accept(doc) -> ["Open a listen port and connect to it, then close the listen port ", "without doing any accept. The connected socket should receive ", @@ -2044,7 +2071,7 @@ send_timeout_active(Config) when is_list(Config) -> ?line {error,timeout} = Loop(fun() -> receive - {tcp, Sock, _Data} -> + {tcp, _Sock, _Data} -> inet:setopts(A, [{active, once}]), Res = gen_tcp:send(A,lists:duplicate(1000, $a)), %erlang:display(Res), @@ -2536,7 +2563,7 @@ otp_8102_do(LSocket, PortNum, {Bin,PType}) -> otp_9389(doc) -> ["Verify packet_size handles long HTTP header lines"]; otp_9389(suite) -> []; otp_9389(Config) when is_list(Config) -> - ?line {ok, LS} = gen_tcp:listen(0, []), + ?line {ok, LS} = gen_tcp:listen(0, [{active,false}]), ?line {ok, {_, PortNum}} = inet:sockname(LS), io:format("Listening on ~w with port number ~p\n", [LS, PortNum]), OrigLinkHdr = "/" ++ string:chars($S, 8192), diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index b39fadd65f..e3fa4642b7 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -608,7 +608,7 @@ boot2(Config) when is_list(Config) -> %% Absolute boot file name Boot = filename:join([code:root_dir(), "bin", "start_sasl"]), - Args = args() ++ " -boot " ++ Boot, + Args = args() ++ " -boot \"" ++ Boot++"\"", ?line {ok, Node} = start_node(init_test, Args), ?line stop_node(Node), @@ -618,7 +618,7 @@ boot2(Config) when is_list(Config) -> %% converted to backslashes. Win_boot = lists:map(fun($/) -> $\\; (C) -> C end, Boot), - Args2 = args() ++ " -boot " ++ Win_boot, + Args2 = args() ++ " -boot \"" ++ Win_boot ++ "\"", ?line {ok, Node2} = start_node(init_test, Args2), ?line stop_node(Node2); _ -> diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl index b2308dd321..96e45cc23f 100644 --- a/lib/kernel/test/interactive_shell_SUITE.erl +++ b/lib/kernel/test/interactive_shell_SUITE.erl @@ -251,7 +251,7 @@ rtnode(Commands,Nodename,ErlPrefix) -> ?line {skip, Reason2}; Tempdir -> ?line SPid = - start_runerl_node(RunErl,ErlPrefix++Erl, + start_runerl_node(RunErl,ErlPrefix++"\\\""++Erl++"\\\"", Tempdir,Nodename), ?line CPid = start_toerl_server(ToErl,Tempdir), ?line erase(getline_skipped), @@ -487,7 +487,7 @@ start_runerl_node(RunErl,Erl,Tempdir,Nodename) -> " -setcookie "++atom_to_list(erlang:get_cookie()) end, spawn(fun() -> - os:cmd(RunErl++" "++Tempdir++"/ "++Tempdir++" \""++ + os:cmd("\""++RunErl++"\" "++Tempdir++"/ "++Tempdir++" \""++ Erl++XArg++"\"") end). @@ -518,7 +518,7 @@ try_to_erl(Command, N) -> end. toerl_server(Parent,ToErl,Tempdir) -> - Port = try_to_erl(ToErl++" "++Tempdir++"/ 2>/dev/null",8), + Port = try_to_erl("\""++ToErl++"\" "++Tempdir++"/ 2>/dev/null",8), case Port of P when is_port(P) -> Parent ! {self(),started}; diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 76d3003ff4..c494f8a864 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 2.15.1 +KERNEL_VSN = 2.15.2 |