diff options
Diffstat (limited to 'lib')
29 files changed, 271 insertions, 148 deletions
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c index 4577689fc3..b29c9a7ed3 100644 --- a/lib/asn1/c_src/asn1_erl_nif.c +++ b/lib/asn1/c_src/asn1_erl_nif.c @@ -21,7 +21,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include "erl_nif.h" +#include <erl_nif.h> /* #define ASN1_DEBUG 1 */ diff --git a/lib/common_test/doc/src/ct_telnet.xml b/lib/common_test/doc/src/ct_telnet.xml index eba3c3030d..8e85cccc99 100644 --- a/lib/common_test/doc/src/ct_telnet.xml +++ b/lib/common_test/doc/src/ct_telnet.xml @@ -337,7 +337,7 @@ <c>FullMatch</c> is the string matched by the whole regular expression, and <c>SubMatchN</c> is the string that matched subexpression number <c>N</c>. Subexpressions are denoted with - <c>(' ')</c> in the regular expression.</p> + <c>'(' ')'</c> in the regular expression.</p> <p>If a <c>Tag</c> is speciifed, the returned <c>Match</c> also includes the matched <c>Tag</c>. Otherwise, only <c>RxMatch</c> diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index cd521f04c5..f9fa80c0c7 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -31,7 +31,7 @@ #include <stdio.h> #include <string.h> -#include "erl_nif.h" +#include <erl_nif.h> #define OPENSSL_THREAD_DEFINES #include <openssl/opensslconf.h> diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c index 3acbbf406b..4c23379f7f 100644 --- a/lib/crypto/c_src/crypto_callback.c +++ b/lib/crypto/c_src/crypto_callback.c @@ -22,7 +22,7 @@ #include <string.h> #include <openssl/opensslconf.h> -#include "erl_nif.h" +#include <erl_nif.h> #include "crypto_callback.h" #ifdef DEBUG diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl index 91256fa6a2..d8bdac24e3 100644 --- a/lib/inets/src/http_client/httpc_response.erl +++ b/lib/inets/src/http_client/httpc_response.erl @@ -110,27 +110,30 @@ result(Response = {{_, 300, _}, _, _}, redirect(Response, Request); result(Response = {{_, Code, _}, _, _}, + Request = #request{settings = + #http_options{autoredirect = true}, + method = post}) when (Code =:= 301) orelse + (Code =:= 302) orelse + (Code =:= 303) -> + redirect(Response, Request#request{method = get}); +result(Response = {{_, Code, _}, _, _}, + Request = #request{settings = + #http_options{autoredirect = true}, + method = post}) when (Code =:= 307) -> + redirect(Response, Request); +result(Response = {{_, Code, _}, _, _}, Request = #request{settings = #http_options{autoredirect = true}, - method = head}) when (Code =:= 301) orelse + method = Method}) when (Code =:= 301) orelse (Code =:= 302) orelse (Code =:= 303) orelse (Code =:= 307) -> - redirect(Response, Request); -result(Response = {{_, Code, _}, _, _}, - Request = #request{settings = - #http_options{autoredirect = true}, - method = get}) when (Code =:= 301) orelse - (Code =:= 302) orelse - (Code =:= 303) orelse - (Code =:= 307) -> - redirect(Response, Request); -result(Response = {{_, 303, _}, _, _}, - Request = #request{settings = - #http_options{autoredirect = true}, - method = post}) -> - redirect(Response, Request#request{method = get}); - + case lists:member(Method, [get, head, options, trace]) of + true -> + redirect(Response, Request); + false -> + transparent(Response, Request) + end; result(Response = {{_,503,_}, _, _}, Request) -> status_service_unavailable(Response, Request); diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 932567ec55..57da82c6ad 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -500,10 +500,11 @@ redirect_multiple_choises(Config) when is_list(Config) -> httpc:request(get, {URL300, []}, [{autoredirect, false}], []). %%------------------------------------------------------------------------- redirect_moved_permanently() -> - [{doc, "If the 301 status code is received in response to a request other " - "than GET or HEAD, the user agent MUST NOT automatically redirect the request " - "unless it can be confirmed by the user, since this might change " - "the conditions under which the request was issued."}]. + [{doc, "The server SHOULD generate a Location header field in the response " + "containing a preferred URI reference for the new permanent URI. The user " + "agent MAY use the Location field value for automatic redirection. The server's " + "response payload usually contains a short hypertext note with a " + "hyperlink to the new URI(s)."}]. redirect_moved_permanently(Config) when is_list(Config) -> URL301 = url(group_name(Config), "/301.html", Config), @@ -514,15 +515,16 @@ redirect_moved_permanently(Config) when is_list(Config) -> {ok, {{_,200,_}, [_ | _], []}} = httpc:request(head, {URL301, []}, [], []), - {ok, {{_,301,_}, [_ | _], [_|_]}} + {ok, {{_,200,_}, [_ | _], [_|_]}} = httpc:request(post, {URL301, [],"text/plain", "foobar"}, [], []). %%------------------------------------------------------------------------- redirect_found() -> - [{doc," If the 302 status code is received in response to a request other " - "than GET or HEAD, the user agent MUST NOT automatically redirect the " - "request unless it can be confirmed by the user, since this might change " - "the conditions under which the request was issued."}]. + [{doc, "The server SHOULD generate a Location header field in the response " + "containing a URI reference for the different URI. The user agent MAY " + "use the Location field value for automatic redirection. The server's " + "response payload usually contains a short hypertext note with a " + "hyperlink to the different URI(s)."}]. redirect_found(Config) when is_list(Config) -> URL302 = url(group_name(Config), "/302.html", Config), @@ -533,14 +535,14 @@ redirect_found(Config) when is_list(Config) -> {ok, {{_,200,_}, [_ | _], []}} = httpc:request(head, {URL302, []}, [], []), - {ok, {{_,302,_}, [_ | _], [_|_]}} + {ok, {{_,200,_}, [_ | _], [_|_]}} = httpc:request(post, {URL302, [],"text/plain", "foobar"}, [], []). %%------------------------------------------------------------------------- redirect_see_other() -> [{doc, "The different URI SHOULD be given by the Location field in the response. " "Unless the request method was HEAD, the entity of the response SHOULD contain a short " - "hypertext note with a hyperlink to the new URI(s). "}]. + "hypertext note with a hyperlink to the new URI(s)."}]. redirect_see_other(Config) when is_list(Config) -> URL303 = url(group_name(Config), "/303.html", Config), @@ -556,10 +558,11 @@ redirect_see_other(Config) when is_list(Config) -> [], []). %%------------------------------------------------------------------------- redirect_temporary_redirect() -> - [{doc," If the 307 status code is received in response to a request other " - "than GET or HEAD, the user agent MUST NOT automatically redirect the request " - "unless it can be confirmed by the user, since this might change " - "the conditions under which the request was issued."}]. + [{doc, "The server SHOULD generate a Location header field in the response " + "containing a URI reference for the different URI. The user agent MAY " + "use the Location field value for automatic redirection. The server's " + "response payload usually contains a short hypertext note with a " + "hyperlink to the different URI(s)."}]. redirect_temporary_redirect(Config) when is_list(Config) -> URL307 = url(group_name(Config), "/307.html", Config), @@ -570,7 +573,7 @@ redirect_temporary_redirect(Config) when is_list(Config) -> {ok, {{_,200,_}, [_ | _], []}} = httpc:request(head, {URL307, []}, [], []), - {ok, {{_,307,_}, [_ | _], [_|_]}} + {ok, {{_,200,_}, [_ | _], [_|_]}} = httpc:request(post, {URL307, [],"text/plain", "foobar"}, [], []). diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 4db377bcde..3143cdc825 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -382,9 +382,14 @@ zip:create("mnesia-4.4.7.ez", <name name="add_pathsa" arity="1"/> <fsummary>Add directories to the beginning of the code path.</fsummary> <desc> - <p>Adds the directories in <c><anno>Dirs</anno></c> to the beginning of - the code path. If a <c><anno>Dir</anno></c> exists, it is removed - from the old position in the code path.</p> + <p>Traverses <c><anno>Dirs</anno></c> and adds + each <c><anno>Dir</anno></c> to the beginning of the code + path. This means that the order of <c><anno>Dirs</anno></c> + is reversed in the resulting code path. For example, if you + add <c>[Dir1,Dir2]</c>, the resulting path will + be <c>[Dir2,Dir1|OldCodePath]</c>.</p> + <p>If a <c><anno>Dir</anno></c> already exists in the code + path, it is removed from the old position.</p> <p>Always returns <c>ok</c>, regardless of the validity of each individual <c><anno>Dir</anno></c>.</p> </desc> diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 58b601e456..1971df9038 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -397,25 +397,36 @@ write_file(Name, Bin) -> Modes :: [mode()], Reason :: posix() | badarg | terminated | system_limit. -write_file(Name, Bin, ModeList) when is_list(ModeList) -> - case make_binary(Bin) of - B when is_binary(B) -> - case open(Name, [binary, write | - lists:delete(binary, - lists:delete(write, ModeList))]) of - {ok, Handle} -> - case write(Handle, B) of - ok -> - close(Handle); - E1 -> - _ = close(Handle), - E1 - end; - E2 -> - E2 - end; - E3 -> - E3 +write_file(Name, IOData, ModeList) when is_list(ModeList) -> + case lists:member(raw, ModeList) of + true -> + %% For backwards compatibility of error messages + try iolist_size(IOData) of + _Size -> do_write_file(Name, IOData, ModeList) + catch + error:Error -> {error, Error} + end; + false -> + case make_binary(IOData) of + Bin when is_binary(Bin) -> + do_write_file(Name, Bin, ModeList); + Error -> + Error + end + end. + +do_write_file(Name, IOData, ModeList) -> + case open(Name, [binary, write | ModeList]) of + {ok, Handle} -> + case write(Handle, IOData) of + ok -> + close(Handle); + E1 -> + _ = close(Handle), + E1 + end; + E2 -> + E2 end. %% Obsolete, undocumented, local node only, don't use!. diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index d16e200cb3..82cf73cbda 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"5\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.* %% Down to - max one major revision back - [{<<"5\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.* }. diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 5f049c6f99..c37d114a58 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -493,22 +493,13 @@ read_write_file(Config) when is_list(Config) -> %% Try writing and reading back some term SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]}, - ok = ?FILE_MODULE:write_file(Name,term_to_binary(SomeTerm)), - {ok,Bin1} = ?FILE_MODULE:read_file(Name), - SomeTerm = binary_to_term(Bin1), + Bin1 = term_to_binary(SomeTerm), + ok = do_read_write_file(Name, Bin1), %% Try a "null" term NullTerm = [], - ok = ?FILE_MODULE:write_file(Name,term_to_binary(NullTerm)), - {ok,Bin2} = ?FILE_MODULE:read_file(Name), - NullTerm = binary_to_term(Bin2), - - %% Try some "complicated" types - BigNum = 123456789012345678901234567890, - ComplTerm = {self(),make_ref(),BigNum,3.14159}, - ok = ?FILE_MODULE:write_file(Name,term_to_binary(ComplTerm)), - {ok,Bin3} = ?FILE_MODULE:read_file(Name), - ComplTerm = binary_to_term(Bin3), + Bin2 = term_to_binary(NullTerm), + ok = do_read_write_file(Name, Bin2), %% Try reading a nonexistent file Name2 = filename:join(RootDir, @@ -519,25 +510,42 @@ read_write_file(Config) when is_list(Config) -> {error, enoent} = ?FILE_MODULE:read_file(''), %% Try writing to a bad filename - {error, enoent} = - ?FILE_MODULE:write_file("",term_to_binary(NullTerm)), + {error, enoent} = do_read_write_file("", Bin2), %% Try writing something else than a binary - {error, badarg} = ?FILE_MODULE:write_file(Name,{1,2,3}), - {error, badarg} = ?FILE_MODULE:write_file(Name,self()), + {error, badarg} = do_read_write_file(Name, {1,2,3}), + {error, badarg} = do_read_write_file(Name, self()), %% Some non-term binaries - ok = ?FILE_MODULE:write_file(Name,[]), - {ok,Bin4} = ?FILE_MODULE:read_file(Name), - 0 = byte_size(Bin4), + ok = do_read_write_file(Name, []), - ok = ?FILE_MODULE:write_file(Name,[Bin1,[],[[Bin2]]]), - {ok,Bin5} = ?FILE_MODULE:read_file(Name), - {Bin1,Bin2} = split_binary(Bin5,byte_size(Bin1)), + %% Write some iolists + ok = do_read_write_file(Name, [Bin1,[],[[Bin2]]]), + ok = do_read_write_file(Name, ["string",<<"binary">>]), + ok = do_read_write_file(Name, "pure string"), [] = flush(), ok. +do_read_write_file(Name, Data) -> + case ?FILE_MODULE:write_file(Name, Data) of + ok -> + BinData = iolist_to_binary(Data), + {ok,BinData} = ?FILE_MODULE:read_file(Name), + + ok = ?FILE_MODULE:write_file(Name, Data, []), + {ok,BinData} = ?FILE_MODULE:read_file(Name), + + ok = ?FILE_MODULE:write_file(Name, Data, [raw]), + {ok,BinData} = ?FILE_MODULE:read_file(Name), + + ok; + {error,_}=Res -> + Res = ?FILE_MODULE:write_file(Name, Data, []), + Res = ?FILE_MODULE:write_file(Name, Data, [raw]), + Res + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c index 2990ddda41..b91dca61d4 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c +++ b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c @@ -17,7 +17,7 @@ * * %CopyrightEnd% */ -#include "erl_nif.h" +#include <erl_nif.h> #include <stdio.h> #include <string.h> diff --git a/lib/observer/doc/src/ttb.xml b/lib/observer/doc/src/ttb.xml index 42b0fa1d8a..7cd15e15d3 100644 --- a/lib/observer/doc/src/ttb.xml +++ b/lib/observer/doc/src/ttb.xml @@ -114,7 +114,8 @@ ttb:p(all, call).</input></pre> <v>Opt = {file,Client} | {handler, FormatHandler} | {process_info,PI} | shell | {shell, ShellSpec} | {timer, TimerSpec} | {overload_check, {MSec, Module, Function}} | - {flush, MSec} | resume | {resume, FetchTimeout}</v> + {flush, MSec} | resume | {resume, FetchTimeout} | + {queue_size, QueueSize}</v> <v>TimerSpec = MSec | {MSec, StopOpts}</v> <v>MSec = FetchTimeout = integer()</v> <v>Module = Function = atom() </v> @@ -126,6 +127,7 @@ ttb:p(all, call).</input></pre> <v>FormatHandler = See format/2</v> <v>PI = true | false </v> <v>ShellSpec = true | false | only</v> + <v>QueueSize = non_neg_integer()</v> </type> <desc> <p>Starts a file trace port on all specified nodes @@ -147,6 +149,18 @@ ttb:p(all, call).</input></pre> <c>Client</c> must be <c>{local, File}</c>. All trace information is then sent to the trace control node where it is written to file.</p></item> + <tag><c>queue_size</c></tag> + <item><p>When tracing to shell or <c>{local,File}</c>, an ip + trace driver is used internally. The ip trace driver has a + queue of maximum <c>QueueSize</c> messages waiting to be + delivered. If the driver cannot deliver messages as fast as + they are produced, the queue size might be exceeded and + messages are dropped. This parameter is optional, and is + only useful if many <c>{drop,N}</c> trace messages are + received by the trace handler. It has no meaning if shell + or <c>{local,File}</c> is not used. See + <seealso marker="runtime_tools:dbg#trace_port/2">dbg:trace_port/2</seealso> + for more information about the ip trace driver.</p></item> <tag><c>process_info</c></tag> <item><p>Indicates if process information is to be collected. If <c>PI = true</c> (which is diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl index ac6c4572eb..87a50e046b 100644 --- a/lib/observer/src/ttb.erl +++ b/lib/observer/src/ttb.erl @@ -78,6 +78,11 @@ do_tracer(Nodes0,PI,Client,Traci) -> do_tracer(Clients,PI,Traci) -> Shell = proplists:get_value(shell, Traci, false), + IpPortSpec = + case proplists:get_value(queue_size, Traci) of + undefined -> 0; + QS -> {0,QS} + end, DefShell = fun(Trace) -> dbg:dhandler(Trace, standard_io) end, {ClientSucc,Succ} = lists:foldl( @@ -98,7 +103,7 @@ do_tracer(Clients,PI,Traci) -> [_,H] = string:tokens(atom_to_list(N),"@"), H end, - case catch dbg:tracer(N,port,dbg:trace_port(ip,0)) of + case catch dbg:tracer(N,port,dbg:trace_port(ip,IpPortSpec)) of {ok,N} -> {ok,Port} = dbg:trace_port_control(N,get_listen_port), {ok,T} = dbg:get_tracer(N), @@ -160,6 +165,8 @@ opt([{resume,MSec}|O],{PI,Client,Traci}) -> opt(O,{PI,Client,[{resume, {true, MSec}}|Traci]}); opt([{flush,MSec}|O],{PI,Client,Traci}) -> opt(O,{PI,Client,[{flush, MSec}|Traci]}); +opt([{queue_size,QueueSize}|O],{PI,Client,Traci}) -> + opt(O,{PI,Client,[{queue_size,QueueSize}|Traci]}); opt([],Opt) -> ensure_opt(Opt). diff --git a/lib/parsetools/src/leex.erl b/lib/parsetools/src/leex.erl index 15d42a4d9c..602e47404d 100644 --- a/lib/parsetools/src/leex.erl +++ b/lib/parsetools/src/leex.erl @@ -1586,6 +1586,8 @@ out_dfa_graph(St, DFA, DF) -> case file:open(St#leex.gfile, [write]) of {ok,Gfile} -> try + %% Set the same encoding as infile: + set_encoding(St, Gfile), io:fwrite(Gfile, "digraph DFA {~n", []), out_dfa_states(Gfile, DFA, DF), out_dfa_edges(Gfile, DFA), @@ -1621,7 +1623,7 @@ out_dfa_edges(File, DFA) -> foreach(fun (T) -> Crs = orddict:fetch(T, Tdict), Edgelab = dfa_edgelabel(Crs), - io:fwrite(File, " ~b -> ~b [label=\"~s\"];~n", + io:fwrite(File, " ~b -> ~b [label=\"~ts\"];~n", [S,T,Edgelab]) end, sort(orddict:fetch_keys(Tdict))) end, DFA). diff --git a/lib/parsetools/test/leex_SUITE.erl b/lib/parsetools/test/leex_SUITE.erl index 949ef3c36e..84f9c996ac 100644 --- a/lib/parsetools/test/leex_SUITE.erl +++ b/lib/parsetools/test/leex_SUITE.erl @@ -408,12 +408,12 @@ unicode(Config) when is_list(Config) -> Ts = [{unicode_1, <<"%% -*- coding: utf-8 -*-\n" "Definitions.\n" - "RTLarrow = (←)\n" + "RTLarrow = (â)\n" "Rules.\n" - "{RTLarrow} : {token,{'<-',TokenLine}}.\n" + "{RTLarrow} : {token,{\"â\",TokenLine}}.\n" "Erlang code.\n" "-export([t/0]).\n" - "t() -> {ok, [{'<-', 1}], 1} = string(\"←\"), ok.">>, + "t() -> {ok, [{\"â\", 1}], 1} = string(\"â\"), ok.">>, default, ok}], @@ -1137,7 +1137,7 @@ run_test(Config, Def, Pre) -> XrlFile = filename:join(DataDir, DefFile), ErlFile = filename:join(DataDir, Filename), Opts = [return, warn_unused_vars,{outdir,DataDir}], - ok = file:write_file(XrlFile, Def, [{encoding, unicode}]), + ok = file:write_file(XrlFile, Def), LOpts = [return, {report, false} | case Pre of default -> diff --git a/lib/public_key/doc/src/public_key_app.xml b/lib/public_key/doc/src/public_key_app.xml index 1f87932b6c..923a9f1dfb 100644 --- a/lib/public_key/doc/src/public_key_app.xml +++ b/lib/public_key/doc/src/public_key_app.xml @@ -61,7 +61,7 @@ <section> <title>DEPENDENCIES</title> <p>The <c>public_key</c> application uses the - Crypto application to preform cryptographic operations and the + Crypto application to perform cryptographic operations and the ASN-1 application to handle PKIX-ASN-1 specifications, hence these applications must be loaded for the <c>public_key</c> application to work. In an embedded environment this means they must be started with @@ -72,7 +72,7 @@ <section> <title>ERROR LOGGER AND EVENT HANDLERS</title> <p> The <c>public_key</c> application is a library application - and does not use the error logger. The functions will either sucssed + and does not use the error logger. The functions will either succeed or fail with a runtime error. </p> </section> diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 3d2de9c21c..b589f5ef07 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -24,7 +24,7 @@ -#include "erl_nif.h" +#include <erl_nif.h> #include "config.h" #include "sys.h" #include "dtrace-wrapper.h" diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml index db04bfdf7b..95f74d4607 100644 --- a/lib/runtime_tools/doc/src/dbg.xml +++ b/lib/runtime_tools/doc/src/dbg.xml @@ -954,7 +954,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\ as the tuple <c>{drop, N}</c> where <c>N</c> is the number of consecutive messages dropped. In case of heavy tracing, drop's are likely to occur, and they surely occur if no client is reading the trace - messages.</p> + messages. The default value of <c>QueSize</c> is 200.</p> </desc> </func> <func> diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl index c0d4665bda..f17aa528ed 100644 --- a/lib/runtime_tools/src/dbg.erl +++ b/lib/runtime_tools/src/dbg.erl @@ -427,7 +427,7 @@ trace_port(file, Filename) -> trace_port1(file, Filename, nowrap); trace_port(ip, Portno) when is_integer(Portno) -> - trace_port(ip,{Portno,50}); + trace_port(ip,{Portno,200}); trace_port(ip, {Portno, Qsiz}) when is_integer(Portno), is_integer(Qsiz) -> fun() -> diff --git a/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c b/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c index ecdee7e3a2..ad90af4da0 100644 --- a/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c +++ b/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c @@ -18,7 +18,7 @@ * %CopyrightEnd% */ -#include "erl_nif.h" +#include <erl_nif.h> #include <stdio.h> #include <string.h> diff --git a/lib/sasl/doc/src/script.xml b/lib/sasl/doc/src/script.xml index 8ed132354d..b40ff28179 100644 --- a/lib/sasl/doc/src/script.xml +++ b/lib/sasl/doc/src/script.xml @@ -88,7 +88,7 @@ follows:</p> <list type="bulleted"> <item><c>-pa Dir1 Dir2 ... DirN</c> adds the directories - <c>Dir1, Dir2, ..., DirN</c> to the front of the initial + <c>DirN, DirN-1, ..., Dir2, Dir1</c> to the front of the initial load path.</item> <item><c>-pz Dir1 Dir2 ... DirN</c> adds the directories <c>Dir1, Dir2, ..., DirN</c> to the end of the initial diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl index 74cd2e081a..8af0ecc5f9 100644 --- a/lib/ssh/src/ssh_cli.erl +++ b/lib/ssh/src/ssh_cli.erl @@ -208,8 +208,15 @@ handle_msg({Group, Req}, #state{group = Group, buf = Buf, pty = Pty, write_chars(ConnectionHandler, ChannelId, Chars), {ok, State#state{buf = NewBuf}}; -handle_msg({'EXIT', Group, _Reason}, #state{group = Group, - channel = ChannelId} = State) -> +handle_msg({'EXIT', Group, Reason}, #state{group = Group, + cm = ConnectionHandler, + channel = ChannelId} = State) -> + Status = case Reason of + normal -> 0; + _ -> -1 + end, + ssh_connection:exit_status(ConnectionHandler, ChannelId, Status), + ssh_connection:send_eof(ConnectionHandler, ChannelId), {stop, ChannelId, State}; handle_msg(_, State) -> diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index d52d453007..51e0d5196b 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -67,7 +67,8 @@ shell_unicode_string/1, ssh_info_print/1, key_callback/1, - key_callback_options/1 + key_callback_options/1, + shell_exit_status/1 ]). %%% Common test callbacks @@ -106,7 +107,8 @@ all() -> multi_daemon_opt_fd, packet_size_zero, ssh_info_print, - {group, login_bad_pwd_no_retry} + {group, login_bad_pwd_no_retry}, + shell_exit_status ]. groups() -> @@ -1167,6 +1169,33 @@ login_bad_pwd_no_retry(Config, AuthMethods) -> end end. + +%%---------------------------------------------------------------------------- +%%% Test that when shell REPL exit with reason normal client receives status 0 +shell_exit_status(Config) when is_list(Config) -> + process_flag(trap_exit, true), + SystemDir = proplists:get_value(data_dir, Config), + UserDir = proplists:get_value(priv_dir, Config), + + ShellFun = fun (_User) -> spawn(fun() -> ok end) end, + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, + {user_passwords, [{"vego", "morot"}]}, + {shell, ShellFun}, + {failfun, fun ssh_test_lib:failfun/2}]), + ConnectionRef = + ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, + {user, "vego"}, + {password, "morot"}, + {user_interaction, false}]), + + {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), + ok = ssh_connection:shell(ConnectionRef, ChannelId), + ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId), + ssh:stop_daemon(Pid). + + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 212b99c695..09e707ad07 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,5 +1,5 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.3.2 +SSH_VSN = 4.3.3 APP_VSN = "ssh-$(SSH_VSN)" diff --git a/lib/stdlib/src/edlin_expand.erl b/lib/stdlib/src/edlin_expand.erl index ec64470461..5f821caef0 100644 --- a/lib/stdlib/src/edlin_expand.erl +++ b/lib/stdlib/src/edlin_expand.erl @@ -118,7 +118,7 @@ format_col([A|T], Width, Len, Acc0) -> {H1, _} -> H1; H2 -> H2 end, - Acc = [io_lib:format("~-*s", [Width,H]) | Acc0], + Acc = [io_lib:format("~-*ts", [Width,H]) | Acc0], format_col(T, Width, Len+Width, Acc); format_col([], _, _, Acc) -> lists:reverse(Acc, "\n"). diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 9877662743..e917b7ea1f 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + [{<<"3\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* {<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.* %% Down to - max one major revision back - [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + [{<<"3\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* {<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.* }. diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index c81e72689c..1cd65fbf18 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -1087,6 +1087,10 @@ wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz, wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1, TRef, EStack); + {'DOWN', _MRef, process, Pid, {shutdown, _}} -> + wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1, + TRef, EStack); + {'DOWN', _MRef, process, Pid, normal} when RType =/= permanent -> wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1, TRef, EStack); diff --git a/lib/stdlib/test/edlin_expand_SUITE.erl b/lib/stdlib/test/edlin_expand_SUITE.erl index ccffa2e244..718d91c6a3 100644 --- a/lib/stdlib/test/edlin_expand_SUITE.erl +++ b/lib/stdlib/test/edlin_expand_SUITE.erl @@ -21,7 +21,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2, init_per_group/2,end_per_group/2]). --export([normal/1, quoted_fun/1, quoted_module/1, quoted_both/1]). +-export([normal/1, quoted_fun/1, quoted_module/1, quoted_both/1, erl_1152/1]). -include_lib("common_test/include/ct.hrl"). @@ -36,7 +36,7 @@ suite() -> {timetrap,{minutes,1}}]. all() -> - [normal, quoted_fun, quoted_module, quoted_both]. + [normal, quoted_fun, quoted_module, quoted_both, erl_1152]. groups() -> []. @@ -149,5 +149,12 @@ quoted_both(Config) when is_list(Config) -> {yes,"weird-fun-name'()",[]} = do_expand("'ExpandTestCaps1':'#"), ok. +erl_1152(Config) when is_list(Config) -> + "\n"++"foo"++" "++[1089]++_ = do_format(["foo",[1089]]), + ok. + do_expand(String) -> edlin_expand:expand(lists:reverse(String)). + +do_format(StringList) -> + lists:flatten(edlin_expand:format_matches(StringList)). diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index b02d17bdb6..e726a29c9e 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -218,7 +218,7 @@ memory_check_summary(_Config) -> receive {get_failed_memchecks, FailedMemchecks} -> ok end, io:format("Failed memchecks: ~p\n",[FailedMemchecks]), NoFailedMemchecks = length(FailedMemchecks), - if NoFailedMemchecks > 3 -> + if NoFailedMemchecks > 1 -> ct:fail("Too many failed (~p) memchecks", [NoFailedMemchecks]); true -> ok @@ -591,12 +591,6 @@ select_fail_do(Opts) -> -define(S(T),ets:info(T,memory)). --define(TAB_STRUCT_SZ, erts_debug:get_internal_state('DbTable_words')). -%%-define(NORMAL_TAB_STRUCT_SZ, 26). %% SunOS5.8, 32-bit, non smp, private heap -%% -%% The hardcoded expected memory sizes (in words) are the ones we expect on: -%% SunOS5.8, 32-bit, non smp, private heap -%% %% Whitebox test of ets:info(X, memory). memory(Config) when is_list(Config) -> @@ -607,11 +601,11 @@ memory(Config) when is_list(Config) -> memory_do(Opts) -> L = [T1,T2,T3,T4] = fill_sets_int(1000,Opts), XR1 = case mem_mode(T1) of - {normal,_} -> {13836,13046,13046,13052}; %{13862,13072,13072,13078}; - {compressed,4} -> {11041,10251,10251,10252}; %{11067,10277,10277,10278}; - {compressed,8} -> {10050,9260,9260,9260} %{10076,9286,9286,9286} + {normal,_} -> {13836, 15346, 15346, 15346+6}; + {compressed,4} -> {11041, 12551, 12551, 12551+1}; + {compressed,8} -> {10050, 11560, 11560, 11560} end, - XRes1 = adjust_xmem(L, XR1), + XRes1 = adjust_xmem(L, XR1, 1), Res1 = {?S(T1),?S(T2),?S(T3),?S(T4)}, lists:foreach(fun(T) -> Before = ets:info(T,size), @@ -623,11 +617,11 @@ memory_do(Opts) -> end, L), XR2 = case mem_mode(T1) of - {normal,_} -> {13826,13037,13028,13034}; %{13852,13063,13054,13060}; - {compressed,4} -> {11031,10242,10233,10234}; %{11057,10268,10259,10260}; - {compressed,8} -> {10040,9251,9242,9242} %10066,9277,9268,9268} + {normal,_} -> {13826, 15337, 15337-9, 15337-3}; + {compressed,4} -> {11031, 12542, 12542-9, 12542-8}; + {compressed,8} -> {10040, 11551, 11551-9, 11551-9} end, - XRes2 = adjust_xmem(L, XR2), + XRes2 = adjust_xmem(L, XR2, 1), Res2 = {?S(T1),?S(T2),?S(T3),?S(T4)}, lists:foreach(fun(T) -> Before = ets:info(T,size), @@ -639,17 +633,17 @@ memory_do(Opts) -> end, L), XR3 = case mem_mode(T1) of - {normal,_} -> {13816,13028,13010,13016}; %{13842,13054,13036,13042}; - {compressed,4} -> {11021,10233,10215,10216}; %{11047,10259,10241,10242}; - {compressed,8} -> {10030,9242,9224,9224} %{10056,9268,9250,9250} + {normal,_} -> {13816, 15328, 15328-18, 15328-12}; + {compressed,4} -> {11021, 12533, 12533-18, 12533-17}; + {compressed,8} -> {10030, 11542, 11542-18, 11542-18} end, - XRes3 = adjust_xmem(L, XR3), + XRes3 = adjust_xmem(L, XR3, 1), Res3 = {?S(T1),?S(T2),?S(T3),?S(T4)}, lists:foreach(fun(T) -> ets:delete_all_objects(T) end, L), - XRes4 = adjust_xmem(L, {50,260,260,260}), %{76,286,286,286}), + XRes4 = adjust_xmem(L, {50, 256, 256, 256}, 0), Res4 = {?S(T1),?S(T2),?S(T3),?S(T4)}, lists:foreach(fun(T) -> ets:delete(T) @@ -660,7 +654,7 @@ memory_do(Opts) -> ets:select_delete(T,[{'_',[],[true]}]) end, L2), - XRes5 = adjust_xmem(L2, {50,260,260,260}), %{76,286,286,286}), + XRes5 = adjust_xmem(L2, {50, 256, 256, 256}, 0), Res5 = {?S(T11),?S(T12),?S(T13),?S(T14)}, io:format("XRes1 = ~p~n" " Res1 = ~p~n~n" @@ -698,15 +692,15 @@ chk_normal_tab_struct_size() -> erlang:system_info(smp_support), erlang:system_info(heap_type)}, io:format("System = ~p~n", [System]), - io:format("?TAB_STRUCT_SZ=~p~n", [?TAB_STRUCT_SZ]), ok. -adjust_xmem([_T1,_T2,_T3,_T4], {A0,B0,C0,D0} = _Mem0) -> +adjust_xmem([_T1,_T2,_T3,_T4], {A0,B0,C0,D0} = _Mem0, EstCnt) -> %% Adjust for 64-bit, smp, and os: %% Table struct size may differ. - TabDiff = ?TAB_STRUCT_SZ, - {A0+TabDiff, B0+TabDiff, C0+TabDiff, D0+TabDiff}. + {TabSz, EstSz} = erts_debug:get_internal_state('DbTable_words'), + HTabSz = TabSz + EstCnt*EstSz, + {A0+TabSz, B0+HTabSz, C0+HTabSz, D0+HTabSz}. %% Misc. whitebox tests t_whitebox(Config) when is_list(Config) -> @@ -1908,7 +1902,7 @@ evil_counter(I,Opts) -> end, Start = Start0 + rand:uniform(100000), ets:insert(T, {dracula,Start}), - Iter = 40000, + Iter = 40000 div syrup_factor(), End = Start + Iter, End = evil_counter_1(Iter, T), ets:delete(T). @@ -3302,7 +3296,8 @@ evil_delete_owner(Name, Flags, Data, Fix) -> exit_large_table_owner(Config) when is_list(Config) -> %%Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 500000)], - FEData = fun(Do) -> repeat_while(fun(500000) -> {false,ok}; + Laps = 500000 div syrup_factor(), + FEData = fun(Do) -> repeat_while(fun(I) when I =:= Laps -> {false,ok}; (I) -> Do({erlang:phash2(I, 16#ffffff),I}), {true, I+1} end, 1) @@ -3318,7 +3313,8 @@ exit_large_table_owner_do(Opts,{FEData,Config}) -> exit_many_large_table_owner(Config) when is_list(Config) -> ct:timetrap({minutes,30}), %% valgrind needs a lot %%Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 500000)], - FEData = fun(Do) -> repeat_while(fun(500000) -> {false,ok}; + Laps = 500000 div syrup_factor(), + FEData = fun(Do) -> repeat_while(fun(I) when I =:= Laps -> {false,ok}; (I) -> Do({erlang:phash2(I, 16#ffffff),I}), {true, I+1} end, 1) @@ -4271,7 +4267,8 @@ heavy_lookup_element_do(Opts) -> Tab = ets_new(foobar_table, [set, protected, {keypos, 2} | Opts]), ok = fill_tab2(Tab, 0, 7000), %% lookup ALL elements 50 times - _ = [do_lookup_element(Tab, 6999, 1) || _ <- lists:seq(1, 50)], + Laps = 50 div syrup_factor(), + _ = [do_lookup_element(Tab, 6999, 1) || _ <- lists:seq(1, Laps)], true = ets:delete(Tab), verify_etsmem(EtsMem). @@ -4295,6 +4292,7 @@ heavy_concurrent(Config) when is_list(Config) -> do_heavy_concurrent(Opts) -> Size = 10000, + Laps = 10000 div syrup_factor(), EtsMem = etsmem(), Tab = ets_new(blupp, [set, public, {keypos, 2} | Opts]), ok = fill_tab2(Tab, 0, Size), @@ -4302,7 +4300,7 @@ do_heavy_concurrent(Opts) -> fun (N) -> my_spawn_link( fun () -> - do_heavy_concurrent_proc(Tab, Size, N) + do_heavy_concurrent_proc(Tab, Laps, N) end) end, lists:seq(1, 500)), @@ -5363,12 +5361,12 @@ verify_table_load(T) -> Stats = ets:info(T,stats), {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_} = Stats, ok = if - AvgLen > 7 -> + AvgLen > 1.2 -> io:format("Table overloaded: Stats=~p\n~p\n", [Stats, ets:info(T)]), false; - Buckets>256, AvgLen < 6 -> + Buckets>256, AvgLen < 0.47 -> io:format("Table underloaded: Stats=~p\n~p\n", [Stats, ets:info(T)]), false; @@ -5442,7 +5440,8 @@ smp_select_delete(Config) when is_list(Config) -> Eq+1 end, 0, TotCnts), - verify_table_load(T), + %% May fail as select_delete does not shrink table (enough) + %%verify_table_load(T), LeftInTab = ets:select_delete(T, [{{'$1','$1'}, [], [true]}]), 0 = ets:info(T,size), false = ets:info(T,fixed), @@ -5718,27 +5717,45 @@ etsmem() -> {Bl0+Bl,BlSz0+BlSz} end, {0,0}, CS) end}, - {Mem,AllTabs}. + {Mem,AllTabs, erts_debug:get_internal_state('DbTable_meta')}. -verify_etsmem({MemInfo,AllTabs}) -> +verify_etsmem(EtsMem) -> wait_for_test_procs(), + verify_etsmem(EtsMem, false). + +verify_etsmem({MemInfo,AllTabs,MetaState}=EtsMem, Adjusted) -> case etsmem() of - {MemInfo,_} -> + {MemInfo,_,_} -> io:format("Ets mem info: ~p", [MemInfo]), case MemInfo of {ErlMem,EtsAlloc} when ErlMem == notsup; EtsAlloc == undefined -> %% Use 'erl +Mea max' to do more complete memory leak testing. {comment,"Incomplete or no mem leak testing"}; _ -> - ok + case Adjusted of + true -> + {comment, "Meta state adjusted"}; + false -> + ok + end end; - {MemInfo2, AllTabs2} -> + + {MemInfo2, AllTabs2, MetaState2} -> io:format("Expected: ~p", [MemInfo]), io:format("Actual: ~p", [MemInfo2]), io:format("Changed tables before: ~p\n",[AllTabs -- AllTabs2]), io:format("Changed tables after: ~p\n", [AllTabs2 -- AllTabs]), - ets_test_spawn_logger ! {failed_memcheck, get('__ETS_TEST_CASE__')}, - {comment, "Failed memory check"} + io:format("Meta state before: ~p\n", [MetaState]), + io:format("Meta state after: ~p\n", [MetaState2]), + case {MetaState =:= MetaState2, Adjusted} of + {false, false} -> + io:format("Adjust meta state and retry...\n\n",[]), + {ok,ok} = erts_debug:set_internal_state('DbTable_meta', MetaState), + verify_etsmem(EtsMem, true); + _ -> + ets_test_spawn_logger ! {failed_memcheck, get('__ETS_TEST_CASE__')}, + {comment, "Failed memory check"} + end end. @@ -6261,3 +6278,9 @@ do_tc(Do, Report) -> T2 = erlang:monotonic_time(), Elapsed = erlang:convert_time_unit(T2 - T1, native, milli_seconds), Report(Elapsed). + +syrup_factor() -> + case erlang:system_info(build_type) of + valgrind -> 20; + _ -> 1 + end. |