diff options
Diffstat (limited to 'lib')
127 files changed, 2604 insertions, 778 deletions
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml index 22ca7840de..284a2b4ce5 100644 --- a/lib/asn1/doc/src/notes.xml +++ b/lib/asn1/doc/src/notes.xml @@ -32,6 +32,32 @@ <p>This document describes the changes made to the asn1 application.</p> +<section><title>Asn1 5.0.9</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + <item> + <p>Corrected problems with the following value + definitions:</p> <list> <item>value of SEQUENCE OF CHOICE + with extensions</item> <item>value of CHOICE with + extensions</item> <item>DEFAULT used with OCTET + STRING</item> </list> + <p> + Own Id: OTP-15697 Aux Id: PR-2159 </p> + </item> + </list> + </section> + +</section> + <section><title>Asn1 5.0.8</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk index 69f1af28e8..018beda307 100644 --- a/lib/asn1/vsn.mk +++ b/lib/asn1/vsn.mk @@ -1 +1 @@ -ASN1_VSN = 5.0.8 +ASN1_VSN = 5.0.9 diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml index 9456b6dbba..a64818da7b 100644 --- a/lib/common_test/doc/src/notes.xml +++ b/lib/common_test/doc/src/notes.xml @@ -33,6 +33,35 @@ <file>notes.xml</file> </header> +<section><title>Common_Test 1.17.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Use <c>ssh</c> instead of <c>rsh</c> as the default + remote shell. </p> + <p> + Own Id: OTP-15633 Aux Id: PR-1787 </p> + </item> + </list> + </section> + +</section> + <section><title>Common_Test 1.17.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk index 14a3622a00..8dcb69c1c6 100644 --- a/lib/common_test/vsn.mk +++ b/lib/common_test/vsn.mk @@ -1 +1 @@ -COMMON_TEST_VSN = 1.17.1 +COMMON_TEST_VSN = 1.17.3 diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index d45dfef8f3..275c6268fa 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,99 @@ <p>This document describes the changes made to the Compiler application.</p> +<section><title>Compiler 7.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p><c>record_info/2</c> is a pseudo-function that + requires literal arguments known at compile time. + Therefore, the following usage is illegal: <c>fun + record/info/2</c>. The compiler would crash when during + compilation of that kind of code. Corrected to issue a + compilation error.</p> + <p> + Own Id: OTP-15760 Aux Id: ERL-907 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The compiler has been rewritten to internally use an + intermediate representation based on Static Single + Assignment (SSA). The new intermediate representation + makes more optimizations possible.</p> + <p> + Most noticeable is that the binary matching optimizations + are now applicable in many more circumstances than + before.</p> + <p> + Another noticeable change is that type optimizations are + now applied across local function calls, and will remove + a lot more redundant type tests than before.</p> + <p> + Own Id: OTP-14894 Aux Id: ERL-714 </p> + </item> + <item> + <p>Funs are no longer created when they are only used + locally, greatly improving the performance of named funs + and "fun-wrapped" macros.</p> + <p> + Own Id: OTP-15273 Aux Id: ERL-639 </p> + </item> + <item> + <p>All compiler options that can be given in the source + file can now also be given in the option list or from the + command line for <c>erlc</c>.</p> + <p>Specifically, the option + <c>{nowarn_deprecated_function,MFAs}</c> was only + recognized when given in the file with the attribute + <c>-compile()</c>. The option + <c>{nowarn_unused_function,FAs}</c> was incorrectly + documented to only work in a file, but it also worked + when given in the option list.</p> + <p> + Own Id: OTP-15456</p> + </item> + <item> + <p> Do not allow function specifications for functions + residing in other modules. </p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15563 Aux Id: ERL-845, OTP-15562 </p> + </item> + <item> + <p>Internal documentation has now been added to the + <em>Erts</em> and <em>Compiler</em> applications.</p> + <p>The internal documents for <em>Erts</em> describe + miscellaneous interesting implementation details. Those + details can change at any time.</p> + <p>The internal documentation for <em>Compiler</em> + documents the API for the Core Erlang modules. While we + will not change those APIs without good reason, we don't + give the same guarantees about backward compatibility as + for the rest of the APIs in OTP.</p> + <p> + Own Id: OTP-15715</p> + </item> + <item> + <p> There are new compiler options <c>nowarn_removed</c> + and <c>{nowarn_removed,Items}</c> to suppress warnings + for functions and modules that have been removed from + OTP.</p> + <p> + Own Id: OTP-15749 Aux Id: ERL-904 </p> + </item> + </list> + </section> + +</section> + <section><title>Compiler 7.3.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index 87b0d345f2..0c1dc30f9c 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -52,7 +52,6 @@ MODULES = \ beam_clean \ beam_dict \ beam_disasm \ - beam_except \ beam_flatten \ beam_jump \ beam_listing \ diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl index 707974b2c1..a734ca3a10 100644 --- a/lib/compiler/src/beam_block.erl +++ b/lib/compiler/src/beam_block.erl @@ -33,8 +33,9 @@ module({Mod,Exp,Attr,Fs0,Lc}, _Opts) -> function({function,Name,Arity,CLabel,Is0}) -> try - Is1 = blockify(Is0), - Is = embed_lines(Is1), + Is1 = swap_opt(Is0), + Is2 = blockify(Is1), + Is = embed_lines(Is2), {function,Name,Arity,CLabel,Is} catch Class:Error:Stack -> @@ -42,6 +43,40 @@ function({function,Name,Arity,CLabel,Is0}) -> erlang:raise(Class, Error, Stack) end. +%%% +%%% Try to use a `swap` instruction instead of a sequence of moves. +%%% +%%% Note that beam_ssa_codegen generates `swap` instructions only for +%%% the moves within a single SSA instruction (such as `call`), not +%%% for the moves generated by a sequence of SSA instructions. +%%% Therefore, this optimization is needed. +%%% + +swap_opt([{move,Reg1,{x,X}=Temp}=Move1, + {move,Reg2,Reg1}=Move2, + {move,Temp,Reg2}=Move3|Is]) when Reg1 =/= Temp -> + case is_unused(X, Is) of + true -> + [{swap,Reg1,Reg2}|swap_opt(Is)]; + false -> + [Move1|swap_opt([Move2,Move3|Is])] + end; +swap_opt([I|Is]) -> + [I|swap_opt(Is)]; +swap_opt([]) -> []. + +is_unused(X, [{call,A,_}|_]) when A =< X -> true; +is_unused(X, [{call_ext,A,_}|_]) when A =< X -> true; +is_unused(X, [{make_fun2,_,_,_,A}|_]) when A =< X -> true; +is_unused(X, [{move,Src,Dst}|Is]) -> + case {Src,Dst} of + {{x,X},_} -> false; + {_,{x,X}} -> true; + {_,_} -> is_unused(X, Is) + end; +is_unused(X, [{line,_}|Is]) -> is_unused(X, Is); +is_unused(_, _) -> false. + %% blockify(Instructions0) -> Instructions %% Collect sequences of instructions to basic blocks. %% Also do some simple optimations on instructions outside the blocks. diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl index 7299654476..6b2b2ce085 100644 --- a/lib/compiler/src/beam_clean.erl +++ b/lib/compiler/src/beam_clean.erl @@ -34,7 +34,8 @@ module({Mod,Exp,Attr,Fs0,_}, Opts) -> Used = find_all_used(WorkList, All, cerl_sets:from_list(WorkList)), Fs1 = remove_unused(Order, Used, All), {Fs2,Lc} = clean_labels(Fs1), - Fs = maybe_remove_lines(Fs2, Opts), + Fs3 = fix_swap(Fs2, Opts), + Fs = maybe_remove_lines(Fs3, Opts), {ok,{Mod,Exp,Attr,Fs,Lc}}. %% Determine the rootset, i.e. exported functions and @@ -137,31 +138,54 @@ function_replace([{function,Name,Arity,Entry,Asm0}|Fs], Dict, Acc) -> function_replace([], _, Acc) -> Acc. %%% +%%% If compatibility with a previous release (OTP 22 or earlier) has +%%% been requested, replace swap instructions with a sequence of moves. +%%% + +fix_swap(Fs, Opts) -> + case proplists:get_bool(no_swap, Opts) of + false -> Fs; + true -> fold_functions(fun swap_moves/1, Fs) + end. + +swap_moves([{swap,Reg1,Reg2}|Is]) -> + Temp = {x,1022}, + [{move,Reg1,Temp},{move,Reg2,Reg1},{move,Temp,Reg2}|swap_moves(Is)]; +swap_moves([I|Is]) -> + [I|swap_moves(Is)]; +swap_moves([]) -> []. + +%%% %%% Remove line instructions if requested. %%% maybe_remove_lines(Fs, Opts) -> case proplists:get_bool(no_line_info, Opts) of false -> Fs; - true -> remove_lines(Fs) + true -> fold_functions(fun remove_lines/1, Fs) end. -remove_lines([{function,N,A,Lbl,Is0}|T]) -> - Is = remove_lines_fun(Is0), - [{function,N,A,Lbl,Is}|remove_lines(T)]; -remove_lines([]) -> []. - -remove_lines_fun([{line,_}|Is]) -> - remove_lines_fun(Is); -remove_lines_fun([{block,Bl0}|Is]) -> +remove_lines([{line,_}|Is]) -> + remove_lines(Is); +remove_lines([{block,Bl0}|Is]) -> Bl = remove_lines_block(Bl0), - [{block,Bl}|remove_lines_fun(Is)]; -remove_lines_fun([I|Is]) -> - [I|remove_lines_fun(Is)]; -remove_lines_fun([]) -> []. + [{block,Bl}|remove_lines(Is)]; +remove_lines([I|Is]) -> + [I|remove_lines(Is)]; +remove_lines([]) -> []. remove_lines_block([{set,_,_,{line,_}}|Is]) -> remove_lines_block(Is); remove_lines_block([I|Is]) -> [I|remove_lines_block(Is)]; remove_lines_block([]) -> []. + + +%%% +%%% Helpers. +%%% + +fold_functions(F, [{function,N,A,Lbl,Is0}|T]) -> + Is = F(Is0), + [{function,N,A,Lbl,Is}|fold_functions(F, T)]; +fold_functions(_F, []) -> []. diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl index 7d048716e4..45b69d7e95 100644 --- a/lib/compiler/src/beam_disasm.erl +++ b/lib/compiler/src/beam_disasm.erl @@ -1123,6 +1123,13 @@ resolve_inst({put_tuple2,[Dst,{{z,1},{u,_},List0}]},_,_,_) -> {put_tuple2,Dst,{list,List}}; %% +%% OTP 23. +%% +resolve_inst({swap,[_,_]=List},_,_,_) -> + [R1,R2] = resolve_args(List), + {swap,R1,R2}; + +%% %% Catches instructions that are not yet handled. %% resolve_inst(X,_,_,_) -> ?exit({resolve_inst,X}). diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl deleted file mode 100644 index 28c89782c9..0000000000 --- a/lib/compiler/src/beam_except.erl +++ /dev/null @@ -1,244 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2011-2018. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(beam_except). --export([module/2]). - -%%% Rewrite certain calls to erlang:error/{1,2} to specialized -%%% instructions: -%%% -%%% erlang:error({badmatch,Value}) => badmatch Value -%%% erlang:error({case_clause,Value}) => case_end Value -%%% erlang:error({try_clause,Value}) => try_case_end Value -%%% erlang:error(if_clause) => if_end -%%% erlang:error(function_clause, Args) => jump FuncInfoLabel -%%% - --import(lists, [reverse/1,reverse/2,seq/2,splitwith/2]). - --spec module(beam_utils:module_code(), [compile:option()]) -> - {'ok',beam_utils:module_code()}. - -module({Mod,Exp,Attr,Fs0,Lc}, _Opt) -> - Fs = [function(F) || F <- Fs0], - {ok,{Mod,Exp,Attr,Fs,Lc}}. - -function({function,Name,Arity,CLabel,Is0}) -> - try - Is = function_1(Is0), - {function,Name,Arity,CLabel,Is} - catch - Class:Error:Stack -> - io:fwrite("Function: ~w/~w\n", [Name,Arity]), - erlang:raise(Class, Error, Stack) - end. - --record(st, - {lbl :: beam_asm:label(), %func_info label - loc :: [_], %location for func_info - arity :: arity() %arity for function - }). - -function_1(Is0) -> - case Is0 of - [{label,Lbl},{line,Loc},{func_info,_,_,Arity}|_] -> - St = #st{lbl=Lbl,loc=Loc,arity=Arity}, - translate(Is0, St, []); - [{label,_}|_] -> - %% No line numbers. The source must be a .S file. - %% There is no need to do anything. - Is0 - end. - -translate([{call_ext,Ar,{extfunc,erlang,error,Ar}}=I|Is], St, Acc) -> - translate_1(Ar, I, Is, St, Acc); -translate([I|Is], St, Acc) -> - translate(Is, St, [I|Acc]); -translate([], _, Acc) -> - reverse(Acc). - -translate_1(Ar, I, Is, #st{arity=Arity}=St, [{line,_}=Line|Acc1]=Acc0) -> - case dig_out(Ar, Arity, Acc1) of - no -> - translate(Is, St, [I|Acc0]); - {yes,function_clause,Acc2} -> - case {Is,Line,St} of - {[return|_],{line,Loc},#st{lbl=Fi,loc=Loc}} -> - Instr = {jump,{f,Fi}}, - translate(Is, St, [Instr|Acc2]); - {_,_,_} -> - %% Not a call_only instruction, or not the same - %% location information as in in the line instruction - %% before the func_info instruction. Not safe - %% to translate to a jump. - translate(Is, St, [I|Acc0]) - end; - {yes,Instr,Acc2} -> - translate(Is, St, [Instr,Line|Acc2]) - end. - -dig_out(1, _Arity, Is) -> - dig_out(Is); -dig_out(2, Arity, Is) -> - dig_out_fc(Arity, Is); -dig_out(_, _, _) -> no. - -dig_out([{block,Bl0}|Is]) -> - case dig_out_block(reverse(Bl0)) of - no -> no; - {yes,What,[]} -> - {yes,What,Is}; - {yes,What,Bl} -> - {yes,What,[{block,Bl}|Is]} - end; -dig_out(_) -> no. - -dig_out_block([{set,[{x,0}],[{atom,if_clause}],move}]) -> - {yes,if_end,[]}; -dig_out_block([{set,[{x,0}],[{literal,{Exc,Value}}],move}|Is]) -> - translate_exception(Exc, {literal,Value}, Is, 0); -dig_out_block([{set,[{x,0}],[{atom,Exc},Value],put_tuple2}|Is]) -> - translate_exception(Exc, Value, Is, 3); -dig_out_block(_) -> no. - -translate_exception(badmatch, Val, Is, Words) -> - {yes,{badmatch,Val},fix_block(Is, Words)}; -translate_exception(case_clause, Val, Is, Words) -> - {yes,{case_end,Val},fix_block(Is, Words)}; -translate_exception(try_clause, Val, Is, Words) -> - {yes,{try_case_end,Val},fix_block(Is, Words)}; -translate_exception(_, _, _, _) -> no. - -fix_block(Is, 0) -> - reverse(Is); -fix_block(Is, Words) -> - reverse(fix_block_1(Is, Words)). - -fix_block_1([{set,[],[],{alloc,Live,{F1,F2,Needed0,F3}}}|Is], Words) -> - case Needed0 - Words of - 0 -> - Is; - Needed -> - true = Needed >= 0, %Assertion. - [{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is] - end; -fix_block_1([I|Is], Words) -> - [I|fix_block_1(Is, Words)]. - - -dig_out_fc(Arity, Is0) -> - Regs0 = maps:from_list([{{x,X},{arg,X}} || X <- seq(0, Arity-1)]), - {Is,Acc0} = splitwith(fun({label,_}) -> false; - ({test,_,_,_}) -> false; - (_) -> true - end, Is0), - {Regs,Acc} = dig_out_fc_1(reverse(Is), Regs0, Acc0), - case Regs of - #{{x,0}:={atom,function_clause},{x,1}:=Args} -> - case moves_from_stack(Args, 0, []) of - {Moves,Arity} -> - {yes,function_clause,reverse(Moves, Acc)}; - {_,_} -> - no - end; - #{} -> - no - end. - -dig_out_fc_1([{block,Bl}|Is], Regs0, Acc) -> - Regs = dig_out_fc_block(Bl, Regs0), - dig_out_fc_1(Is, Regs, Acc); -dig_out_fc_1([{bs_set_position,_,_}=I|Is], Regs, Acc) -> - dig_out_fc_1(Is, Regs, [I|Acc]); -dig_out_fc_1([{bs_get_tail,Src,Dst,Live0}|Is], Regs0, Acc) -> - Regs = prune_xregs(Live0, Regs0), - Live = dig_out_stack_live(Regs, Live0), - I = {bs_get_tail,Src,Dst,Live}, - dig_out_fc_1(Is, Regs, [I|Acc]); -dig_out_fc_1([_|_], _Regs, _Acc) -> - {#{},[]}; -dig_out_fc_1([], Regs, Acc) -> - {Regs,Acc}. - -dig_out_fc_block([{set,[],[],{alloc,Live,_}}|Is], Regs0) -> - Regs = prune_xregs(Live, Regs0), - dig_out_fc_block(Is, Regs); -dig_out_fc_block([{set,[Dst],[Hd,Tl],put_list}|Is], Regs0) -> - Regs = Regs0#{Dst=>{cons,get_reg(Hd, Regs0),get_reg(Tl, Regs0)}}, - dig_out_fc_block(Is, Regs); -dig_out_fc_block([{set,[Dst],[Src],move}|Is], Regs0) -> - Regs = Regs0#{Dst=>get_reg(Src, Regs0)}, - dig_out_fc_block(Is, Regs); -dig_out_fc_block([{set,_,_,_}|_], _Regs) -> - %% Unknown instruction. Fail. - #{}; -dig_out_fc_block([], Regs) -> Regs. - -dig_out_stack_live(Regs, Default) -> - Reg = {x,2}, - case Regs of - #{Reg:=List} -> - dig_out_stack_live_1(List, Default); - #{} -> - Default - end. - -dig_out_stack_live_1({cons,{arg,N},T}, Live) -> - dig_out_stack_live_1(T, max(N + 1, Live)); -dig_out_stack_live_1({cons,_,T}, Live) -> - dig_out_stack_live_1(T, Live); -dig_out_stack_live_1(nil, Live) -> - Live; -dig_out_stack_live_1(_, Live) -> Live. - -prune_xregs(Live, Regs) -> - maps:filter(fun({x,X}, _) -> X < Live end, Regs). - -moves_from_stack({cons,{arg,N},_}, I, _Acc) when N =/= I -> - %% Wrong argument. Give up. - {[],-1}; -moves_from_stack({cons,H,T}, I, Acc) -> - case H of - {arg,I} -> - moves_from_stack(T, I+1, Acc); - _ -> - moves_from_stack(T, I+1, [{move,H,{x,I}}|Acc]) - end; -moves_from_stack(nil, I, Acc) -> - {reverse(Acc),I}; -moves_from_stack({literal,[H|T]}, I, Acc) -> - Cons = {cons,tag_literal(H),tag_literal(T)}, - moves_from_stack(Cons, I, Acc); -moves_from_stack(_, _, _) -> - %% Not understood. Give up. - {[],-1}. - - -get_reg(R, Regs) -> - case Regs of - #{R:=Val} -> Val; - #{} -> R - end. - -tag_literal([]) -> nil; -tag_literal(T) when is_atom(T) -> {atom,T}; -tag_literal(T) when is_float(T) -> {float,T}; -tag_literal(T) when is_integer(T) -> {integer,T}; -tag_literal(T) -> {literal,T}. diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl index a9977b0b1d..e8b77e382f 100644 --- a/lib/compiler/src/beam_ssa.erl +++ b/lib/compiler/src/beam_ssa.erl @@ -118,7 +118,7 @@ %% Primops only used internally during code generation. -type cg_prim_op() :: 'bs_get' | 'bs_match_string' | 'bs_restore' | 'bs_skip' | - 'copy' | 'put_tuple_arity' | 'put_tuple_element' | + 'copy' | 'match_fail' | 'put_tuple_arity' | 'put_tuple_element' | 'set_tuple_element'. -import(lists, [foldl/3,keyfind/3,mapfoldl/3,member/2,reverse/1]). diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl index c2d5035b19..02b644f41a 100644 --- a/lib/compiler/src/beam_ssa_codegen.erl +++ b/lib/compiler/src/beam_ssa_codegen.erl @@ -28,7 +28,7 @@ -include("beam_ssa.hrl"). --import(lists, [foldl/3,keymember/3,keysort/2,last/1,map/2,mapfoldl/3, +-import(lists, [foldl/3,keymember/3,keysort/2,map/2,mapfoldl/3, reverse/1,reverse/2,sort/1,splitwith/2,takewhile/2]). -record(cg, {lcount=1 :: beam_label(), %Label counter @@ -37,7 +37,8 @@ used_labels=gb_sets:empty() :: gb_sets:set(ssa_label()), regs=#{} :: #{beam_ssa:var_name()=>ssa_register()}, ultimate_fail=1 :: beam_label(), - catches=gb_sets:empty() :: gb_sets:set(ssa_label()) + catches=gb_sets:empty() :: gb_sets:set(ssa_label()), + fc_label=1 :: beam_label() }). -spec module(beam_ssa:b_module(), [compile:option()]) -> @@ -124,7 +125,7 @@ function(#b_function{anno=Anno,bs=Blocks}, AtomMod, St0) -> Labels = (St4#cg.labels)#{0=>Entry,?BADARG_BLOCK=>0}, St5 = St4#cg{labels=Labels,used_labels=gb_sets:singleton(Entry), ultimate_fail=Ult}, - {Body,St} = cg_fun(Blocks, St5), + {Body,St} = cg_fun(Blocks, St5#cg{fc_label=Fi}), Asm = [{label,Fi},line(Anno), {func_info,AtomMod,{atom,Name},Arity}] ++ add_parameter_annos(Body, Anno) ++ @@ -384,6 +385,7 @@ classify_heap_need(is_tagged_tuple) -> neutral; classify_heap_need(kill_try_tag) -> gc; classify_heap_need(landingpad) -> gc; classify_heap_need(make_fun) -> gc; +classify_heap_need(match_fail) -> gc; classify_heap_need(new_try_tag) -> gc; classify_heap_need(peek_message) -> gc; classify_heap_need(put_map) -> gc; @@ -1160,6 +1162,10 @@ cg_block([#cg_set{op=call}=I, #cg_set{op=succeeded,dst=Bool}], {Bool,_Fail}, St) -> %% A call in try/catch block. cg_block([I], none, St); +cg_block([#cg_set{op=match_fail}=I, + #cg_set{op=succeeded,dst=Bool}], {Bool,_Fail}, St) -> + %% A match_fail instruction in a try/catch block. + cg_block([I], none, St); cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=I, #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) -> [Dst|Args] = beam_args([Dst0|Args0], St), @@ -1216,6 +1222,28 @@ cg_block([#cg_set{op=copy}|_]=T0, Context, St0) -> no -> {Is,St} end; +cg_block([#cg_set{op=match_fail,args=Args0,anno=Anno}], none, St) -> + Args = beam_args(Args0, St), + Is = cg_match_fail(Args, line(Anno), none), + {Is,St}; +cg_block([#cg_set{op=match_fail,args=Args0,anno=Anno}|T], Context, St0) -> + FcLabel = case Context of + {return,_,none} -> + %% There is no stack frame. If this is a function_clause + %% exception, it is safe to jump to the label of the + %% func_info instruction. + St0#cg.fc_label; + _ -> + %% This is most probably not a function_clause. + %% If this is a function_clause exception + %% (rare), it is not safe to jump to the + %% func_info label. + none + end, + Args = beam_args(Args0, St0), + Is0 = cg_match_fail(Args, line(Anno), FcLabel), + {Is1,St} = cg_block(T, Context, St0), + {Is0++Is1,St}; cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=Set], none, St) -> [Dst|Args] = beam_args([Dst0|Args0], St), Is = cg_instr(Op, Args, Dst, Set), @@ -1247,8 +1275,7 @@ cg_copy(T0, St) -> end, T0), Moves0 = cg_copy_1(Copies, St), Moves1 = [Move || {move,Src,Dst}=Move <- Moves0, Src =/= Dst], - Scratch = {x,1022}, - Moves = order_moves(Moves1, Scratch), + Moves = order_moves(Moves1), {Moves,T}. cg_copy_1([#cg_set{dst=Dst0,args=Args}|T], St) -> @@ -1489,6 +1516,42 @@ cg_call(#cg_set{anno=Anno,op=call,dst=Dst0,args=Args0}, Is = setup_args(Args++[Func], Anno, Context, St) ++ Line ++ Call, {Is,St}. +cg_match_fail([{atom,function_clause}|Args], Line, Fc) -> + case Fc of + none -> + %% There is a stack frame (probably because of inlining). + %% Jumping to the func_info label is not allowed by + %% beam_validator. Rewrite the instruction as a call to + %% erlang:error/2. + make_fc(Args, Line); + _ -> + setup_args(Args) ++ [{jump,{f,Fc}}] + end; +cg_match_fail([{atom,Op}], Line, _Fc) -> + [Line,Op]; +cg_match_fail([{atom,Op},Val], Line, _Fc) -> + [Line,{Op,Val}]. + +make_fc(Args, Line) -> + %% Recreate the original call to erlang:error/2. + Live = foldl(fun({x,X}, A) -> max(X+1, A); + (_, A) -> A + end, 0, Args), + TmpReg = {x,Live}, + StkMoves = build_stk(reverse(Args), TmpReg, nil), + [{test_heap,2*length(Args),Live}|StkMoves] ++ + [{move,{atom,function_clause},{x,0}}, + Line, + {call_ext,2,{extfunc,erlang,error,2}}]. + +build_stk([V], _TmpReg, Tail) -> + [{put_list,V,Tail,{x,1}}]; +build_stk([V|Vs], TmpReg, Tail) -> + I = {put_list,V,Tail,TmpReg}, + [I|build_stk(Vs, TmpReg, TmpReg)]; +build_stk([], _TmpReg, nil) -> + [{move,nil,{x,1}}]. + build_call(call_fun, Arity, _Func, none, Dst) -> [{call_fun,Arity}|copy({x,0}, Dst)]; build_call(call_fun, Arity, _Func, {return,Dst,N}, Dst) when is_integer(N) -> @@ -1527,15 +1590,15 @@ build_apply(Arity, {return,Val,N}, _Dst) when is_integer(N) -> build_apply(Arity, none, Dst) -> [{apply,Arity}|copy({x,0}, Dst)]. -cg_instr(put_map, [{atom,assoc},SrcMap|Ss], Dst, Set) -> - Live = get_live(Set), - [{put_map_assoc,{f,0},SrcMap,Dst,Live,{list,Ss}}]; cg_instr(bs_get_tail, [Src], Dst, Set) -> Live = get_live(Set), [{bs_get_tail,Src,Dst,Live}]; cg_instr(bs_get_position, [Ctx], Dst, Set) -> Live = get_live(Set), [{bs_get_position,Ctx,Dst,Live}]; +cg_instr(put_map, [{atom,assoc},SrcMap|Ss], Dst, Set) -> + Live = get_live(Set), + [{put_map_assoc,{f,0},SrcMap,Dst,Live,{list,Ss}}]; cg_instr(Op, Args, Dst, _Set) -> cg_instr(Op, Args, Dst). @@ -1707,7 +1770,7 @@ cg_catch(Agg, T0, Context, St0) -> cg_try(Agg, Tag, T0, Context, St0) -> {Moves0,T1} = cg_extract(T0, Agg, St0), - Moves = order_moves(Moves0, {x,3}), + Moves = order_moves(Moves0), [#cg_set{op=kill_try_tag}|T2] = T1, {T,St} = cg_block(T2, Context, St0), {[{try_case,Tag}|Moves++T],St}. @@ -1863,8 +1926,7 @@ setup_args([]) -> []; setup_args([_|_]=Args) -> Moves = gen_moves(Args, 0, []), - Scratch = {x,1+last(sort([length(Args)-1|[X || {x,X} <- Args]]))}, - order_moves(Moves, Scratch). + order_moves(Moves). %% kill_yregs(Anno, #cg{}) -> [{kill,{y,Y}}]. %% Kill Y registers that will not be used again. @@ -1884,47 +1946,48 @@ gen_moves([A|As], I, Acc) -> gen_moves([], _, Acc) -> keysort(3, Acc). -%% order_moves([Move], ScratchReg) -> [Move] +%% order_moves([Move]) -> [Move] %% Orders move instruction so that source registers are not %% destroyed before they are used. If there are cycles %% (such as {move,{x,0},{x,1}}, {move,{x,1},{x,1}}), -%% the scratch register is used to break up the cycle. -%% If possible, the first move of the input list is placed +%% swap instructions will be used to break up the cycle. +%% +%% If possible, the first move of the input list is placed %% last in the result list (to make the move to {x,0} occur %% just before the call to allow the Beam loader to coalesce %% the instructions). -order_moves(Ms, Scr) -> order_moves(Ms, Scr, []). +order_moves(Ms) -> order_moves(Ms, []). -order_moves([{move,_,_}=M|Ms0], ScrReg, Acc0) -> - {Chain,Ms} = collect_chain(Ms0, [M], ScrReg), +order_moves([{move,_,_}=M|Ms0], Acc0) -> + {Chain,Ms} = collect_chain(Ms0, [M]), Acc = reverse(Chain, Acc0), - order_moves(Ms, ScrReg, Acc); -order_moves([], _, Acc) -> Acc. + order_moves(Ms, Acc); +order_moves([], Acc) -> Acc. -collect_chain(Ms, Path, ScrReg) -> - collect_chain(Ms, Path, [], ScrReg). +collect_chain(Ms, Path) -> + collect_chain(Ms, Path, []). -collect_chain([{move,Src,Same}=M|Ms0], [{move,Same,_}|_]=Path, Others, ScrReg) -> +collect_chain([{move,Src,Same}=M|Ms0], [{move,Same,_}|_]=Path, Others) -> case keymember(Src, 3, Path) of false -> - collect_chain(reverse(Others, Ms0), [M|Path], [], ScrReg); + collect_chain(reverse(Others, Ms0), [M|Path], []); true -> - %% There is a cycle, which we must break up. - {break_up_cycle(M, Path, ScrReg),reverse(Others, Ms0)} + %% There is a cycle. + {break_up_cycle(M, Path),reverse(Others, Ms0)} end; -collect_chain([M|Ms], Path, Others, ScrReg) -> - collect_chain(Ms, Path, [M|Others], ScrReg); -collect_chain([], Path, Others, _) -> +collect_chain([M|Ms], Path, Others) -> + collect_chain(Ms, Path, [M|Others]); +collect_chain([], Path, Others) -> {Path,Others}. -break_up_cycle({move,Src,_}=M, Path, ScrReg) -> - [{move,ScrReg,Src},M|break_up_cycle1(Src, Path, ScrReg)]. +break_up_cycle({move,Src,_Dst}=M, Path) -> + break_up_cycle_1(Src, [M|Path], []). -break_up_cycle1(Dst, [{move,Src,Dst}|Path], ScrReg) -> - [{move,Src,ScrReg}|Path]; -break_up_cycle1(Dst, [M|Path], LastMove) -> - [M|break_up_cycle1(Dst, Path, LastMove)]. +break_up_cycle_1(Dst, [{move,_Src,Dst}|Path], Acc) -> + reverse(Acc, Path); +break_up_cycle_1(Dst, [{move,S,D}|Path], Acc) -> + break_up_cycle_1(Dst, Path, [{swap,S,D}|Acc]). %%% %%% General utility functions. diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl index bb43a550ae..423bc88c3b 100644 --- a/lib/compiler/src/beam_ssa_dead.erl +++ b/lib/compiler/src/beam_ssa_dead.erl @@ -719,8 +719,8 @@ will_succeed_1('=/=', A, '=:=', B) when A =:= B -> no; will_succeed_1('<', A, '=:=', B) when B >= A -> no; will_succeed_1('<', A, '=/=', B) when B >= A -> yes; will_succeed_1('<', A, '<', B) when B >= A -> yes; -will_succeed_1('<', A, '=<', B) when B > A -> yes; -will_succeed_1('<', A, '>=', B) when B > A -> no; +will_succeed_1('<', A, '=<', B) when B >= A -> yes; +will_succeed_1('<', A, '>=', B) when B >= A -> no; will_succeed_1('<', A, '>', B) when B >= A -> no; will_succeed_1('=<', A, '=:=', B) when B > A -> no; @@ -740,9 +740,9 @@ will_succeed_1('>=', A, '>', B) when B < A -> yes; will_succeed_1('>', A, '=:=', B) when B =< A -> no; will_succeed_1('>', A, '=/=', B) when B =< A -> yes; will_succeed_1('>', A, '<', B) when B =< A -> no; -will_succeed_1('>', A, '=<', B) when B < A -> no; +will_succeed_1('>', A, '=<', B) when B =< A -> no; will_succeed_1('>', A, '>=', B) when B =< A -> yes; -will_succeed_1('>', A, '>', B) when B < A -> yes; +will_succeed_1('>', A, '>', B) when B =< A -> yes; will_succeed_1('==', A, '==', B) -> if diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl index bf99e8fc26..a5fcb91cc0 100644 --- a/lib/compiler/src/beam_ssa_pre_codegen.erl +++ b/lib/compiler/src/beam_ssa_pre_codegen.erl @@ -108,7 +108,8 @@ functions([], _Ps, _UseBSM3) -> []. intervals=[] :: [{b_var(),[range()]}], res=[] :: [{b_var(),reservation()}] | #{b_var():=reservation()}, regs=#{} :: #{b_var():=ssa_register()}, - extra_annos=[] :: [{atom(),term()}] + extra_annos=[] :: [{atom(),term()}], + location :: term() }). -define(PASS(N), {N,fun N/1}). @@ -120,6 +121,7 @@ passes(Opts) -> %% Preliminaries. ?PASS(fix_bs), ?PASS(sanitize), + ?PASS(match_fail_instructions), case FixTuples of false -> ignore; true -> ?PASS(fix_tuples) @@ -162,7 +164,9 @@ passes(Opts) -> function(#b_function{anno=Anno,args=Args,bs=Blocks0,cnt=Count0}=F0, Ps, UseBSM3) -> try - St0 = #st{ssa=Blocks0,args=Args,use_bsm3=UseBSM3,cnt=Count0}, + Location = maps:get(location, Anno, none), + St0 = #st{ssa=Blocks0,args=Args,use_bsm3=UseBSM3, + cnt=Count0,location=Location}, St = compile:run_sub_passes(Ps, St0), #st{ssa=Blocks,cnt=Count,regs=Regs,extra_annos=ExtraAnnos} = St, F1 = add_extra_annos(F0, ExtraAnnos), @@ -854,6 +858,114 @@ prune_phi(#b_set{args=Args0}=Phi, Reachable) -> gb_sets:is_element(Pred, Reachable)], Phi#b_set{args=Args}. +%%% Rewrite certain calls to erlang:error/{1,2} to specialized +%%% instructions: +%%% +%%% erlang:error({badmatch,Value}) => badmatch Value +%%% erlang:error({case_clause,Value}) => case_end Value +%%% erlang:error({try_clause,Value}) => try_case_end Value +%%% erlang:error(if_clause) => if_end +%%% erlang:error(function_clause, Args) => jump FuncInfoLabel +%%% +%%% In SSA code, we represent those instructions as a 'match_fail' +%%% instruction with the name of the BEAM instruction as the first +%%% argument. + +match_fail_instructions(#st{ssa=Blocks0,args=Args,location=Location}=St) -> + Ls = maps:to_list(Blocks0), + Info = {length(Args),Location}, + Blocks = match_fail_instrs_1(Ls, Info, Blocks0), + St#st{ssa=Blocks}. + +match_fail_instrs_1([{L,#b_blk{is=Is0}=Blk}|Bs], Arity, Blocks0) -> + case match_fail_instrs_blk(Is0, Arity, []) of + none -> + match_fail_instrs_1(Bs, Arity, Blocks0); + Is -> + Blocks = Blocks0#{L:=Blk#b_blk{is=Is}}, + match_fail_instrs_1(Bs, Arity, Blocks) + end; +match_fail_instrs_1([], _Arity, Blocks) -> Blocks. + +match_fail_instrs_blk([#b_set{op=put_tuple,dst=Dst, + args=[#b_literal{val=Tag},Val]}, + #b_set{op=call, + args=[#b_remote{mod=#b_literal{val=erlang}, + name=#b_literal{val=error}}, + Dst]}=Call|Is], + _Arity, Acc) -> + match_fail_instr(Call, Tag, Val, Is, Acc); +match_fail_instrs_blk([#b_set{op=call, + args=[#b_remote{mod=#b_literal{val=erlang}, + name=#b_literal{val=error}}, + #b_literal{val={Tag,Val}}]}=Call|Is], + _Arity, Acc) -> + match_fail_instr(Call, Tag, #b_literal{val=Val}, Is, Acc); +match_fail_instrs_blk([#b_set{op=call, + args=[#b_remote{mod=#b_literal{val=erlang}, + name=#b_literal{val=error}}, + #b_literal{val=if_clause}]}=Call|Is], + _Arity, Acc) -> + I = Call#b_set{op=match_fail,args=[#b_literal{val=if_end}]}, + reverse(Acc, [I|Is]); +match_fail_instrs_blk([#b_set{op=call,anno=Anno, + args=[#b_remote{mod=#b_literal{val=erlang}, + name=#b_literal{val=error}}, + #b_literal{val=function_clause}, + Stk]}=Call], + {Arity,Location}, Acc) -> + case match_fail_stk(Stk, Acc, [], []) of + {[_|_]=Vars,Is} when length(Vars) =:= Arity -> + case maps:get(location, Anno, none) of + Location -> + I = Call#b_set{op=match_fail, + args=[#b_literal{val=function_clause}|Vars]}, + Is ++ [I]; + _ -> + %% erlang:error/2 has a different location than the + %% func_info instruction at the beginning of the function + %% (probably because of inlining). Keep the original call. + reverse(Acc, [Call]) + end; + _ -> + %% Either the stacktrace could not be picked apart (for example, + %% if the call to erlang:error/2 was handwritten) or the number + %% of arguments in the stacktrace was different from the arity + %% of the host function (because it is the implementation of a + %% fun). Keep the original call. + reverse(Acc, [Call]) + end; +match_fail_instrs_blk([I|Is], Arity, Acc) -> + match_fail_instrs_blk(Is, Arity, [I|Acc]); +match_fail_instrs_blk(_, _, _) -> + none. + +match_fail_instr(Call, Tag, Val, Is, Acc) -> + Op = case Tag of + badmatch -> Tag; + case_clause -> case_end; + try_clause -> try_case_end; + _ -> none + end, + case Op of + none -> + none; + _ -> + I = Call#b_set{op=match_fail,args=[#b_literal{val=Op},Val]}, + reverse(Acc, [I|Is]) + end. + +match_fail_stk(#b_var{}=V, [#b_set{op=put_list,dst=V,args=[H,T]}|Is], IAcc, VAcc) -> + match_fail_stk(T, Is, IAcc, [H|VAcc]); +match_fail_stk(#b_literal{val=[H|T]}, Is, IAcc, VAcc) -> + match_fail_stk(#b_literal{val=T}, Is, IAcc, [#b_literal{val=H}|VAcc]); +match_fail_stk(#b_literal{val=[]}, [], IAcc, VAcc) -> + {reverse(VAcc),IAcc}; +match_fail_stk(T, [#b_set{op=Op}=I|Is], IAcc, VAcc) + when Op =:= bs_get_tail; Op =:= bs_set_position -> + match_fail_stk(T, Is, [I|IAcc], VAcc); +match_fail_stk(_, _, _, _) -> none. + %%% %%% Fix tuples. %%% @@ -1415,12 +1527,15 @@ fix_receive([], _Defs, Blocks, Count) -> find_loop_exit([L1,L2|_Ls], Blocks) -> Path1 = beam_ssa:rpo([L1], Blocks), Path2 = beam_ssa:rpo([L2], Blocks), - find_loop_exit_1(reverse(Path1), reverse(Path2), none); + find_loop_exit_1(Path1, cerl_sets:from_list(Path2)); find_loop_exit(_, _) -> none. -find_loop_exit_1([H|T1], [H|T2], _) -> - find_loop_exit_1(T1, T2, H); -find_loop_exit_1(_, _, Exit) -> Exit. +find_loop_exit_1([H|T], OtherPath) -> + case cerl_sets:is_element(H, OtherPath) of + true -> H; + false -> find_loop_exit_1(T, OtherPath) + end; +find_loop_exit_1([], _) -> none. %% find_rm_blocks(StartLabel, Blocks) -> [Label]. %% Find all blocks that start with remove_message within the receive diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 06b42f1928..2ea7e89dfa 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -24,7 +24,7 @@ -include("beam_ssa_opt.hrl"). -import(lists, [all/2,any/2,droplast/1,foldl/3,last/1,member/2, keyfind/3,partition/2,reverse/1,reverse/2, - seq/2,sort/1,split/2]). + sort/1,split/2]). -define(UNICODE_INT, #t_integer{elements={0,16#10FFFF}}). @@ -874,11 +874,11 @@ type(call, [#b_remote{mod=#b_literal{val=Mod}, true -> none end; - {#t_integer{elements={Min,Max}}, + {#t_integer{elements={Min,_}}=IntType, #t_tuple{elements=Es0,size=Size}=T} -> - %% We know this will land between Min and Max, so kill the - %% types for those indexes. - Es = maps:without(seq(Min, Max), Es0), + %% Remove type information for all indices that + %% falls into the range of the integer. + Es = remove_element_info(IntType, Es0), case T#t_tuple.exact of false -> T#t_tuple{elements=Es,size=max(Min, Size)}; @@ -1649,6 +1649,12 @@ get_literal_from_type(nil) -> #b_literal{val=[]}; get_literal_from_type(_) -> none. +remove_element_info(#t_integer{elements={Min,Max}}, Es) -> + foldl(fun(El, Acc) when Min =< El, El =< Max -> + maps:remove(El, Acc); + (_El, Acc) -> Acc + end, Es, maps:keys(Es)). + t_atom() -> #t_atom{elements=any}. diff --git a/lib/compiler/src/beam_trim.erl b/lib/compiler/src/beam_trim.erl index acf3838da4..ad8839cc7d 100644 --- a/lib/compiler/src/beam_trim.erl +++ b/lib/compiler/src/beam_trim.erl @@ -244,6 +244,9 @@ remap([{make_fun2,_,_,_,_}=I|T], Map, Acc) -> remap([{deallocate,N}|Is], Map, Acc) -> I = {deallocate,Map({frame_size,N})}, remap(Is, Map, [I|Acc]); +remap([{swap,Reg1,Reg2}|Is], Map, Acc) -> + I = {swap,Map(Reg1),Map(Reg2)}, + remap(Is, Map, [I|Acc]); remap([{test,Name,Fail,Ss}|Is], Map, Acc) -> I = {test,Name,Fail,[Map(S) || S <- Ss]}, remap(Is, Map, [I|Acc]); @@ -382,6 +385,8 @@ frame_size([{bs_set_position,_,_}|Is], Safe) -> frame_size(Is, Safe); frame_size([{bs_get_tail,_,_,_}|Is], Safe) -> frame_size(Is, Safe); +frame_size([{swap,_,_}|Is], Safe) -> + frame_size(Is, Safe); frame_size(_, _) -> throw(not_possible). frame_size_branch(0, Is, Safe) -> @@ -444,6 +449,8 @@ is_not_used(Y, [{line,_}|Is]) -> is_not_used(Y, Is); is_not_used(Y, [{make_fun2,_,_,_,_}|Is]) -> is_not_used(Y, Is); +is_not_used(Y, [{swap,Reg1,Reg2}|Is]) -> + Y =/= Reg1 andalso Y =/= Reg2 andalso is_not_used(Y, Is); is_not_used(Y, [{test,_,_,Ss}|Is]) -> not member(Y, Ss) andalso is_not_used(Y, Is); is_not_used(Y, [{test,_Op,{f,_},_Live,Ss,Dst}|Is]) -> diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 09a5a6c104..b4acebbfae 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -392,6 +392,23 @@ valfun_1(build_stacktrace=I, Vst) -> call(I, 1, Vst); valfun_1({move,Src,Dst}, Vst) -> assign(Src, Dst, Vst); +valfun_1({swap,RegA,RegB}, Vst0) -> + assert_movable(RegA, Vst0), + assert_movable(RegB, Vst0), + + %% We don't expect fragile registers to be swapped. + %% Therefore, we can conservatively make both registers + %% fragile if one of the register is fragile instead of + %% swapping the fragility of the registers. + Sources = [RegA,RegB], + Vst1 = propagate_fragility(RegA, Sources, Vst0), + Vst2 = propagate_fragility(RegB, Sources, Vst1), + + %% Swap the value references. + VrefA = get_reg_vref(RegA, Vst2), + VrefB = get_reg_vref(RegB, Vst2), + Vst = set_reg_vref(VrefB, RegA, Vst2), + set_reg_vref(VrefA, RegB, Vst); valfun_1({fmove,Src,{fr,_}=Dst}, Vst) -> assert_type(float, Src, Vst), set_freg(Dst, Vst); diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 28db8986ff..e5e63341b7 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -265,7 +265,9 @@ expand_opt(r19, Os) -> expand_opt(r20, Os) -> expand_opt_before_21(Os); expand_opt(r21, Os) -> - [no_put_tuple2 | expand_opt(no_bsm3, Os)]; + [no_swap, no_put_tuple2 | expand_opt(no_bsm3, Os)]; +expand_opt(r22, Os) -> + [no_swap | Os]; expand_opt({debug_info_key,_}=O, Os) -> [encrypt_debug_info,O|Os]; expand_opt(no_type_opt, Os) -> @@ -275,7 +277,7 @@ expand_opt(no_type_opt, Os) -> expand_opt(O, Os) -> [O|Os]. expand_opt_before_21(Os) -> - [no_put_tuple2, no_get_hd_tl, no_ssa_opt_record, + [no_swap, no_put_tuple2, no_get_hd_tl, no_ssa_opt_record, no_utf8_atoms | expand_opt(no_bsm3, Os)]. %% format_error(ErrorDescriptor) -> string() @@ -860,8 +862,6 @@ asm_passes() -> {unless,no_postopt, [{pass,beam_block}, {iff,dblk,{listing,"block"}}, - {unless,no_except,{pass,beam_except}}, - {iff,dexcept,{listing,"except"}}, {unless,no_jopt,{pass,beam_jump}}, {iff,djmp,{listing,"jump"}}, {unless,no_peep_opt,{pass,beam_peep}}, @@ -2095,7 +2095,6 @@ pre_load() -> beam_block, beam_clean, beam_dict, - beam_except, beam_flatten, beam_jump, beam_kernel_to_ssa, diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src index a086a3a8d3..9dc3b6e339 100644 --- a/lib/compiler/src/compiler.app.src +++ b/lib/compiler/src/compiler.app.src @@ -27,7 +27,6 @@ beam_clean, beam_dict, beam_disasm, - beam_except, beam_flatten, beam_jump, beam_kernel_to_ssa, diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab index 86590fad87..03507bafb3 100755 --- a/lib/compiler/src/genop.tab +++ b/lib/compiler/src/genop.tab @@ -596,3 +596,7 @@ BEAM_FORMAT_NUMBER=0 ## @spec bs_set_positon Ctx Pos ## @doc Sets the current position of Ctx to Pos 168: bs_set_position/2 + +## @spec swap Register1 Register2 +## @doc Swaps the contents of two registers. +169: swap/2 diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 3699c9d22e..007a0247f4 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -1811,7 +1811,8 @@ force_safe(Ce, St0) -> is_safe(#c_cons{}) -> true; is_safe(#c_tuple{}) -> true; -is_safe(#c_var{}) -> true; +is_safe(#c_var{name={_,_}}) -> false; %Fun. Not safe. +is_safe(#c_var{name=_}) -> true; %Ordinary variable. is_safe(#c_literal{}) -> true; is_safe(_) -> false. diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl index 15cf9bcbf3..c1086276d0 100644 --- a/lib/compiler/test/beam_ssa_SUITE.erl +++ b/lib/compiler/test/beam_ssa_SUITE.erl @@ -344,48 +344,8 @@ cover_ssa_dead(_Config) -> 40.0 = percentage(4.0, 10.0), 60.0 = percentage(6, 10), - %% Cover '=:=', followed by '=/='. - false = 'cover__=:=__=/='(41), - true = 'cover__=:=__=/='(42), - false = 'cover__=:=__=/='(43), - - %% Cover '<', followed by '=/='. - true = 'cover__<__=/='(41), - false = 'cover__<__=/='(42), - false = 'cover__<__=/='(43), - - %% Cover '=<', followed by '=/='. - true = 'cover__=<__=/='(41), - true = 'cover__=<__=/='(42), - false = 'cover__=<__=/='(43), - - %% Cover '>=', followed by '=/='. - false = 'cover__>=__=/='(41), - true = 'cover__>=__=/='(42), - true = 'cover__>=__=/='(43), - - %% Cover '>', followed by '=/='. - false = 'cover__>__=/='(41), - false = 'cover__>__=/='(42), - true = 'cover__>__=/='(43), - ok. -'cover__=:=__=/='(X) when X =:= 42 -> X =/= 43; -'cover__=:=__=/='(_) -> false. - -'cover__<__=/='(X) when X < 42 -> X =/= 42; -'cover__<__=/='(_) -> false. - -'cover__=<__=/='(X) when X =< 42 -> X =/= 43; -'cover__=<__=/='(_) -> false. - -'cover__>=__=/='(X) when X >= 42 -> X =/= 41; -'cover__>=__=/='(_) -> false. - -'cover__>__=/='(X) when X > 42 -> X =/= 42; -'cover__>__=/='(_) -> false. - format_str(Str, FormatData, IoList, EscChars) -> Escapable = FormatData =:= escapable, case id(Str) of diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 882e281a44..0d1680fb15 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -271,8 +271,22 @@ setelement(_Config) -> T0 = id({a,42}), {a,_} = T0, {b,_} = setelement(1, T0, b), + {z,b} = do_setelement_1(<<(id(1)):32>>, {a,b}, z), + {new,two} = do_setelement_2(<<(id(1)):1>>, {one,two}, new), ok. +do_setelement_1(<<N:32>>, Tuple, NewValue) -> + _ = element(N, Tuple), + %% While updating the type for Tuple, beam_ssa_type would do: + %% maps:without(lists:seq(0, 4294967295), Elements) + setelement(N, Tuple, NewValue). + +do_setelement_2(<<N:1>>, Tuple, NewValue) -> + %% Cover the second clause in remove_element_info/2. The + %% type for the second element will be kept. + two = element(2, Tuple), + setelement(N, Tuple, NewValue). + cons(_Config) -> [did] = cons(assigned, did), diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 53627b9d81..7e9e641478 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -378,7 +378,6 @@ do_file_listings(DataDir, PrivDir, [File|Files]) -> {dprecg, ".precodegen"}, {dcg, ".codegen"}, {dblk, ".block"}, - {dexcept, ".except"}, {djmp, ".jump"}, {dclean, ".clean"}, {dpeep, ".peep"}, @@ -1411,8 +1410,13 @@ bc_options(Config) -> {158, small_maps, [r20]}, {158, small_maps, [r21]}, + {164, small_maps, [r22]}, + {164, big, [r22]}, {164, small_maps, []}, - {164, big, []} + {164, big, []}, + + {168, small, [r22]}, + {168, small, []} ], Test = fun({Expected,Mod,Options}) -> diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl index 1df0a05275..7fc6195e31 100644 --- a/lib/compiler/test/fun_SUITE.erl +++ b/lib/compiler/test/fun_SUITE.erl @@ -22,7 +22,8 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1, - external/1,eep37/1,eep37_dup/1,badarity/1,badfun/1]). + external/1,eep37/1,eep37_dup/1,badarity/1,badfun/1, + duplicated_fun/1]). %% Internal exports. -export([call_me/1,dup1/0,dup2/0]). @@ -37,7 +38,7 @@ all() -> groups() -> [{p,[parallel], [test1,overwritten_fun,otp_7202,bif_fun,external,eep37, - eep37_dup,badarity,badfun]}]. + eep37_dup,badarity,badfun,duplicated_fun]}]. init_per_suite(Config) -> test_lib:recompile(?MODULE), @@ -261,5 +262,20 @@ badfun(_Config) -> expect_badfun(Term, Exit) -> {'EXIT',{{badfun,Term},_}} = Exit. +duplicated_fun(_Config) -> + try + %% The following code used to crash the compiler before + %% v3_core:is_safe/1 was corrected to consider fun variables + %% unsafe. + id([print_result_paths_fun = fun duplicated_fun_helper/1]), + ct:error(should_fail) + catch + error:{badmatch,F} when is_function(F, 1) -> + ok + end. + +duplicated_fun_helper(_) -> + ok. + id(I) -> I. diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl index ed0a56f064..f25d8a1a46 100644 --- a/lib/compiler/test/guard_SUITE.erl +++ b/lib/compiler/test/guard_SUITE.erl @@ -19,7 +19,7 @@ %% -module(guard_SUITE). --include_lib("common_test/include/ct.hrl"). +-include_lib("syntax_tools/include/merl.hrl"). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, @@ -31,7 +31,8 @@ old_guard_tests/1,complex_guard/1, build_in_guard/1,gbif/1, t_is_boolean/1,is_function_2/1, - tricky/1,rel_ops/1,rel_op_combinations/1,literal_type_tests/1, + tricky/1,rel_ops/1,rel_op_combinations/1, + generated_combinations/1,literal_type_tests/1, basic_andalso_orelse/1,traverse_dcd/1, check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1, bad_constants/1,bad_guards/1, @@ -50,7 +51,7 @@ groups() -> more_xor_guards,build_in_guard, old_guard_tests,complex_guard,gbif, t_is_boolean,is_function_2,tricky, - rel_ops,rel_op_combinations, + rel_ops,rel_op_combinations,generated_combinations, literal_type_tests,basic_andalso_orelse,traverse_dcd, check_qlc_hrl,andalso_semi,t_tuple_size,binary_part, bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE]}]. @@ -1577,6 +1578,122 @@ redundant_12(X) when X >= 50, X =< 80 -> 2*X; redundant_12(X) when X < 51 -> 5*X; redundant_12(_) -> none. +generated_combinations(Config) -> + case ?MODULE of + guard_SUITE -> generated_combinations_1(Config); + _ -> {skip,"Enough to run this case once."} + end. + +%% Exhaustively test all combinations of relational operators +%% to ensure the correctness of the optimizations in beam_ssa_dead. + +generated_combinations_1(Config) -> + Mod = ?FUNCTION_NAME, + RelOps = ['=:=','=/=','==','/=','<','=<','>=','>'], + Combinations0 = [{Op1,Op2} || Op1 <- RelOps, Op2 <- RelOps], + Combinations1 = gen_lit_combs(Combinations0), + Combinations2 = [{neq,Comb} || + {_Op1,_Lit1,Op2,_Lit2}=Comb <- Combinations1, + Op2 =:= '=/=' orelse Op2 =:= '/='] ++ Combinations1, + Combinations = gen_func_names(Combinations2, 0), + Fs = gen_rel_op_functions(Combinations), + Tree = ?Q(["-module('@Mod@').", + "-compile([export_all,nowarn_export_all])."]) ++ Fs, + %%merl:print(Tree), + Opts = test_lib:opt_opts(?MODULE), + {ok,_Bin} = merl:compile_and_load(Tree, Opts), + test_combinations(Combinations, Mod). + +gen_lit_combs([{Op1,Op2}|T]) -> + [{Op1,7,Op2,6}, + {Op1,7.0,Op2,6}, + {Op1,7,Op2,6.0}, + {Op1,7.0,Op2,6.0}, + + {Op1,7,Op2,7}, + {Op1,7.0,Op2,7}, + {Op1,7,Op2,7.0}, + {Op1,7.0,Op2,7.0}, + + {Op1,6,Op2,7}, + {Op1,6.0,Op2,7}, + {Op1,6,Op2,7.0}, + {Op1,6.0,Op2,7.0}|gen_lit_combs(T)]; +gen_lit_combs([]) -> []. + +gen_func_names([E|Es], I) -> + Name = list_to_atom("f" ++ integer_to_list(I)), + [{Name,E}|gen_func_names(Es, I+1)]; +gen_func_names([], _) -> []. + +gen_rel_op_functions([{Name,{neq,{Op1,Lit1,Op2,Lit2}}}|T]) -> + %% Note that in the translation to SSA, '=/=' will be + %% translated to '=:=' in a guard (with switched success + %% and failure labels). Therefore, to test the optimization, + %% we must use '=/=' (or '/=') in a body context. + %% + %% Here is an example of a generated function: + %% + %% f160(A) when erlang:'>='(A, 7) -> + %% one; + %% f160(A) -> + %% true = erlang:'/='(A, 7), + %% two. + [?Q("'@Name@'(A) when erlang:'@Op1@'(A, _@Lit1@) -> one; + '@Name@'(A) -> true = erlang:'@Op2@'(A, _@Lit2@), two. ")| + gen_rel_op_functions(T)]; +gen_rel_op_functions([{Name,{Op1,Lit1,Op2,Lit2}}|T]) -> + %% Example of a generated function: + %% + %% f721(A) when erlang:'=<'(A, 7.0) -> one; + %% f721(A) when erlang:'<'(A, 6) -> two; + %% f721(_) -> three. + [?Q("'@Name@'(A) when erlang:'@Op1@'(A, _@Lit1@) -> one; + '@Name@'(A) when erlang:'@Op2@'(A, _@Lit2@) -> two; + '@Name@'(_) -> three.")|gen_rel_op_functions(T)]; +gen_rel_op_functions([]) -> []. + +test_combinations([{Name,E}|T], Mod) -> + try + test_combinations_1([5,6,7,8,9], E, fun Mod:Name/1), + test_combination(6.5, E, fun Mod:Name/1) + catch + error:Reason:Stk -> + io:format("~p: ~p\n", [Name,E]), + erlang:raise(error, Reason, Stk) + end, + test_combinations(T, Mod); +test_combinations([], _Mod) -> ok. + +test_combinations_1([V|Vs], E, Fun) -> + test_combination(V, E, Fun), + test_combination(float(V), E, Fun), + test_combinations_1(Vs, E, Fun); +test_combinations_1([], _, _) -> ok. + +test_combination(Val, {neq,Expr}, Fun) -> + Result = eval_combination_expr(Expr, Val), + Result = try + Fun(Val) %Returns 'one' or 'two'. + catch + error:{badmatch,_} -> + three + end; +test_combination(Val, Expr, Fun) -> + Result = eval_combination_expr(Expr, Val), + Result = Fun(Val). + +eval_combination_expr({Op1,Lit1,Op2,Lit2}, Val) -> + case erlang:Op1(Val, Lit1) of + true -> + one; + false -> + case erlang:Op2(Val, Lit2) of + true -> two; + false -> three + end + end. + %% Test type tests on literal values. (From emulator test suites.) literal_type_tests(Config) when is_list(Config) -> case ?MODULE of diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index a0b415ceaa..eb60dc049d 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -227,15 +227,6 @@ silly_coverage(Config) when is_list(Config) -> {label,2}|non_proper_list]}],99}, expect_error(fun() -> beam_block:module(BlockInput, []) end), - %% beam_except - ExceptInput = {?MODULE,[{foo,0}],[], - [{function,foo,0,2, - [{label,1}, - {line,loc}, - {func_info,{atom,?MODULE},{atom,foo},0}, - {label,2}|non_proper_list]}],99}, - expect_error(fun() -> beam_except:module(ExceptInput, []) end), - %% beam_jump JumpInput = BlockInput, expect_error(fun() -> beam_jump:module(JumpInput, []) end), diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl index 0038eb1a4b..752491f0f8 100644 --- a/lib/compiler/test/receive_SUITE.erl +++ b/lib/compiler/test/receive_SUITE.erl @@ -26,7 +26,7 @@ init_per_testcase/2,end_per_testcase/2, export/1,recv/1,coverage/1,otp_7980/1,ref_opt/1, wait/1,recv_in_try/1,double_recv/1,receive_var_zero/1, - match_built_terms/1]). + match_built_terms/1,elusive_common_exit/1]). -include_lib("common_test/include/ct.hrl"). @@ -47,7 +47,7 @@ groups() -> [{p,test_lib:parallel(), [recv,coverage,otp_7980,ref_opt,export,wait, recv_in_try,double_recv,receive_var_zero, - match_built_terms]}]. + match_built_terms,elusive_common_exit]}]. init_per_suite(Config) -> @@ -427,4 +427,26 @@ match_built_terms(Config) when is_list(Config) -> ?MATCH_BUILT_TERM(Ref, <<A, B>>), ?MATCH_BUILT_TERM(Ref, #{ 1 => A, 2 => B}). +elusive_common_exit(_Config) -> + self() ! {1, a}, + self() ! {2, b}, + {[z], [{2,b},{1,a}]} = elusive_loop([x,y,z], 2, []), + ok. + +elusive_loop(List, 0, Results) -> + {List, Results}; +elusive_loop(List, ToReceive, Results) -> + {Result, RemList} = + receive + {_Pos, _R} = Res when List =/= [] -> + [_H|T] = List, + {Res, T}; + {_Pos, _R} = Res when List =:= [] -> + {Res, []} + end, + %% beam_ssa_pre_codegen:fix_receives() would fail to find + %% the common exit block for this receive. That would mean + %% that it would not insert all necessary copy instructions. + elusive_loop(RemList, ToReceive-1, [Result | Results]). + id(I) -> I. diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl index 3348c6e9ea..98210a351c 100644 --- a/lib/compiler/test/test_lib.erl +++ b/lib/compiler/test/test_lib.erl @@ -82,6 +82,7 @@ opt_opts(Mod) -> (no_ssa_float) -> true; (no_ssa_opt) -> true; (no_stack_trimming) -> true; + (no_swap) -> true; (no_type_opt) -> true; (_) -> false end, Opts). diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index a523627384..494de072ff 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 7.3.2 +COMPILER_VSN = 7.4 diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c index 00072af632..0532fb7566 100644 --- a/lib/crypto/c_src/cipher.c +++ b/lib/crypto/c_src/cipher.c @@ -334,6 +334,7 @@ ERL_NIF_TERM cipher_types_as_list(ErlNifEnv* env) continue; if ((p->cipher.p != NULL) || + (p->flags & AES_CTR_COMPAT) || (p->type.atom == atom_aes_ige256)) /* Special handling. Bad indeed... */ { hd = enif_make_list_cell(env, p->type.atom, hd); diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index 195c9d029d..b69657bfa8 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -31,6 +31,137 @@ </header> <p>This document describes the changes made to the Crypto application.</p> +<section><title>Crypto 4.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a bug in error return for <c>crypto:poly1305/2</c>. + It returned the atom <c>notsup</c> instead of the + exception <c>notsup</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15677</p> + </item> + <item> + <p> + The cipher chacha20 was introduced in OpenSSL 1.1.0. + However, it could in a very odd situation, fail for + versions less than OpenSSL 1.1.0d. It is therefore + disabled for those versions.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15678</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> A new <c>rand</c> module algorithm, <c>exro928ss</c> + (Xoroshiro928**), has been implemented. It has got a + really long period and good statistical quality for all + output bits, while still being only about 50% slower than + the default algorithm. </p><p> The same generator is also + used as a long period counter in a new <c>crypto</c> + plugin for the <c>rand</c> module, algorithm + <c>crypto_aes</c>. This plugin uses AES-256 to scramble + the counter which buries any detectable statistical + artifacts. Scrambling is done in chunks which are cached + to get good amortized speed (about half of the default + algorithm). </p> + <p> + Own Id: OTP-14461 Aux Id: PR-1857 </p> + </item> + <item> + <p> + Crypto's single C-file is split into multiple files. The + different coding styles in the different parts are + unified into a single style.</p> + <p> + Own Id: OTP-14732 Aux Id: PR-2068, PR-2095 </p> + </item> + <item> + <p> + Build configuration of the <c>crypto</c> application has + been moved from the <c>erts</c> application into the + <c>crypto</c> application.</p> + <p> + Own Id: OTP-15129</p> + </item> + <item> + <p> + Adds two hash functions <c>blake2b</c> and <c>blake2s</c> + (64 bit hash and 32 bit hash respectively). These are + modern and standard hash functions used in blockchains + and encrypted communication protocols. The hash functions + are available in OpenSSL since version 1.1.1.</p> + <p> + Own Id: OTP-15564 Aux Id: PR-2129 </p> + </item> + <item> + <p> + A new API is implemented in crypto. See the CRYPTO user's + guide, chapter <i>New and Old API</i> for more + information.</p> + <p> + The old api with the <c>crypto:block_*</c> and + <c>crypto:stream_*</c> interfaces are kept for + compatibility, but implemented with the new api. Please + note that since the error checking is more thorough, + there <i>might</i> be arguments with for example faulty + lengths that are no longer accepted.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15644 Aux Id: OTP-14732 , OTP-15451, PR-1857 + , PR-2068, PR-2095 </p> + </item> + <item> + <p> + The new hash_info/1 and cipher_info/1 functions returns + maps with information about the hash or cipher in the + argument.</p> + <p> + Own Id: OTP-15655 Aux Id: PR-2173, ERL-864, PR-2186 </p> + </item> + <item> + <p> + Obey additional OpenSSL configure flags when compiling + the C-part of the CRYPTO application: <c>no-bf</c>, + <c>no-blake2</c>, <c>no-chacha</c>, <c>no-cmac</c>, + <c>no-dh</c>, <c>no-dsa</c>, <c>no-md4</c>, + <c>no-poly1305</c>, <c>no-rc2</c>, <c>no-rc4</c> and + <c>no-rmd160</c>.</p> + <p> + Own Id: OTP-15683</p> + </item> + <item> + <p> + A new function <c>crypto:supports/1</c> is introduced. + The single argument takes an atom as argument: + <c>hashes</c>, <c>public_keys</c>, <c>ciphers</c>, + <c>macs</c>, <c>curves</c> or <c>rsa_opts</c>. The return + value is a list of supported algorithms.</p> + <p> + The difference with the existing <c>crypto:supports/0</c> + is, apart from the argument and the return value, that + the old function reports what is supported by the old + api, and the new function reports algorithms in the new + api.</p> + <p> + Own Id: OTP-15771</p> + </item> + </list> + </section> + +</section> + <section><title>Crypto 4.4.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index 0a3d9f45e4..72a51bfec9 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 4.4.2 +CRYPTO_VSN = 4.5 diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml index 395b69973d..795b46d467 100644 --- a/lib/debugger/doc/src/notes.xml +++ b/lib/debugger/doc/src/notes.xml @@ -33,6 +33,23 @@ <p>This document describes the changes made to the Debugger application.</p> +<section><title>Debugger 4.2.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + <section><title>Debugger 4.2.6</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk index a3cbb497f8..daecc7594c 100644 --- a/lib/debugger/vsn.mk +++ b/lib/debugger/vsn.mk @@ -1 +1 @@ -DEBUGGER_VSN = 4.2.6 +DEBUGGER_VSN = 4.2.7 diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index bc422c43a0..dd0a2bfd7d 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -32,6 +32,52 @@ <p>This document describes the changes made to the Dialyzer application.</p> +<section><title>Dialyzer 4.0</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> By default Dialyzer inserts line breaks in types, + contracts, and Erlang Code when formatting results. Use + the new <c>--no_indentation</c> option to get the old + behavior of not inserting line breaks. </p> + <p> + Own Id: OTP-15135</p> + </item> + <item> + <p> Use bit syntax in warnings instead of Core Erlang + syntax, for readability. </p> + <p> + Own Id: OTP-15752</p> + </item> + <item> + <p> The format of the raw analysis result tagged with + <c>fun_app_args</c> is changed to <c>{fun_app_args, + [ArgNs, Args, Type]}</c>. </p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15779</p> + </item> + </list> + </section> + +</section> + <section><title>Dialyzer 3.3.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 7221993963..95984c7c85 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 3.3.2 +DIALYZER_VSN = 4.0 diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml index 145856bcaa..48bc5d9c74 100644 --- a/lib/edoc/doc/src/notes.xml +++ b/lib/edoc/doc/src/notes.xml @@ -32,6 +32,20 @@ <p>This document describes the changes made to the EDoc application.</p> +<section><title>Edoc 0.11</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Correct links in the documentation. </p> + <p> + Own Id: OTP-15761</p> + </item> + </list> + </section> + +</section> + <section><title>Edoc 0.10</title> <section><title>Improvements and New Features</title> diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk index b6e1422623..3510fdfccf 100644 --- a/lib/edoc/vsn.mk +++ b/lib/edoc/vsn.mk @@ -1 +1 @@ -EDOC_VSN = 0.10 +EDOC_VSN = 0.11 diff --git a/lib/eldap/doc/src/notes.xml b/lib/eldap/doc/src/notes.xml index 975a25d7a8..946db5b93d 100644 --- a/lib/eldap/doc/src/notes.xml +++ b/lib/eldap/doc/src/notes.xml @@ -31,6 +31,22 @@ </header> <p>This document describes the changes made to the Eldap application.</p> +<section><title>Eldap 1.2.8</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix dialyzer warnings in eldap when not matching the + return value of ssl:close/1.</p> + <p> + Own Id: OTP-15775</p> + </item> + </list> + </section> + +</section> + <section><title>Eldap 1.2.7</title> <section><title>Improvements and New Features</title> diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk index 7f03fbd1b2..8f969e6945 100644 --- a/lib/eldap/vsn.mk +++ b/lib/eldap/vsn.mk @@ -1 +1 @@ -ELDAP_VSN = 1.2.7 +ELDAP_VSN = 1.2.8 diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml index 54f0a36b27..f25361a202 100644 --- a/lib/erl_docgen/doc/src/notes.xml +++ b/lib/erl_docgen/doc/src/notes.xml @@ -31,7 +31,24 @@ </header> <p>This document describes the changes made to the <em>erl_docgen</em> application.</p> - <section><title>Erl_Docgen 0.9</title> + <section><title>Erl_Docgen 0.9.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Docgen 0.9</title> <section><title>Improvements and New Features</title> <list> diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk index 6321f229dd..fece2456c1 100644 --- a/lib/erl_docgen/vsn.mk +++ b/lib/erl_docgen/vsn.mk @@ -1 +1 @@ -ERL_DOCGEN_VSN = 0.9 +ERL_DOCGEN_VSN = 0.9.1 diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml index c22f3fb0ce..70af5642da 100644 --- a/lib/erl_interface/doc/src/ei.xml +++ b/lib/erl_interface/doc/src/ei.xml @@ -183,7 +183,7 @@ typedef enum { </func> <func> - <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, const char **pp, unsigned int *bitoffsp, size_t *nbitsp)</nametext></name> + <name since="OTP 22.0"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, const char **pp, unsigned int *bitoffsp, size_t *nbitsp)</nametext></name> <fsummary>Decode a bitstring.</fsummary> <desc> <p>Decodes a bit string from the binary format.</p> @@ -498,9 +498,9 @@ typedef enum { </func> <func> - <name since="OTP @OTP-15712@"><ret>int</ret> + <name since="OTP 22.0"><ret>int</ret> <nametext>ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t nbits)</nametext></name> - <name since="OTP @OTP-15712@"><ret>int</ret> + <name since="OTP 22.0"><ret>int</ret> <nametext>ei_x_encode_bitstring(ei_x_buff* x, const char *p, size_t bitoffs, size_t nbits)</nametext></name> <fsummary>Encode a bitstring.</fsummary> <desc> diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml index 3d7f7e5637..c47f0d2bd1 100644 --- a/lib/erl_interface/doc/src/notes.xml +++ b/lib/erl_interface/doc/src/notes.xml @@ -31,6 +31,82 @@ </header> <p>This document describes the changes made to the Erl_interface application.</p> +<section><title>Erl_Interface 3.12</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The vxworks configure has been updated to respect the + environment CFLAGS.</p> + <p> + Own Id: OTP-15773</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Minor adjustments made to build system for parallel + configure.</p> + <p> + Own Id: OTP-15340 Aux Id: OTP-14625 </p> + </item> + <item> + <p> + The limited support for VxWorks is deprecated as of OTP + 22, and will be removed in OTP 23.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15621</p> + </item> + <item> + <p>The old legacy <c>erl_interface</c> library (functions + with prefix <c>erl_</c>) is deprecated as of OTP 22, and + will be removed in OTP 23. This does not apply to the + <c>ei</c> library. Reasonably new <c>gcc</c> compilers + will issue deprecation warnings. In order to disable + these warnings, define the macro + <c>EI_NO_DEPR_WARN</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15622</p> + </item> + <item> + <p>Added support to receive, decode, encode and send both + bit strings and export funs (<c>fun M:F/A</c>).</p> + <p>New functions <c>ei_decode_bitstring</c> and + <c>ei_encode_bitstring</c> have been added in order to + decode and encode bit strings where the number of bits is + not necessary divisible by 8 (a whole number of bytes). + The existing functions <c>ei_decode_fun</c> and + <c>ei_encode_fun</c> can now also handle export funs.</p> + <p>Before this change, bit strings and export funs sent + to an erl_interface c-node were encoded using an + undocumented fallback tuple format. For bit strings + <c>{Binary,BitsInLastByte}</c> and for export funs + <c>{M,F}</c>. Existing c-node implementations expecting + these tuples must be changed to instead use + <c>ei_decode_bitstring</c> and <c>ei_decode_fun</c>. As a + temporary solution you can also build erl_interface with + macro <c>EI_COMPAT=21</c> or call + <c>ei_set_compat_rel(21)</c> to receive the old fallback + tuples.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15712 Aux Id: OTP-15774 </p> + </item> + </list> + </section> + +</section> + <section><title>Erl_Interface 3.11.3</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk index 4e31b3835d..cc72ed639a 100644 --- a/lib/erl_interface/vsn.mk +++ b/lib/erl_interface/vsn.mk @@ -1,2 +1,2 @@ -EI_VSN = 3.11.3 +EI_VSN = 3.12 ERL_INTERFACE_VSN = $(EI_VSN) diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index 9a803cb9df..a2e0766bb7 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -31,6 +31,52 @@ </header> <p>This document describes the changes made to HiPE.</p> +<section><title>Hipe 3.19</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Add function <c>hipe:erllvm_is_supported</c> to check for + the presences of a suitable version of the LLVM tool + chain as well as supported hardware architecture. The old + <c>hipe:llvm_support_available</c> has been removed.</p> + <p> + Own Id: OTP-15385 Aux Id: PR-1986 </p> + </item> + <item> + <p> + Fix hipe LLVM for FreeBSD and other non-linux unix to use + /tmp/ instead of /dev/shm/.</p> + <p> + Own Id: OTP-15386 Aux Id: PR-1963 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>In OTP 22, HiPE (the native code compiler) is not + fully functional. The reasons for this are:</p> + <p>There are new BEAM instructions for binary matching + that the HiPE native code compiler does not support.</p> + <p>The new optimizations in the Erlang compiler create + new combination of instructions that HiPE currently does + not handle correctly.</p> + <p>If erlc is invoked with the <c>+native</c> option, and + if any of the new binary matching instructions are used, + the compiler will issue a warning and produce a BEAM file + without native code.</p> + <p> + Own Id: OTP-15596</p> + </item> + </list> + </section> + +</section> + <section><title>Hipe 3.18.3</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl index 8e7e56b6c4..42e4ead169 100644 --- a/lib/hipe/icode/hipe_beam_to_icode.erl +++ b/lib/hipe/icode/hipe_beam_to_icode.erl @@ -1204,6 +1204,17 @@ trans_fun([{bs_get_position=Name,_,_,_}|_Instructions], _Env) -> trans_fun([{bs_set_position=Name,_,_}|_Instructions], _Env) -> nyi(Name); %%-------------------------------------------------------------------- +%% New instructions added in OTP 23. +%%-------------------------------------------------------------------- +%%--- swap --- +trans_fun([{swap,Reg1,Reg2}|Instructions], Env) -> + Var1 = mk_var(Reg1), + Var2 = mk_var(Reg2), + Temp = mk_var(new), + [hipe_icode:mk_move(Temp, Var1), + hipe_icode:mk_move(Var1, Var2), + hipe_icode:mk_move(Var2, Temp) | trans_fun(Instructions, Env)]; +%%-------------------------------------------------------------------- %%--- ERROR HANDLING --- %%-------------------------------------------------------------------- trans_fun([X|_], _) -> diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index 39565d721f..a91d92ca14 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.18.3 +HIPE_VSN = 3.19 diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 2710ea2f2f..03bd1d8042 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,24 @@ <file>notes.xml</file> </header> - <section><title>Inets 7.0.7</title> + <section><title>Inets 7.0.8</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + +<section><title>Inets 7.0.7</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index fd248e793a..5dbec9e7b3 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 7.0.7 +INETS_VSN = 7.0.8 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml index e4bfddcd17..e79ada47f1 100644 --- a/lib/jinterface/doc/src/notes.xml +++ b/lib/jinterface/doc/src/notes.xml @@ -31,6 +31,42 @@ </header> <p>This document describes the changes made to the Jinterface application.</p> +<section><title>Jinterface 1.10</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Added support to receive export funs (<c>fun + M:F/A</c>).</p> + <p>Before this change, export funs sent to a jinterface + node were encoded using an undocumented fallback tuple + format <c>{M,F}</c>. Existing jinterface implementations + expecting these tuples must be changed to instead use the + existing <c>OtpErlangExternalFun</c> class.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15774 Aux Id: OTP-15712 </p> + </item> + </list> + </section> + +</section> + <section><title>Jinterface 1.9.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk index a8dc815145..95c7c95726 100644 --- a/lib/jinterface/vsn.mk +++ b/lib/jinterface/vsn.mk @@ -1 +1 @@ -JINTERFACE_VSN = 1.9.1 +JINTERFACE_VSN = 1.10 diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 61bd598145..6f68a67174 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,104 @@ </header> <p>This document describes the changes made to the Kernel application.</p> +<section><title>Kernel 6.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix so that when multiple <c>-sname</c> or <c>-name</c> + are given to <c>erl</c> the first one is chosen. Before + this fix distribution was not started at all when + multiple name options were given.</p> + <p> + Own Id: OTP-15786 Aux Id: ERL-918 </p> + </item> + <item> + <p> + Fix <c>inet_res</c> configuration pointing to + non-existing files to work again. This was broken in + KERNEL-6.3 (OTP-21.3).</p> + <p> + Own Id: OTP-15806</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + A simple socket API is provided through the socket + module. This is a low level API that does *not* replace + gen_[tcp|udp|sctp]. It is intended to *eventually* + replace the inet driver, but not the high level + gen-modules (gen_tcp, gen_udp and gen_sctp). It also + provides a basic API that facilitates the implementation + of other protocols, that is TCP, UDP and SCTP. </p> + <p> + Known issues are; No support for the Windows OS + (currently).</p> + <p> + Own Id: OTP-14831</p> + </item> + <item> + <p> + Improved the documentation for the linger option.</p> + <p> + Own Id: OTP-15491 Aux Id: PR-2019 </p> + </item> + <item> + <p> Global no longer tries more than once when connecting + to other nodes. </p> + <p> + Own Id: OTP-15607 Aux Id: ERIERL-280 </p> + </item> + <item> + <p> + The dist messages EXIT, EXIT2 and MONITOR_DOWN have been + updated with new versions that send the reason term as + part of the payload of the message instead of as part of + the control message.</p> + <p> + The old versions are still present and can be used when + communicating with nodes that don't support the new + versions.</p> + <p> + Own Id: OTP-15611</p> + </item> + <item> + <p> + Kernel configuration parameter <c>start_distribution = + boolean()</c> is added. If set to <c>false</c>, the + system is started with all distribution functionality + disabled. Defaults to <c>true</c>.</p> + <p> + Own Id: OTP-15668 Aux Id: PR-2088 </p> + </item> + <item> + <p> + In OTP-21.3, a warning was introduced for duplicated + applications/keys in configuration. This warning would be + displayed both when the configuration was given as a file + on system start, and during runtime via + <c>application:set_env/1,2</c>.</p> + <p> + The warning is now changed to a <c>badarg</c> exception + in <c>application:set_env/1,2</c>. If the faulty + configuration is given in a configuration file on system + start, the startup will fail.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15692 Aux Id: PR-2170 </p> + </item> + </list> + </section> + +</section> + <section><title>Kernel 6.3.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index aca3247c8f..cd0397a98c 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -19,23 +19,15 @@ %% %% We allow upgrade from, and downgrade to all previous %% versions from the following OTP releases: -%% - OTP 20 %% - OTP 21 +%% - OTP 22 %% %% We also allow upgrade from, and downgrade to all %% versions that have branched off from the above %% stated previous versions. %% {"%VSN%", - [{<<"^5\\.3$">>,[restart_new_emulator]}, - {<<"^5\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^5\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^6\\.0$">>,[restart_new_emulator]}, + [{<<"^6\\.0$">>,[restart_new_emulator]}, {<<"^6\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^6\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^6\\.1$">>,[restart_new_emulator]}, @@ -45,16 +37,9 @@ {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^6\\.3$">>,[restart_new_emulator]}, - {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}], - [{<<"^5\\.3$">>,[restart_new_emulator]}, - {<<"^5\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^5\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^6\\.0$">>,[restart_new_emulator]}, + {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, + {<<"^6\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}], + [{<<"^6\\.0$">>,[restart_new_emulator]}, {<<"^6\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^6\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^6\\.1$">>,[restart_new_emulator]}, @@ -64,4 +49,5 @@ {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^6\\.3$">>,[restart_new_emulator]}, - {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}. + {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, + {<<"^6\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}. diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl index bfa091a036..bc4f09a023 100644 --- a/lib/kernel/src/kernel.erl +++ b/lib/kernel/src/kernel.erl @@ -116,7 +116,7 @@ init([]) -> restart => temporary, shutdown => 2000, type => supervisor, - modules => [user_sup]}, + modules => [standard_error]}, User = #{id => user, start => {user_sup, start, []}, diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index 1be016444f..00c9dc5ed5 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -594,10 +594,13 @@ unused_ip() -> io:format("we = ~p, unused_ip = ~p~n", [Hent, IP]), IP. -unused_ip(_, _, _, 255) -> error; +unused_ip(255, 255, 255, 255) -> error; +unused_ip(255, B, C, D) -> unused_ip(1, B + 1, C, D); +unused_ip(A, 255, C, D) -> unused_ip(A, 1, C + 1, D); +unused_ip(A, B, 255, D) -> unused_ip(A, B, 1, D + 1); unused_ip(A, B, C, D) -> case inet:gethostbyaddr({A, B, C, D}) of - {ok, _} -> unused_ip(A, B, C, D+1); + {ok, _} -> unused_ip(A + 1, B, C, D); {error, _} -> {ok, {A, B, C, D}} end. diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index b1ae513223..765e890157 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 6.3.1 +KERNEL_VSN = 6.4 diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml index b697c3f631..6f33ae390c 100644 --- a/lib/megaco/doc/src/notes.xml +++ b/lib/megaco/doc/src/notes.xml @@ -37,7 +37,30 @@ section is the version number of Megaco.</p> - <section><title>Megaco 3.18.4</title> + <section><title>Megaco 3.18.5</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Minor updates to build system necessary due to move of + configuration of <c>crypto</c> application.</p> + <p> + Own Id: OTP-15262 Aux Id: OTP-15129 </p> + </item> + <item> + <p> + Minor adjustments made to build system for parallel + configure.</p> + <p> + Own Id: OTP-15340 Aux Id: OTP-14625 </p> + </item> + </list> + </section> + +</section> + +<section><title>Megaco 3.18.4</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk index f4c82c537a..843a3dccc5 100644 --- a/lib/megaco/vsn.mk +++ b/lib/megaco/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = megaco -MEGACO_VSN = 3.18.4 +MEGACO_VSN = 3.18.5 PRE_VSN = APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)" diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index 01d1666b8d..2d38e4d01c 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -39,7 +39,51 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.</p> - <section><title>Mnesia 4.15.6</title> + <section><title>Mnesia 4.16</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Optimize mnesia:read/1 if data have been written in the + same transaction.</p> + <p> + Own Id: OTP-15550 Aux Id: PR-2029 </p> + </item> + <item> + <p> + Fixed bugs in table index plugin handling.</p> + <p> + Own Id: OTP-15689 Aux Id: PR-1695 ERL-556 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Optimized dumping of tables with plugin backends.</p> + <p> + Own Id: OTP-15588 Aux Id: PR-2102 </p> + </item> + <item> + <p> + Include stacktrace in exception if a dirty activity + errors, thus if user have matched on the error thrown it + may not match any more.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15804 Aux Id: PR-2216 </p> + </item> + </list> + </section> + +</section> + +<section><title>Mnesia 4.15.6</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index 781a4830a0..aa5d9adb6d 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1 +1 @@ -MNESIA_VSN = 4.15.6 +MNESIA_VSN = 4.16 diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml index 2d914f8c61..f05e58dc21 100644 --- a/lib/observer/doc/src/notes.xml +++ b/lib/observer/doc/src/notes.xml @@ -32,6 +32,23 @@ <p>This document describes the changes made to the Observer application.</p> +<section><title>Observer 2.9.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + <section><title>Observer 2.9</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk index 0e9c8b302c..c16c43f942 100644 --- a/lib/observer/vsn.mk +++ b/lib/observer/vsn.mk @@ -1 +1 @@ -OBSERVER_VSN = 2.9 +OBSERVER_VSN = 2.9.1 diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml index 696fcaa479..8d708162e4 100644 --- a/lib/odbc/doc/src/notes.xml +++ b/lib/odbc/doc/src/notes.xml @@ -32,7 +32,23 @@ <p>This document describes the changes made to the odbc application. </p> - <section><title>ODBC 2.12.3</title> + <section><title>ODBC 2.12.4</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Minor adjustments made to build system for parallel + configure.</p> + <p> + Own Id: OTP-15340 Aux Id: OTP-14625 </p> + </item> + </list> + </section> + +</section> + +<section><title>ODBC 2.12.3</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk index ff023e666b..df6db09f2f 100644 --- a/lib/odbc/vsn.mk +++ b/lib/odbc/vsn.mk @@ -1 +1 @@ -ODBC_VSN = 2.12.3 +ODBC_VSN = 2.12.4 diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml index 64e9f281e3..1f169263e9 100644 --- a/lib/os_mon/doc/src/notes.xml +++ b/lib/os_mon/doc/src/notes.xml @@ -31,6 +31,35 @@ </header> <p>This document describes the changes made to the OS_Mon application.</p> +<section><title>Os_Mon 2.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix typespec of <c>cpu_sup:util()</c>.</p> + <p> + Own Id: OTP-15770 Aux Id: PR-2208 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The application otp_mibs has been removed from OTP. Some + of its components (mibs) have been moved to other apps + (snmp), or removed completely (os_mon).</p> + <p> + Own Id: OTP-14984 Aux Id: OTP-15329 </p> + </item> + </list> + </section> + +</section> + <section><title>Os_Mon 2.4.7</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl index ba28f31f26..3a8346ac44 100644 --- a/lib/os_mon/test/cpu_sup_SUITE.erl +++ b/lib/os_mon/test/cpu_sup_SUITE.erl @@ -162,39 +162,54 @@ util_values(Config) when is_list(Config) -> Ref = make_ref(), Loop = fun (L) -> L(L) end, Spinner = fun () -> - Looper = spawn_link(fun () -> Loop(Loop) end), + NrOfProcesses = 100, + Loopers = [spawn_link(fun () -> Loop(Loop) end) + || _ <- lists:seq(1,NrOfProcesses)], receive after ?SPIN_TIME -> ok end, - unlink(Looper), - exit(Looper, kill), - Tester ! Ref - end, + [(fun () -> + unlink(Looper), + exit(Looper, kill), + Tester ! Ref + end)() + || Looper <- Loopers] + end, cpu_sup:util(), - - spawn_link(Spinner), - receive Ref -> ok end, - HighUtil1 = cpu_sup:util(), - receive after ?SPIN_TIME -> ok end, - LowUtil1 = cpu_sup:util(), + LowUtil0 = cpu_sup:util(), + NrOfProcessors = erlang:system_info(logical_processors_available), + case LowUtil0 of + U when U > ((100.0 / NrOfProcessors) * 0.5) -> + %% We cannot run this test if the system is doing other + %% work at the same time as the result will be unreliable + {skip, io_lib:format("CPU utilization was too high (~f%)", [LowUtil0])}; + _ -> + cpu_sup:util(), + spawn_link(Spinner), + receive Ref -> ok end, + HighUtil1 = cpu_sup:util(), - spawn_link(Spinner), - receive Ref -> ok end, - HighUtil2 = cpu_sup:util(), + receive after ?SPIN_TIME -> ok end, + LowUtil1 = cpu_sup:util(), - receive after ?SPIN_TIME -> ok end, - LowUtil2 = cpu_sup:util(), + spawn_link(Spinner), + receive Ref -> ok end, + HighUtil2 = cpu_sup:util(), - Utils = [{high1,HighUtil1}, {low1,LowUtil1}, - {high2,HighUtil2}, {low2,LowUtil2}], - io:format("Utils: ~p~n", [Utils]), + receive after ?SPIN_TIME -> ok end, + LowUtil2 = cpu_sup:util(), - false = LowUtil1 > HighUtil1, - false = LowUtil1 > HighUtil2, - false = LowUtil2 > HighUtil1, - false = LowUtil2 > HighUtil2, + Utils = [{high1,HighUtil1}, {low1,LowUtil1}, + {high2,HighUtil2}, {low2,LowUtil2}], + io:format("Utils: ~p~n", [Utils]), - ok. + false = LowUtil1 > HighUtil1, + false = LowUtil1 > HighUtil2, + false = LowUtil2 > HighUtil1, + false = LowUtil2 > HighUtil2, + + ok + end. % Outdated diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk index 9713f6bc6b..845443d329 100644 --- a/lib/os_mon/vsn.mk +++ b/lib/os_mon/vsn.mk @@ -1 +1 @@ -OS_MON_VSN = 2.4.7 +OS_MON_VSN = 2.5 diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml index d83dd24f41..d13c9a520a 100644 --- a/lib/public_key/doc/src/notes.xml +++ b/lib/public_key/doc/src/notes.xml @@ -35,6 +35,58 @@ <file>notes.xml</file> </header> +<section><title>Public_Key 1.6.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + RSA options passed to crypto for encrypt and decrypt with + public or private key.</p> + <p> + Own Id: OTP-15754 Aux Id: ERL-878 </p> + </item> + <item> + <p> + Fix dialyzer warnings caused by a faulty type + specification for digest_type().</p> + <p> + This change updates digest_type() and the functions + operating with this argument type to accept both 'sha1' + and 'sha' as digest_type().</p> + <p> + Own Id: OTP-15776</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add possibility to read PEM files encrypted with old PEM + encryption using AES-256</p> + <p> + Own Id: OTP-13726</p> + </item> + <item> + <p> + Relax decoding of certificates to so that "harmless" + third party encoding errors may be accepted but not + created by the public_key application. This adds + acceptance of using an incorrect three character country + code, the PKIX standard use two character country codes. + It is also accepted that the country code is utf8 encoded + but the specification says it should be ASCII.</p> + <p> + Own Id: OTP-15687 Aux Id: PR-2162 </p> + </item> + </list> + </section> + +</section> + <section><title>Public_Key 1.6.6</title> <section><title>Improvements and New Features</title> diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index c68806d856..a5e4ec8d5a 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1 +1 @@ -PUBLIC_KEY_VSN = 1.6.6 +PUBLIC_KEY_VSN = 1.6.7 diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml index 165ae6db6a..ee00b6086d 100644 --- a/lib/reltool/doc/src/notes.xml +++ b/lib/reltool/doc/src/notes.xml @@ -38,7 +38,40 @@ thus constitutes one section in this document. The title of each section is the version number of Reltool.</p> - <section><title>Reltool 0.7.8</title> + <section><title>Reltool 0.8</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + A new element, <c>Opts</c>, can now be included in a + <c>rel</c> tuple in the reltool release specific + configuration format: {rel, Name, Vsn, RelApps, Opts}.</p> + <p> + This supports the use of <c>{rel, Name, Vsn, RelApps, + [{load_dot_erlang, false}]}</c> to prevent the boot + script from running the <c>.erlang</c> file.</p> + <p> + The incompatibilities are as follows:</p> + <p> + * The return from <c>reltool:get_config/1</c> and + <c>reltool:get_config/3</c> includes the new <c>rel</c> + tuple for all releases where the <c>load_dot_erlang</c> + option is set to <c>false</c>.<br/> * The return from + <c>reltool:get_config/3</c> includes the new <c>rel</c> + tuple for ALL releases if the <c>InclDefs</c> parameter + is set to <c>true</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15571</p> + </item> + </list> + </section> + +</section> + +<section><title>Reltool 0.7.8</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk index a649a3e0c0..c5aacfba38 100644 --- a/lib/reltool/vsn.mk +++ b/lib/reltool/vsn.mk @@ -1 +1 @@ -RELTOOL_VSN = 0.7.8 +RELTOOL_VSN = 0.8 diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml index 58a2a66c4b..1b94c3e6d9 100644 --- a/lib/runtime_tools/doc/src/notes.xml +++ b/lib/runtime_tools/doc/src/notes.xml @@ -32,6 +32,22 @@ <p>This document describes the changes made to the Runtime_Tools application.</p> +<section><title>Runtime_Tools 1.13.3</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Minor updates to build system necessary due to move of + configuration of <c>crypto</c> application.</p> + <p> + Own Id: OTP-15262 Aux Id: OTP-15129 </p> + </item> + </list> + </section> + +</section> + <section><title>Runtime_Tools 1.13.2</title> <section><title>Improvements and New Features</title> diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk index fa2f338ec2..3f38574be4 100644 --- a/lib/runtime_tools/vsn.mk +++ b/lib/runtime_tools/vsn.mk @@ -1 +1 @@ -RUNTIME_TOOLS_VSN = 1.13.2 +RUNTIME_TOOLS_VSN = 1.13.3 diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml index 982c874117..a1ae404776 100644 --- a/lib/sasl/doc/src/notes.xml +++ b/lib/sasl/doc/src/notes.xml @@ -31,6 +31,23 @@ </header> <p>This document describes the changes made to the SASL application.</p> +<section><title>SASL 3.4</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Change the first module called by erts to be named + erl_init instead of otp_ring0. systools in sasl have been + updated to reflect this change.</p> + <p> + Own Id: OTP-15336 Aux Id: PR-1825 </p> + </item> + </list> + </section> + +</section> + <section><title>SASL 3.3</title> <section><title>Improvements and New Features</title> diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src index 26127eae84..22a9027b7c 100644 --- a/lib/sasl/src/sasl.appup.src +++ b/lib/sasl/src/sasl.appup.src @@ -19,27 +19,21 @@ %% %% We allow upgrade from, and downgrade to all previous %% versions from the following OTP releases: -%% - OTP 20 %% - OTP 21 +%% - OTP 22 %% %% We also allow upgrade from, and downgrade to all %% versions that have branched off from the above %% stated previous versions. %% {"%VSN%", - [{<<"^3\\.0\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.1$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.2$">>,[restart_new_emulator]}, + [{<<"^3\\.2$">>,[restart_new_emulator]}, {<<"^3\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}], - [{<<"^3\\.0\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.1$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.2$">>,[restart_new_emulator]}, + {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^3\\.3$">>,[restart_new_emulator]}, + {<<"^3\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}], + [{<<"^3\\.2$">>,[restart_new_emulator]}, {<<"^3\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}. + {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^3\\.3$">>,[restart_new_emulator]}, + {<<"^3\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}. diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk index c1f80752a7..8838b514da 100644 --- a/lib/sasl/vsn.mk +++ b/lib/sasl/vsn.mk @@ -1 +1 @@ -SASL_VSN = 3.3 +SASL_VSN = 3.4 diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index a6c3d57148..780e0cae76 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -34,7 +34,32 @@ </header> - <section><title>SNMP 5.2.12</title> + <section><title>SNMP 5.3</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The application otp_mibs has been removed from OTP. Some + of its components (mibs) have been moved to other apps + (snmp), or removed completely (os_mon).</p> + <p> + Own Id: OTP-14984 Aux Id: OTP-15329 </p> + </item> + <item> + <p> + [snmp|agent] Add a get-mechanism callback module (and a + corresponding behaviour). The agent calls this module to + handle each get (get, get-next and get-bulk) request.</p> + <p> + Own Id: OTP-15691 Aux Id: ERIERL-324 </p> + </item> + </list> + </section> + +</section> + +<section><title>SNMP 5.2.12</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/snmp/src/agent/snmp_community_mib.erl b/lib/snmp/src/agent/snmp_community_mib.erl index 9fd7b30f9f..984b0bcee1 100644 --- a/lib/snmp/src/agent/snmp_community_mib.erl +++ b/lib/snmp/src/agent/snmp_community_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -206,10 +206,10 @@ do_add_community(Community) -> {error, create_failed} end catch - {error, Reason} -> - {error, Reason}; - Class:Reason -> - {error, {Class, Reason, erlang:get_stacktrace()}} + throw:{error, _} = ERROR -> + ERROR; + C:E:S -> + {error, {C, E, S}} end. %% FIXME: does not work with mnesia diff --git a/lib/snmp/src/agent/snmp_generic.erl b/lib/snmp/src/agent/snmp_generic.erl index e67a1b3c80..26a0dd0648 100644 --- a/lib/snmp/src/agent/snmp_generic.erl +++ b/lib/snmp/src/agent/snmp_generic.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2017. All Rights Reserved. +%% Copyright Ericsson AB 1996-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -421,12 +421,12 @@ table_check_status(NameDb, Col, ?'RowStatus_createAndGo', RowIndex, Cols) -> _Found -> {inconsistentValue, Col} end catch - _:_Reason -> + _:_E:_S -> ?vtrace( "failed construct row (createAndGo): " - " n Reason: ~p" - " n Stack: ~p", - [_Reason, erlang:get_stacktrace()]), + " n Error: ~p" + " n Stack: ~p", + [_E, _S]), {noCreation, Col} % Bad RowIndex end; true -> {inconsistentValue, Col} @@ -441,12 +441,12 @@ table_check_status(NameDb, Col, ?'RowStatus_createAndWait', RowIndex, Cols) -> _Row -> {noError, 0} catch - _:_Reason -> + _:_E:_S -> ?vtrace( "failed construct row (createAndWait): " - " n Reason: ~p" - " n Stack: ~p", - [_Reason, erlang:get_stacktrace()]), + " n Error: ~p" + " n Stack: ~p", + [_E, _S]), {noCreation, Col} % Bad RowIndex end; true -> {inconsistentValue, Col} diff --git a/lib/snmp/src/agent/snmp_standard_mib.erl b/lib/snmp/src/agent/snmp_standard_mib.erl index bfe471178d..679d2657c6 100644 --- a/lib/snmp/src/agent/snmp_standard_mib.erl +++ b/lib/snmp/src/agent/snmp_standard_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2015. All Rights Reserved. +%% Copyright Ericsson AB 1996-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ -include("snmp_types.hrl"). -include("STANDARD-MIB.hrl"). +-include("snmpa_internal.hrl"). -define(VMODULE,"STANDARD-MIB"). -include("snmp_verbosity.hrl"). @@ -547,10 +548,12 @@ dummy(_Op) -> ok. %%----------------------------------------------------------------- snmp_set_serial_no(new) -> snmp_generic:variable_func(new, {snmpSetSerialNo, volatile}), - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - Val = random:uniform(2147483648) - 1, + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), + Val = rand:uniform(2147483648) - 1, snmp_generic:variable_func(set, Val, {snmpSetSerialNo, volatile}); snmp_set_serial_no(delete) -> diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl index e65fa7f340..22fd3acb84 100644 --- a/lib/snmp/src/agent/snmp_target_mib.erl +++ b/lib/snmp/src/agent/snmp_target_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2015. All Rights Reserved. +%% Copyright Ericsson AB 1998-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ -define(VMODULE,"TARGET-MIB"). -include("snmp_verbosity.hrl"). +-include("snmpa_internal.hrl"). %% Column not accessible via SNMP - needed when the agent sends informs @@ -673,10 +674,12 @@ snmpTargetSpinLock(print) -> snmpTargetSpinLock(new) -> snmp_generic:variable_func(new, {snmpTargetSpinLock, volatile}), - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - Val = random:uniform(2147483648) - 1, + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), + Val = rand:uniform(2147483648) - 1, snmp_generic:variable_func(set, Val, {snmpTargetSpinLock, volatile}); snmpTargetSpinLock(delete) -> diff --git a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl index f6e4fd3951..4842669fa4 100644 --- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl +++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2015. All Rights Reserved. +%% Copyright Ericsson AB 1999-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -440,10 +440,12 @@ usmUserSpinLock(print) -> usmUserSpinLock(new) -> snmp_generic:variable_func(new, {usmUserSpinLock, volatile}), - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - Val = random:uniform(2147483648) - 1, + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), + Val = rand:uniform(2147483648) - 1, snmp_generic:variable_func(set, Val, {usmUserSpinLock, volatile}); usmUserSpinLock(delete) -> diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl index c6eeb7cea2..56b5d96142 100644 --- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl +++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl @@ -48,6 +48,7 @@ -include("SNMPv2-TC.hrl"). -include("SNMP-VIEW-BASED-ACM-MIB.hrl"). -include("snmpa_vacm.hrl"). +-include("snmpa_internal.hrl"). -define(VMODULE,"VACM-MIB"). @@ -860,10 +861,12 @@ vacmViewSpinLock(print) -> vacmViewSpinLock(new) -> snmp_generic:variable_func(new, volatile_db(vacmViewSpinLock)), - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - Val = random:uniform(2147483648) - 1, + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), + Val = rand:uniform(2147483648) - 1, snmp_generic:variable_func(set, Val, volatile_db(vacmViewSpinLock)); vacmViewSpinLock(delete) -> diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl index b440d57d03..2ec5dcb5e6 100644 --- a/lib/snmp/src/agent/snmpa_mpd.erl +++ b/lib/snmp/src/agent/snmpa_mpd.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2015. All Rights Reserved. +%% Copyright Ericsson AB 1997-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -76,11 +76,9 @@ init(Vsns) -> ?vlog("init -> entry with" "~n Vsns: ~p", [Vsns]), - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - ets:insert(snmp_agent_table, {msg_id, random:uniform(2147483647)}), - ets:insert(snmp_agent_table, {req_id, random:uniform(2147483647)}), + ?SNMP_RAND_SEED(), + ets:insert(snmp_agent_table, {msg_id, rand:uniform(2147483647)}), + ets:insert(snmp_agent_table, {req_id, rand:uniform(2147483647)}), init_counters(), init_versions(Vsns, #state{}). diff --git a/lib/snmp/src/agent/snmpa_trap.erl b/lib/snmp/src/agent/snmpa_trap.erl index d04b6a206e..f741c3aaa9 100644 --- a/lib/snmp/src/agent/snmpa_trap.erl +++ b/lib/snmp/src/agent/snmpa_trap.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -364,13 +364,14 @@ send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, LocalEngineID, ExtraInfo, NetIf) end catch - T:E -> - Info = [{args, [TrapRec, NotifyName, ContextName, - Recv, Vbs, LocalEngineID, ExtraInfo, NetIf]}, - {tag, T}, - {err, E}, - {stacktrace, erlang:get_stacktrace()}], - ?vlog("snmpa_trap:send_trap exception: ~p", [Info]), + C:E:S -> + Info = [{args, [TrapRec, NotifyName, ContextName, + Recv, Vbs, LocalEngineID, ExtraInfo, NetIf]}, + {class, C}, + {err, E}, + {stacktrace, S}], + ?vlog("snmpa_trap:send_trap exception: " + "~n ~p", [Info]), {error, {failed_sending_trap, Info}} end. diff --git a/lib/snmp/src/agent/snmpa_usm.erl b/lib/snmp/src/agent/snmpa_usm.erl index fb616cd9ef..1debceae98 100644 --- a/lib/snmp/src/agent/snmpa_usm.erl +++ b/lib/snmp/src/agent/snmpa_usm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2015. All Rights Reserved. +%% Copyright Ericsson AB 1999-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -646,10 +646,12 @@ get_des_salt() -> ets:insert(snmp_agent_table, {usm_des_salt, 0}), 0; _ -> % it doesn't exist, initialize - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - R = random:uniform(4294967295), + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), + R = rand:uniform(4294967295), ets:insert(snmp_agent_table, {usm_des_salt, R}), R end, @@ -679,10 +681,12 @@ get_aes_salt() -> ets:insert(snmp_agent_table, {usm_aes_salt, 0}), 0; _ -> % it doesn't exist, initialize - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - R = random:uniform(36893488147419103231), + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), + R = rand:uniform(36893488147419103231), ets:insert(snmp_agent_table, {usm_aes_salt, R}), R end, diff --git a/lib/snmp/src/app/snmp_internal.hrl b/lib/snmp/src/app/snmp_internal.hrl index 374767df15..f9a758ab7b 100644 --- a/lib/snmp/src/app/snmp_internal.hrl +++ b/lib/snmp/src/app/snmp_internal.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2016. All Rights Reserved. +%% Copyright Ericsson AB 2006-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,12 @@ -define(APPLICATION, snmp). -endif. --define(STACK(), erlang:get_stacktrace()). + +-define(SNMP_RAND_SEED_ALG, exrop). +-define(SNMP_RAND_SEED(), rand:seed(?SNMP_RAND_SEED_ALG, + {erlang:phash2([node()]), + erlang:monotonic_time(), + erlang:unique_integer()})). -define(snmp_info(C, F, A), ?snmp_msg(info_msg, C, F, A)). -define(snmp_warning(C, F, A), ?snmp_msg(warning_msg, C, F, A)). @@ -39,5 +44,3 @@ -endif. % -ifdef(snmp_internal). - - diff --git a/lib/snmp/src/compile/Makefile b/lib/snmp/src/compile/Makefile index 4093ffa9ca..d9678669a5 100644 --- a/lib/snmp/src/compile/Makefile +++ b/lib/snmp/src/compile/Makefile @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2016. All Rights Reserved. +# Copyright Ericsson AB 1997-2019. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -59,6 +59,8 @@ PARSER_TARGET = $(PARSER_MODULE).$(EMULATOR) # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- +ERL_COMPILE_FLAGS += -pa $(ERL_TOP)/lib/snmp/ebin + ifeq ($(WARN_UNUSED_VARS),true) ERL_COMPILE_FLAGS += +warn_unused_vars endif diff --git a/lib/snmp/src/compile/snmpc.erl b/lib/snmp/src/compile/snmpc.erl index c810bfcd41..4249799195 100644 --- a/lib/snmp/src/compile/snmpc.erl +++ b/lib/snmp/src/compile/snmpc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2018. All Rights Reserved. +%% Copyright Ericsson AB 1997-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ -export([init/3]). -include_lib("stdlib/include/erl_compile.hrl"). +-include_lib("snmp/src/app/snmp_internal.hrl"). -include("snmp_types.hrl"). -include("snmpc.hrl"). -include("snmpc_lib.hrl"). @@ -413,9 +414,11 @@ get_verbosity(Options) -> %%---------------------------------------------------------------------- init(From, MibFileName, Options) -> - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), put(options, Options), put(verbosity, get_verbosity(Options)), put(description, get_description(Options)), diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 118cdcd1df..cd9fecd4d4 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -479,10 +479,7 @@ agent_info(Domain, Address, Item) when is_atom(Domain) -> NAddress -> do_agent_info(Domain, NAddress, Item) catch - _Thrown -> - %% p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n" - %% " ~p", - %% [Domain, Address, Item, _Thrown, erlang:get_stacktrace()]), + _C:_E:_S -> {error, not_found} end; agent_info(Ip, Port, Item) when is_integer(Port) -> @@ -493,10 +490,7 @@ agent_info(Ip, Port, Item) when is_integer(Port) -> Address -> do_agent_info(Domain, Address, Item) catch - _Thrown -> - %% p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n" - %% " ~p", - %% [Ip, Port, Item, _Thrown, erlang:get_stacktrace()]), + _C:_E:_S -> {error, not_found} end. @@ -1688,9 +1682,10 @@ read_agents_config_file(Dir) -> Check = fun check_agent_config/2, try read_file(Dir, "agents.conf", Order, Check, []) catch - throw:Error -> - ?vlog("agent config error: ~p", [Error]), - erlang:raise(throw, Error, erlang:get_stacktrace()) + throw:E:S -> + ?vlog("agent config error: " + "~n ~p", [E]), + erlang:raise(throw, E, S) end. check_agent_config(Agent, State) -> @@ -1935,9 +1930,10 @@ read_users_config_file(Dir) -> Check = fun (User, State) -> {check_user_config(User), State} end, try read_file(Dir, "users.conf", Order, Check, []) catch - throw:Error -> - ?vlog("failure reading users config file: ~n ~p", [Error]), - erlang:raise(throw, Error, erlang:get_stacktrace()) + throw:E:S -> + ?vlog("failure reading users config file: " + "~n ~p", [E]), + erlang:raise(throw, E, S) end. check_user_config({Id, Mod, Data}) -> @@ -2351,10 +2347,11 @@ read_file(Dir, FileName, Order, Check, Default) -> read_file(Dir, FileName, Order, Check) -> try snmp_conf:read(filename:join(Dir, FileName), Order, Check) catch - throw:{error, Reason} = Error + throw:{error, Reason} = E:S when element(1, Reason) =:= failed_open -> - error_msg("failed reading config from ~s: ~p", [FileName, Reason]), - erlang:raise(throw, Error, erlang:get_stacktrace()) + error_msg("failed reading config from ~s: " + "~n ~p", [FileName, Reason]), + erlang:raise(throw, E, S) end. %%-------------------------------------------------------------------- diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl index 191dc2c281..8d0a7918a6 100644 --- a/lib/snmp/src/manager/snmpm_mpd.erl +++ b/lib/snmp/src/manager/snmpm_mpd.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2015. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -68,11 +68,13 @@ %%%----------------------------------------------------------------- init(Vsns) -> ?vdebug("init -> entry with ~p", [Vsns]), - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), - snmpm_config:cre_counter(msg_id, random:uniform(2147483647)), - snmpm_config:cre_counter(req_id, random:uniform(2147483647)), + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), + snmpm_config:cre_counter(msg_id, rand:uniform(2147483647)), + snmpm_config:cre_counter(req_id, rand:uniform(2147483647)), init_counters(), State = init_versions(Vsns, #state{}), init_usm(State#state.v3), diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl index 29216f9d6a..184f782860 100644 --- a/lib/snmp/src/manager/snmpm_net_if.erl +++ b/lib/snmp/src/manager/snmpm_net_if.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2017. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -182,11 +182,9 @@ worker(Worker, Failer, #state{log = Log} = State) -> %% Winds up in handle_info {'DOWN', ...} erlang:exit({net_if_worker, Result}) catch - Class:Reason -> + C:E:S -> %% Winds up in handle_info {'DOWN', ...} - erlang:exit( - {net_if_worker, Failer, - Class, Reason, erlang:get_stacktrace()}) + erlang:exit({net_if_worker, Failer, C, E, S}) end end, [monitor]). @@ -983,11 +981,10 @@ udp_send(Sock, To, Msg) -> error_msg("failed sending message to ~p:~p:~n" " ~p",[IpAddr, IpPort, Reason]) catch - error:Error -> - error_msg("failed sending message to ~p:~p:~n" - " error:~p~n" - " ~p", - [IpAddr, IpPort, Error, erlang:get_stacktrace()]) + error:E:S -> + error_msg("failed sending message to ~p:~p:" + "~n ~p" + "~n ~p", [IpAddr, IpPort, E, S]) end. sz(B) when is_binary(B) -> diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl index c8d7fa1e8b..a6ca2b2b14 100644 --- a/lib/snmp/src/manager/snmpm_server.erl +++ b/lib/snmp/src/manager/snmpm_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2015. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1755,9 +1755,10 @@ handle_error(_UserId, Mod, Reason, ReqId, Data, _State) -> Mod:handle_error(ReqId, Reason, Data) end catch - T:E -> + C:E:S -> CallbackArgs = [ReqId, Reason, Data], - handle_invalid_result(handle_error, CallbackArgs, T, E) + handle_invalid_result(handle_error, CallbackArgs, + C, E, S) end end, handle_callback(F), @@ -1948,9 +1949,10 @@ handle_pdu( Mod:handle_pdu(TargetName, ReqId, SnmpResponse, Data) end catch - T:E -> + C:E:S -> CallbackArgs = [TargetName, ReqId, SnmpResponse, Data], - handle_invalid_result(handle_pdu, CallbackArgs, T, E) + handle_invalid_result(handle_pdu, CallbackArgs, + C, E, S) end end, handle_callback(F), @@ -2119,10 +2121,10 @@ do_handle_agent(DefUserId, DefMod, "<~p,~p>: ~n~w", [Type, Domain, Addr, SnmpInfo]) end; - T:E -> + C:E:S -> CallbackArgs = [Domain_or_Ip, Addr_or_Port, Type, SnmpInfo, DefData], - handle_invalid_result(handle_agent, CallbackArgs, T, E) + handle_invalid_result(handle_agent, CallbackArgs, C, E, S) end. @@ -2331,8 +2333,8 @@ do_handle_trap( handle_invalid_result(handle_trap, CallbackArgs, InvalidResult) catch - T:E -> - handle_invalid_result(handle_trap, CallbackArgs, T, E) + C:E:S -> + handle_invalid_result(handle_trap, CallbackArgs, C, E, S) end. @@ -2523,8 +2525,8 @@ do_handle_inform( reply catch - T:E -> - handle_invalid_result(handle_inform, CallbackArgs, T, E), + C:E:S -> + handle_invalid_result(handle_inform, CallbackArgs, C, E, S), reply end, @@ -2837,8 +2839,8 @@ do_handle_report( reply catch - T:E -> - handle_invalid_result(handle_report, CallbackArgs, T, E), + C:E:S -> + handle_invalid_result(handle_report, CallbackArgs, C, E, S), reply end. @@ -2855,15 +2857,14 @@ handle_callback(F) -> -handle_invalid_result(Func, Args, T, E) -> - Stacktrace = ?STACK(), +handle_invalid_result(Func, Args, C, E, S) -> error_msg("Callback function failed: " "~n Function: ~p" "~n Args: ~p" - "~n Error Type: ~p" + "~n Class: ~p" "~n Error: ~p" "~n Stacktrace: ~p", - [Func, Args, T, E, Stacktrace]). + [Func, Args, C, E, S]). handle_invalid_result(Func, Args, InvalidResult) -> error_msg("Callback function returned invalid result: " diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl index 513616a285..d73291764d 100644 --- a/lib/snmp/src/misc/snmp_conf.erl +++ b/lib/snmp/src/misc/snmp_conf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -236,15 +236,16 @@ read_check(File, Check, [{StartLine, Row, EndLine}|Lines], State, Res) -> " NewRow: ~p~n", [NewRow]), read_check(File, Check, Lines, NewState, [NewRow | Res]) catch - {error, Reason} -> - ?vtrace("read_check -> error:~n" - " Reason: ~p", [Reason]), + throw:{error, Reason} -> + ?vtrace("read_check -> error:" + "~n Reason: ~p", [Reason]), error({failed_check, File, StartLine, EndLine, Reason}); - Class:Reason -> - Error = {Class,Reason,erlang:get_stacktrace()}, - ?vtrace("read_check -> failure:~n" - " Error: ~p", [Error]), - error({failed_check, File, StartLine, EndLine, Error}) + C:E:S -> + ?vtrace("read_check -> failure:" + "~n Class: ~p" + "~n Error: ~p" + "~n Stack: ~p", [C, E, S]), + error({failed_check, File, StartLine, EndLine, {C, E, S}}) end. open_file(File) -> diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl index 45661b71a7..26e85897f4 100644 --- a/lib/snmp/src/misc/snmp_config.erl +++ b/lib/snmp/src/misc/snmp_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -2573,15 +2573,17 @@ write_config_file(Dir, FileName, Order, Check, Write, Entries) Error end catch - Error -> - S = erlang:get_stacktrace(), - d("File write of ~s throwed: ~p~n ~p~n", - [FileName, Error, S]), - Error; - C:E -> - S = erlang:get_stacktrace(), - d("File write of ~s exception: ~p:~p~n ~p~n", - [FileName,C,E,S]), + throw:E:S -> + d("File write of ~s throwed: " + "~n ~p" + "~n ~p" + "~n", [FileName, E, S]), + E; + C:E:S -> + d("File write of ~s exception: " + "~n ~p:~p" + "~n ~p" + "~n", [FileName, C, E, S]), {error, {failed_write, Dir, FileName, {C, E, S}}} end. @@ -2590,16 +2592,18 @@ write_config_file(Dir, FileName, Write, Entries, Fd) -> ok -> close_config_file(Dir, FileName, Fd) catch - Error -> - S = erlang:get_stacktrace(), - d("File write of ~s throwed: ~p~n ~p~n", - [FileName, Error, S]), + throw:E:S -> + d("File write of ~s throwed: " + "~n ~p" + "~n ~p" + "~n", [FileName, E, S]), close_config_file(Dir, FileName, Fd), - Error; - C:E -> - S = erlang:get_stacktrace(), - d("File write of ~s exception: ~p:~p~n ~p~n", - [FileName,C,E,S]), + E; + C:E:S -> + d("File write of ~s exception: " + "~n ~p:~p" + "~n ~p" + "~n", [FileName, C, E, S]), close_config_file(Dir, FileName, Fd), {error, {failed_write, Dir, FileName, {C, E, S}}} end. @@ -2661,16 +2665,18 @@ append_config_file(Dir, FileName, Order, Check, Write, Entries, Fd) -> ok -> close_config_file(Dir, FileName, Fd) catch - Error -> - S = erlang:get_stacktrace(), - d("File append of ~s throwed: ~p~n ~p~n", - [FileName, Error, S]), + throw:E:S -> + d("File append of ~s throwed: " + "~n ~p" + "~n ~p" + "~n", [FileName, E, S]), close_config_file(Dir, FileName, Fd), - Error; - C:E -> - S = erlang:get_stacktrace(), - d("File append of ~s exception: ~p:~p~n ~p~n", - [FileName,C,E,S]), + E; + C:E:S -> + d("File append of ~s exception: " + "~n ~p:~p" + "~n ~p" + "~n", [FileName, C, E, S]), close_config_file(Dir, FileName, Fd), {error, {failed_append, Dir, FileName, {C, E, S}}} end. @@ -2702,16 +2708,18 @@ read_config_file(Dir, FileName, Order, Check) SortedLines = sort_lines(Lines, Order), {ok, verify_lines(SortedLines, Check, undefined, [])} catch - Error -> - S = erlang:get_stacktrace(), - d("File read of ~s throwed: ~p~n ~p~n", - [FileName, Error, S]), - {error, Error}; - T:E -> - S = erlang:get_stacktrace(), - d("File read of ~s exception: ~p:~p~n ~p~n", - [FileName,T,E,S]), - {error, {failed_read, Dir, FileName, {T, E, S}}} + throw:E:S -> + d("File read of ~s throwed: " + "~n ~p" + "~n ~p" + "~n", [FileName, E, S]), + {error, E}; + C:E:S -> + d("File read of ~s exception: " + "~n ~p:~p" + "~n ~p" + "~n", [FileName, C, E, S]), + {error, {failed_read, Dir, FileName, {C, E, S}}} after file:close(Fd) end; @@ -2760,11 +2768,10 @@ verify_lines( {{ok, NewTerm}, NewState} -> verify_lines(Lines, Check, NewState, [NewTerm|Acc]) catch - {error, Reason} -> + throw:{error, Reason}:_ -> throw({failed_check, StartLine, EndLine, Reason}); - C:R -> - S = erlang:get_stacktrace(), - throw({failed_check, StartLine, EndLine, {C, R, S}}) + C:E:S -> + throw({failed_check, StartLine, EndLine, {C, E, S}}) end. diff --git a/lib/snmp/test/snmp_manager_config_test.erl b/lib/snmp/test/snmp_manager_config_test.erl index 64d3134055..ccbdd77629 100644 --- a/lib/snmp/test/snmp_manager_config_test.erl +++ b/lib/snmp/test/snmp_manager_config_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ -include_lib("common_test/include/ct.hrl"). -include("snmp_test_lib.hrl"). -include_lib("snmp/src/manager/snmpm_usm.hrl"). +-include_lib("snmp/src/app/snmp_internal.hrl"). %%---------------------------------------------------------------------- @@ -2259,11 +2260,13 @@ create_and_increment(Conf) when is_list(Conf) -> ?line {ok, _Pid} = snmpm_config:start_link(Opts), %% Random init - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), - StartVal = random:uniform(2147483647), + StartVal = rand:uniform(2147483647), IncVal = 42, EndVal = StartVal + IncVal, diff --git a/lib/snmp/test/snmp_test_mgr.erl b/lib/snmp/test/snmp_test_mgr.erl index 73a4d56084..9190c07e6d 100644 --- a/lib/snmp/test/snmp_test_mgr.erl +++ b/lib/snmp/test/snmp_test_mgr.erl @@ -52,6 +52,7 @@ -include_lib("snmp/include/snmp_types.hrl"). -include_lib("snmp/include/STANDARD-MIB.hrl"). -include("snmp_test_lib.hrl"). +-include_lib("snmp/src/app/snmp_internal.hrl"). -record(state, {dbg = true, quiet, @@ -192,9 +193,11 @@ receive_trap(Timeout) -> init({Options, CallerPid}) -> put(sname, mgr), put(verbosity, debug), - random:seed(erlang:phash2([node()]), - erlang:monotonic_time(), - erlang:unique_integer()), + ?SNMP_RAND_SEED(), + %% rand:seed(exrop, + %% {erlang:phash2([node()]), + %% erlang:monotonic_time(), + %% erlang:unique_integer()}), case (catch is_options_ok(Options)) of true -> put(debug, get_value(debug, Options, false)), @@ -668,7 +671,6 @@ make_vb(Oid) -> #varbind{oid = Oid, variabletype = 'NULL', value = 'NULL'}. make_request_id() -> - %% random:uniform(16#FFFFFFF-1). snmp_test_mgr_counter_server:increment(mgr_request_id, 1, 1, 2147483647). echo_pdu(PDU, MiniMIB) -> @@ -1141,5 +1143,5 @@ d(_,_F,_A) -> print(F, A) -> ?PRINT2("MGR " ++ F, A). -formated_timestamp() -> - snmp_test_lib:formated_timestamp(). +%% formated_timestamp() -> +%% snmp_test_lib:formated_timestamp(). diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 78990c48f2..60f20c7c3f 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,21 @@ <file>notes.xml</file> </header> +<section><title>Ssh 4.7.7</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + SSH uses the new crypto API.</p> + <p> + Own Id: OTP-15673</p> + </item> + </list> + </section> + +</section> + <section><title>Ssh 4.7.6</title> <section><title>Improvements and New Features</title> diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src index 7449405d20..2193c14611 100644 --- a/lib/ssh/src/ssh.app.src +++ b/lib/ssh/src/ssh.app.src @@ -44,7 +44,7 @@ {env, []}, {mod, {ssh_app, []}}, {runtime_dependencies, [ - "crypto-@OTP-15644@", + "crypto-4.5", "erts-9.0", "kernel-5.3", "public_key-1.6.1", diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 837da27ab0..bb87dd388c 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,4 +1,4 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.7.6 +SSH_VSN = 4.7.7 APP_VSN = "ssh-$(SSH_VSN)" diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 7947049a04..01cd630668 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -27,6 +27,115 @@ </header> <p>This document describes the changes made to the SSL application.</p> +<section><title>SSL 9.3.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Missing check of size of user_data_buffer made internal + socket behave as an active socket instead of active N. + This could cause memory problems.</p> + <p> + Own Id: OTP-15825 Aux Id: ERL-934, OTP-15823 </p> + </item> + </list> + </section> + +</section> + +<section><title>SSL 9.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The distribution handshake with TLS distribution + (<c>inet_tls_dist</c>) does now utilize the socket option + <c>{nodelay, true}</c>, which decreases the distribution + setup time significantly.</p> + <p> + Own Id: OTP-14792</p> + </item> + <item> + <p> + Correct shutdown reason to avoid an incorrect crash + report</p> + <p> + Own Id: OTP-15710 Aux Id: ERL-893 </p> + </item> + <item> + <p> + Enhance documentation and type specifications.</p> + <p> + Own Id: OTP-15746 Aux Id: ERIERL-333 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + TLS-1.0, TLS-1.1 and DTLS-1.0 are now considered legacy + and not supported by default</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14865</p> + </item> + <item> + <p> + Use new logger API in ssl. Introduce log levels and + verbose debug logging for SSL.</p> + <p> + Own Id: OTP-15055</p> + </item> + <item> + <p> + Add new API function str_to_suite/1, cipher_suites/3 + (list cipher suites as rfc or OpenSSL name strings) and + suite_to_openssl_str/1</p> + <p> + Own Id: OTP-15483 Aux Id: ERL-924 </p> + </item> + <item> + <p> + Basic support for TLS 1.3 Server for experimental use. + The client is not yet functional, for more information + see the Standards Compliance chapter of the User's Guide.</p> + <p> + Own Id: OTP-15591</p> + </item> + <item> + <p> + Add support for PSK CCM ciphers from RFC 6655</p> + <p> + Own Id: OTP-15626</p> + </item> + </list> + </section> + +</section> + +<section><title>SSL 9.2.3.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Correct solution for retaining tcp flow control OTP-15802 + (ERL-934) as to not break ssl:recv as reported in + (ERL-938)</p> + <p> + Own Id: OTP-15823 Aux Id: ERL-934, ERL-938 </p> + </item> + </list> + </section> + +</section> + <section><title>SSL 9.2.3</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl index e070006900..6928d7a93d 100644 --- a/lib/ssl/src/dtls_connection.erl +++ b/lib/ssl/src/dtls_connection.erl @@ -51,7 +51,7 @@ -export([encode_alert/3, send_alert/2, send_alert_in_connection/2, close/5, protocol_name/0]). %% Data handling --export([next_record/1, socket/4, setopts/3, getopts/3]). +-export([socket/4, setopts/3, getopts/3]). %% gen_statem state functions -export([init/3, error/3, downgrade/3, %% Initiation and take down states @@ -451,11 +451,11 @@ init({call, From}, {start, Timeout}, HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions), State1 = prepare_flight(State0#state{connection_env = CEnv#connection_env{negotiated_version = Version}}), {State2, Actions} = send_handshake(Hello, State1#state{connection_env = CEnv#connection_env{negotiated_version = HelloVersion}}), - State3 = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% RequestedVersion + State = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% RequestedVersion session = Session0#session{session_id = Hello#client_hello.session_id}, start_or_recv_from = From}, - next_event(hello, no_record, State3, [{{timeout, handshake}, Timeout, close} | Actions]); + next_event(hello, no_record, State, [{{timeout, handshake}, Timeout, close} | Actions]); init({call, _} = Type, Event, #state{static_env = #static_env{role = server}, protocol_specific = PS} = State) -> Result = gen_handshake(?FUNCTION_NAME, Type, Event, @@ -514,7 +514,7 @@ hello(internal, #client_hello{cookie = <<>>, VerifyRequest = dtls_handshake:hello_verify_request(Cookie, ?HELLO_VERIFY_REQUEST_VERSION), State1 = prepare_flight(State0#state{connection_env = CEnv#connection_env{negotiated_version = Version}}), {State, Actions} = send_handshake(VerifyRequest, State1), - next_event(?FUNCTION_NAME, no_record, + next_event(?FUNCTION_NAME, no_record, State#state{handshake_env = HsEnv#handshake_env{ tls_handshake_history = ssl_handshake:init_handshake_history()}}, diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index a5f754d2e3..345db7510f 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -1194,7 +1194,7 @@ cipher(internal, #next_protocol{selected_protocol = SelectedProtocol}, #state{static_env = #static_env{role = server}, handshake_env = #handshake_env{expecting_finished = true, expecting_next_protocol_negotiation = true} = HsEnv} = State, Connection) -> - Connection:next_event(?FUNCTION_NAME, no_record, + Connection:next_event(?FUNCTION_NAME, no_record, State#state{handshake_env = HsEnv#handshake_env{negotiated_protocol = SelectedProtocol, expecting_next_protocol_negotiation = false}}); cipher(internal, #change_cipher_spec{type = <<1>>}, #state{handshake_env = HsEnv, connection_states = ConnectionStates0} = diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 7b34991f4f..f68d3e9b26 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -98,8 +98,8 @@ hello_request() -> #hello_request{}. %%-------------------------------------------------------------------- --spec server_hello(binary(), ssl_record:ssl_version(), ssl_record:connection_states(), - Extension::map()) -> #server_hello{}. +%%-spec server_hello(binary(), ssl_record:ssl_version(), ssl_record:connection_states(), +%% Extension::map()) -> #server_hello{}. %% %% Description: Creates a server hello message. %%-------------------------------------------------------------------- diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index a05858221a..61281a3fb2 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -62,7 +62,7 @@ close/5, protocol_name/0]). %% Data handling --export([next_record/1, socket/4, setopts/3, getopts/3]). +-export([socket/4, setopts/3, getopts/3]). %% gen_statem state functions -export([init/3, error/3, downgrade/3, %% Initiation and take down states @@ -161,32 +161,60 @@ pids(#state{protocol_specific = #{sender := Sender}}) -> %%==================================================================== %% State transition handling %%==================================================================== -next_record(#state{handshake_env = +next_record(_, #state{handshake_env = #handshake_env{unprocessed_handshake_events = N} = HsEnv} = State) when N > 0 -> {no_record, State#state{handshake_env = HsEnv#handshake_env{unprocessed_handshake_events = N-1}}}; -next_record(#state{protocol_buffers = - #protocol_buffers{tls_cipher_texts = [_|_] = CipherTexts}, - connection_states = ConnectionStates, - ssl_options = #ssl_options{padding_check = Check}} = State) -> +next_record(_, #state{protocol_buffers = + #protocol_buffers{tls_cipher_texts = [_|_] = CipherTexts}, + connection_states = ConnectionStates, + ssl_options = #ssl_options{padding_check = Check}} = State) -> next_record(State, CipherTexts, ConnectionStates, Check); -next_record(#state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, - protocol_specific = #{active_n_toggle := true, active_n := N} = ProtocolSpec, - static_env = #static_env{socket = Socket, - close_tag = CloseTag, - transport_cb = Transport} - } = State) -> - case tls_socket:setopts(Transport, Socket, [{active, N}]) of - ok -> - {no_record, State#state{protocol_specific = ProtocolSpec#{active_n_toggle => false}}}; - _ -> - self() ! {CloseTag, Socket}, - {no_record, State} - end; -next_record(State) -> +next_record(connection, #state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, + protocol_specific = #{active_n_toggle := true} + } = State) -> + %% If ssl application user is not reading data wait to activate socket + flow_ctrl(State); + +next_record(_, #state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, + protocol_specific = #{active_n_toggle := true} + } = State) -> + activate_socket(State); +next_record(_, State) -> {no_record, State}. + +flow_ctrl(#state{user_data_buffer = {_,Size,_}, + socket_options = #socket_options{active = false}, + bytes_to_read = undefined} = State) when Size =/= 0 -> + {no_record, State}; +flow_ctrl(#state{user_data_buffer = {_,Size,_}, + socket_options = #socket_options{active = false}, + bytes_to_read = 0} = State) when Size =/= 0 -> + {no_record, State}; +flow_ctrl(#state{user_data_buffer = {_,Size,_}, + socket_options = #socket_options{active = false}, + bytes_to_read = BytesToRead} = State) when (Size >= BytesToRead) andalso + (BytesToRead > 0) -> + {no_record, State}; +flow_ctrl(State) -> + activate_socket(State). + + +activate_socket(#state{protocol_specific = #{active_n_toggle := true, active_n := N} = ProtocolSpec, + static_env = #static_env{socket = Socket, + close_tag = CloseTag, + transport_cb = Transport} + } = State) -> + case tls_socket:setopts(Transport, Socket, [{active, N}]) of + ok -> + {no_record, State#state{protocol_specific = ProtocolSpec#{active_n_toggle => false}}}; + _ -> + self() ! {CloseTag, Socket}, + {no_record, State} + end. + %% Decipher next record and concatenate consecutive ?APPLICATION_DATA records into one %% next_record(State, CipherTexts, ConnectionStates, Check) -> @@ -224,31 +252,20 @@ next_record_done(#state{protocol_buffers = Buffers} = State, CipherTexts, Connec State#state{protocol_buffers = Buffers#protocol_buffers{tls_cipher_texts = CipherTexts}, connection_states = ConnectionStates}}. - next_event(StateName, Record, State) -> next_event(StateName, Record, State, []). %% next_event(StateName, no_record, State0, Actions) -> - case next_record(State0) of + case next_record(StateName, State0) of {no_record, State} -> {next_state, StateName, State, Actions}; - {#ssl_tls{} = Record, State} -> - {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; - #alert{} = Alert -> - Version = State0#state.connection_env#connection_env.negotiated_version, - ssl_connection:handle_own_alert(Alert, Version, StateName, State0) + {Record, State} -> + next_event(StateName, Record, State, Actions) end; -next_event(StateName, Record, State, Actions) -> - case Record of - no_record -> - {next_state, StateName, State, Actions}; - #ssl_tls{} = Record -> - {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; - #alert{} = Alert -> - Version = State#state.connection_env#connection_env.negotiated_version, - ssl_connection:handle_own_alert(Alert, Version, StateName, State) - end. - +next_event(StateName, #ssl_tls{} = Record, State, Actions) -> + {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; +next_event(StateName, #alert{} = Alert, State, Actions) -> + {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}. %%% TLS record protocol level application data messages handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName, @@ -272,12 +289,8 @@ handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, Stat {stop, _, _} = Stop-> Stop; {Record, State1} -> - case next_event(StateName, Record, State1) of - {next_state, StateName, State, Actions} -> - ssl_connection:hibernate_after(StateName, State, Actions); - {stop, _, _} = Stop -> - Stop - end + {next_state, StateName, State, Actions} = next_event(StateName, Record, State1), + ssl_connection:hibernate_after(StateName, State, Actions) end; %%% TLS record protocol level handshake messages handle_protocol_record(#ssl_tls{type = ?HANDSHAKE, fragment = Data}, @@ -1049,7 +1062,7 @@ next_tls_record(Data, StateName, case tls_record:get_tls_records(Data, Versions, Buf0, SslOpts) of {Records, Buf1} -> CT1 = CT0 ++ Records, - next_record(State0#state{protocol_buffers = + next_record(StateName, State0#state{protocol_buffers = Buffers#protocol_buffers{tls_record_buffer = Buf1, tls_cipher_texts = CT1}}); #alert{} = Alert -> diff --git a/lib/ssl/src/tls_connection_1_3.erl b/lib/ssl/src/tls_connection_1_3.erl index 701a5860c2..76cdebc76f 100644 --- a/lib/ssl/src/tls_connection_1_3.erl +++ b/lib/ssl/src/tls_connection_1_3.erl @@ -116,9 +116,8 @@ ]). -start(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +start(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); start(internal, #client_hello{} = Hello, State0, _Module) -> case tls_handshake_1_3:do_start(Hello, State0) of #alert{} = Alert -> @@ -132,9 +131,8 @@ start(Type, Msg, State, Connection) -> ssl_connection:handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). -negotiated(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +negotiated(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); negotiated(internal, Message, State0, _Module) -> case tls_handshake_1_3:do_negotiated(Message, State0) of #alert{} = Alert -> @@ -144,41 +142,36 @@ negotiated(internal, Message, State0, _Module) -> end. -wait_cert(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +wait_cert(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); wait_cert(internal, #certificate_1_3{} = Certificate, State0, _Module) -> case tls_handshake_1_3:do_wait_cert(Certificate, State0) of {#alert{} = Alert, State} -> ssl_connection:handle_own_alert(Alert, {3,4}, wait_cert, State); - {State1, NextState} -> - {Record, State} = tls_connection:next_record(State1), - tls_connection:next_event(NextState, Record, State) + {State, NextState} -> + tls_connection:next_event(NextState, no_record, State) end; wait_cert(Type, Msg, State, Connection) -> ssl_connection:handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). -wait_cv(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +wait_cv(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); wait_cv(internal, #certificate_verify_1_3{} = CertificateVerify, State0, _Module) -> case tls_handshake_1_3:do_wait_cv(CertificateVerify, State0) of {#alert{} = Alert, State} -> ssl_connection:handle_own_alert(Alert, {3,4}, wait_cv, State); - {State1, NextState} -> - {Record, State} = tls_connection:next_record(State1), - tls_connection:next_event(NextState, Record, State) + {State, NextState} -> + tls_connection:next_event(NextState, no_record, State) end; wait_cv(Type, Msg, State, Connection) -> ssl_connection:handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). -wait_finished(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +wait_finished(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); wait_finished(internal, #finished{} = Finished, State0, Module) -> case tls_handshake_1_3:do_wait_finished(Finished, State0) of diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl index 27b9c258a0..2d0ffd03d7 100644 --- a/lib/ssl/test/ssl_payload_SUITE.erl +++ b/lib/ssl/test/ssl_payload_SUITE.erl @@ -48,21 +48,27 @@ groups() -> payload_tests() -> [server_echos_passive_small, + server_echos_passive_chunk_small, server_echos_active_once_small, server_echos_active_small, client_echos_passive_small, + client_echos_passive_chunk_small, client_echos_active_once_small, client_echos_active_small, server_echos_passive_big, + server_echos_passive_chunk_big, server_echos_active_once_big, server_echos_active_big, client_echos_passive_big, + client_echos_passive_chunk_big, client_echos_active_once_big, client_echos_active_big, server_echos_passive_huge, + server_echos_passive_chunk_huge, server_echos_active_once_huge, server_echos_active_huge, client_echos_passive_huge, + client_echos_passive_chunk_huge, client_echos_active_once_huge, client_echos_active_huge, client_active_once_server_close]. @@ -109,9 +115,11 @@ end_per_group(GroupName, Config) -> init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_huge; + TestCase == server_echos_passive_chunk_huge; TestCase == server_echos_active_once_huge; TestCase == server_echos_active_huge; TestCase == client_echos_passive_huge; + TestCase == client_echos_passive_chunk_huge; TestCase == client_echos_active_once_huge; TestCase == client_echos_active_huge -> case erlang:system_info(system_architecture) of @@ -124,9 +132,11 @@ init_per_testcase(TestCase, Config) init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_big; + TestCase == server_echos_passive_chunk_big; TestCase == server_echos_active_once_big; TestCase == server_echos_active_big; TestCase == client_echos_passive_big; + TestCase == client_echos_passive_chunk_big; TestCase == client_echos_active_once_big; TestCase == client_echos_active_big -> ct:timetrap({seconds, 60}), @@ -157,6 +167,22 @@ server_echos_passive_small(Config) when is_list(Config) -> %%-------------------------------------------------------------------- +server_echos_passive_chunk_small() -> + [{doc, "Client sends 1000 bytes in passive mode to server, that receives them in chunks, " + "sends them back, and closes."}]. + +server_echos_passive_chunk_small(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 100), + server_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + + +%%-------------------------------------------------------------------- + server_echos_active_once_small() -> [{doc, "Client sends 1000 bytes in active once mode to server, that receives " " them, sends them back, and closes."}]. @@ -200,6 +226,21 @@ client_echos_passive_small(Config) when is_list(Config) -> Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). %%-------------------------------------------------------------------- +client_echos_passive_chunk__small() -> + [{doc, "Server sends 1000 bytes in passive mode to client, that receives them in chunks, " + "sends them back, and closes."}]. + +client_echos_passive_chunk_small(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 100), + client_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + + +%%-------------------------------------------------------------------- client_echos_active_once_small() -> ["Server sends 1000 bytes in active once mode to client, that receives " "them, sends them back, and closes."]. @@ -241,6 +282,19 @@ server_echos_passive_big(Config) when is_list(Config) -> Data = binary:copy(<<"1234567890">>, 5000), server_echos_passive( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). +%%-------------------------------------------------------------------- +server_echos_passive_chunk_big() -> + [{doc, "Client sends 50000 bytes to server in passive mode, that receives them, " + "sends them back, and closes."}]. + +server_echos_passive_chunk_big(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 5000), + server_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). %%-------------------------------------------------------------------- @@ -286,6 +340,22 @@ client_echos_passive_big(Config) when is_list(Config) -> client_echos_passive( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + +%%-------------------------------------------------------------------- +client_echos_passive_chunk_big() -> + [{doc, "Server sends 50000 bytes to client in passive mode, that receives them, " + "sends them back, and closes."}]. + +client_echos_passive_chunk_big(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 5000), + client_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + + %%-------------------------------------------------------------------- client_echos_active_once_big() -> [{doc, "Server sends 50000 bytes to client in active once mode, that receives" @@ -329,6 +399,20 @@ server_echos_passive_huge(Config) when is_list(Config) -> Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). %%-------------------------------------------------------------------- +server_echos_passive_chunk_huge() -> + [{doc, "Client sends 500000 bytes to server in passive mode, that receives " + " them, sends them back, and closes."}]. + +server_echos_passive_chunk_huge(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 50000), + server_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + +%%-------------------------------------------------------------------- server_echos_active_once_huge() -> [{doc, "Client sends 500000 bytes to server in active once mode, that receives " "them, sends them back, and closes."}]. @@ -369,7 +453,19 @@ client_echos_passive_huge(Config) when is_list(Config) -> Data = binary:copy(<<"1234567890">>, 50000), client_echos_passive( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). +%%-------------------------------------------------------------------- +client_echos_passive_chunk_huge() -> + [{doc, "Server sends 500000 bytes to client in passive mode, that receives " + "them, sends them back, and closes."}]. +client_echos_passive_chunk_huge(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 50000), + client_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). %%-------------------------------------------------------------------- client_echos_active_once_huge() -> [{doc, "Server sends 500000 bytes to client in active once mode, that receives " @@ -442,6 +538,28 @@ server_echos_passive( ssl_test_lib:close(Server), ssl_test_lib:close(Client). +server_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) -> + Length = byte_size(Data), + Server = + ssl_test_lib:start_server( + [{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, echoer_chunk, [Length]}}, + {options, [{active, false}, {mode, binary} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = + ssl_test_lib:start_client( + [{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, sender, [Data]}}, + {options, [{active, false}, {mode, binary} | ClientOpts]}]), + %% + ssl_test_lib:check_result(Server, ok, Client, ok), + %% + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). server_echos_active_once( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) -> @@ -513,6 +631,31 @@ client_echos_passive( ssl_test_lib:close(Server), ssl_test_lib:close(Client). + +client_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) -> + Length = byte_size(Data), + Server = + ssl_test_lib:start_server( + [{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, sender, [Data]}}, + {options, [{active, false}, {mode, binary} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = + ssl_test_lib:start_client( + [{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, echoer_chunk, [Length]}}, + {options, [{active, false}, {mode, binary} | ClientOpts]}]), + %% + ssl_test_lib:check_result(Server, ok, Client, ok), + %% + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + client_echos_active_once( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) -> Length = byte_size(Data), @@ -615,6 +758,10 @@ echoer(Socket, Size) -> ct:log("Echoer recv: ~p~n", [ssl:getopts(Socket, [active])]), echo_recv(Socket, Size * 100). +echoer_chunk(Socket, Size) -> + ct:log("Echoer recv: ~p~n", [ssl:getopts(Socket, [active])]), + echo_recv_chunk(Socket, Size, Size * 100). + echoer_active_once(Socket, Size) -> ct:log("Echoer active once: ~p~n", [ssl:getopts(Socket, [active])]), echo_active_once(Socket, Size * 100). @@ -632,6 +779,16 @@ echo_recv(Socket, Size) -> ok = ssl:send(Socket, Data), echo_recv(Socket, Size - byte_size(Data)). + +%% Receive Size bytes +echo_recv_chunk(_Socket, _, 0) -> + ok; +echo_recv_chunk(Socket, ChunkSize, Size) -> + {ok, Data} = ssl:recv(Socket, ChunkSize), + ok = ssl:send(Socket, Data), + echo_recv_chunk(Socket, ChunkSize, Size - ChunkSize). + + %% Receive Size bytes echo_active_once(_Socket, 0) -> ok; diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index b5545b71f7..cbc32cd5a8 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 9.2.3 +SSL_VSN = 9.3.1 diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml index f3d4edd30f..fd991f258b 100644 --- a/lib/stdlib/doc/src/binary.xml +++ b/lib/stdlib/doc/src/binary.xml @@ -505,15 +505,16 @@ store(Binary, GBSet) -> <<1,1,1,1,1 ... 2> byte_size(A). 100 -3> binary:referenced_byte_size(A) +3> binary:referenced_byte_size(A). 100 -4> <<_:10/binary,B:10/binary,_/binary>> = A. +4> <<B:10/binary, C:90/binary>> = A. <<1,1,1,1,1 ... -5> byte_size(B). -10 -6> binary:referenced_byte_size(B) -100</code> - +5> {byte_size(B), binary:referenced_byte_size(B)}. +{10,10} +6> {byte_size(C), binary:referenced_byte_size(C)}. +{90,100}</code> + <p>In the above example, the small binary <c>B</c> was copied while the + larger binary <c>C</c> references binary <c>A</c>.</p> <note> <p>Binary data is shared among processes. If another process still references the larger binary, copying the part this diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index 6f6849a19d..ef548ad643 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -40,7 +40,7 @@ <p> This reference manual describes types generated from the types in the <c>gen_statem</c> source code, so they are correct. - However, the generated descriptions also reflect the type hiearchy, + However, the generated descriptions also reflect the type hierarchy, which makes them kind of hard to read. </p> <p> diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index ef12e525e3..605a9f224d 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -31,6 +31,247 @@ </header> <p>This document describes the changes made to the STDLIB application.</p> +<section><title>STDLIB 3.9</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> Fix a bug in <c>string:lexemes/2</c>. </p> <p> The + bug was found when optimizing the handling of deep lists + of Unicode characters in the <c>string</c> module. </p> + <p> + Own Id: OTP-15649</p> + </item> + <item> + <p>A bug has been fixed in the <c>maps</c> implementation + that could cause a crash or memory usage to grow until + the machine ran out of memory. This could happen when + inserting a new key-value pair with a key <c>K1</c> + containing a binary <c>B1</c> into a map <c>M</c> having + a key <c>K2</c> with a binary <c>B2</c> if the following + conditions were met:</p> <list> <item><c>B1 =/= + B2</c></item> <item><c>size(B1) >= 4294967296</c></item> + <item><c>size(B2) >= 4294967296</c></item> + <item><c>size(M) >= 32</c></item> <item><c>(size(B1) rem + 4294967296) == (size(B2) rem 4294967296)</c></item> + <item>the first <c>(size(B1) rem 4294967296)</c> bytes + are the same both in <c>B1</c> and <c>B2</c></item> + <item>substituting <c>B1</c> in <c>K1</c> with <c>B2</c> + would create a term with the same value as + <c>K2</c></item> </list> <p>The root cause of the problem + is that the <c>maps</c> implementation only hashed the + first <c>(X rem 4294967296)</c> bytes of binaries so that + different binaries could get the same hash value + independently of the hash seed.</p> + <p> + Own Id: OTP-15707</p> + </item> + <item> + <p> Since the introduction of the stack trace variable, + the Erlang Pretty Printer has left out the exception + class <c>throw</c> even when the stack trace variable + cannot be left out, which is not correct Erlang code. The + fix is to always include the exception class + <c>throw</c>. </p> + <p> + Own Id: OTP-15751</p> + </item> + <item> + <p><c>record_info/2</c> is a pseudo-function that + requires literal arguments known at compile time. + Therefore, the following usage is illegal: <c>fun + record/info/2</c>. The compiler would crash when during + compilation of that kind of code. Corrected to issue a + compilation error.</p> + <p> + Own Id: OTP-15760 Aux Id: ERL-907 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> A new <c>rand</c> module algorithm, <c>exro928ss</c> + (Xoroshiro928**), has been implemented. It has got a + really long period and good statistical quality for all + output bits, while still being only about 50% slower than + the default algorithm. </p><p> The same generator is also + used as a long period counter in a new <c>crypto</c> + plugin for the <c>rand</c> module, algorithm + <c>crypto_aes</c>. This plugin uses AES-256 to scramble + the counter which buries any detectable statistical + artifacts. Scrambling is done in chunks which are cached + to get good amortized speed (about half of the default + algorithm). </p> + <p> + Own Id: OTP-14461 Aux Id: PR-1857 </p> + </item> + <item> + <p> + Types related to server naming and starting have been + exported from <c>gen_statem</c>. These are: + <c>server_name/0</c>, <c>server_ref/0</c>, + <c>start_opt/0</c>, <c>start_ret/0</c> and + <c>enter_loop_opt/0</c>.</p> + <p> + Own Id: OTP-14724 Aux Id: PR-2056 </p> + </item> + <item> + <p> + The default algorithm for the <c>rand</c> module has been + changed to <c>exsss</c> (Xorshift116**) which is a + combination of the Xorshift116 (<c>exsp</c>) state update + and a new scrambler "StarStar" from the 2018 paper + "Scrambled Linear Pseudorandom Number Generators" by + David Blackman and Sebastiano Vigna. This combination + should not have the caveat of weak low bits that the + previous default algorithm(s) have had, with the cost of + about 10% lower speed. See GitHub pull request #1969.</p> + <p> + Own Id: OTP-14731 Aux Id: PR-1969 </p> + </item> + <item> + <p> + The generic state machine behaviour <c>gen_statem</c> has + gotten code cleanup and documentation improvements from + GitHub Pull Request #1855, even though the PR itself was + rejected.</p> + <p> + Own Id: OTP-14737 Aux Id: PR-1855 </p> + </item> + <item> + <p> + Update Unicode specification to version 11.0.</p> + <p> + Own Id: OTP-15111</p> + </item> + <item> + <p> + ETS option <c>write_concurrency</c> now also affects and + improves the scalability of <c>ordered_set</c> tables. + The implementation is based on a data structure called + contention adapting search tree, where the lock + granularity adapts to the actual amount of concurrency + exploited by the applications in runtime.</p> + <p> + Own Id: OTP-15128</p> + </item> + <item> + <p> + Optimized <c>maps:new/0</c> with trivial Erlang + implementation, making use of literal terms (the empty + map) not needing dynamic heap allocation.</p> + <p> + Own Id: OTP-15200 Aux Id: PR-1878 </p> + </item> + <item> + <p>The <c>gen_*</c> behaviours have been changed so that + if logging of the last N messages through + <c>sys:log/2,3</c> is active for the server, this log is + included in the terminate report.</p> <p>To accomplish + this the format of "System Events" as defined in the man + page for <c>sys</c> has been clarified and cleaned up, a + new function <c>sys:get_log/1</c> has been added, and + <c>sys:get_debug/3</c> has been deprecated. Due to these + changes, code that relies on the internal badly + documented format of "System Events", need to be + corrected.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15381</p> + </item> + <item> + <p> + The <c>gen_statem</c> behaviour engine loop has been + optimized for better performance in particular when the + callback module returns some actions, that is better + performance for more realistic applications than the Echo + Benchmark.</p> + <p> + Own Id: OTP-15452</p> + </item> + <item> + <p> Do not allow function specifications for functions + residing in other modules. </p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15563 Aux Id: ERL-845, OTP-15562 </p> + </item> + <item> + <p> + The <c>persistent_term</c> functions <c>put/2</c> and + <c>erase/1</c> are now yielding.</p> + <p> + Own Id: OTP-15615</p> + </item> + <item> + <p>Previously, all ETS tables used centralized counter + variables to keep track of the number of items stored and + the amount of memory consumed. These counters can cause + scalability problems (especially on big NUMA systems). + This change adds an implementation of a decentralized + counter and modifies the implementation of ETS so that + ETS tables of type <c>ordered_set</c> with + <c>write_concurrency</c> enabled use the decentralized + counter. Experiments indicate that this change + substantially improves the scalability of ETS + <c>ordered_set</c> tables with <c>write_concurrency</c> + enabled in scenarios with frequent <c>ets:insert/2</c> + and <c>ets:delete/2</c> calls.</p> + <p> + Own Id: OTP-15623 Aux Id: PR-2190 </p> + </item> + <item> + <p> Use <c>ssh</c> instead of <c>rsh</c> as the default + remote shell. </p> + <p> + Own Id: OTP-15633 Aux Id: PR-1787 </p> + </item> + <item> + <p>Added <c>beam_lib:strip/2</c> and friends, which + accept a list of chunks that should be preserved when + stripping.</p> + <p> + Own Id: OTP-15680 Aux Id: PR-2114 </p> + </item> + <item> + <p> Optimize printing of maps with <c>io_lib:write()</c>. + Also optimize pretty printing of strings (<c>~s</c> and + <c>~ts</c>) when limiting the output with the + <c>chars_limit</c> option. </p> + <p> + Own Id: OTP-15705</p> + </item> + <item> + <p> There are new compiler options <c>nowarn_removed</c> + and <c>{nowarn_removed,Items}</c> to suppress warnings + for functions and modules that have been removed from + OTP.</p> + <p> + Own Id: OTP-15749 Aux Id: ERL-904 </p> + </item> + <item> + <p> Let the Erlang Pretty Printer put atomic parts on the + same line. </p> + <p> + Own Id: OTP-15755</p> + </item> + <item> + <p> Add option <c>quote_singleton_atom_types</c> to the + Erlang Pretty Printer's functions. Setting the option to + <c>true</c> adds quotes to all singleton atom types. </p> + <p> + Own Id: OTP-15756</p> + </item> + </list> + </section> + +</section> + <section><title>STDLIB 3.8.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src index 9cd425db9a..ecb514e9f3 100644 --- a/lib/stdlib/src/stdlib.app.src +++ b/lib/stdlib/src/stdlib.app.src @@ -108,7 +108,7 @@ dets]}, {applications, [kernel]}, {env, []}, - {runtime_dependencies, ["sasl-3.0","kernel-6.0","erts-@OTP-15128@","crypto-3.3", + {runtime_dependencies, ["sasl-3.0","kernel-6.0","erts-10.4","crypto-3.3", "compiler-5.0"]} ]}. diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 9a1b92a87c..7038cc159c 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -19,22 +19,15 @@ %% %% We allow upgrade from, and downgrade to all previous %% versions from the following OTP releases: -%% - OTP 20 %% - OTP 21 +%% - OTP 22 %% %% We also allow upgrade from, and downgrade to all %% versions that have branched off from the above %% stated previous versions. %% {"%VSN%", - [{<<"^3\\.4$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.5(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.5$">>,[restart_new_emulator]}, + [{<<"^3\\.5$">>,[restart_new_emulator]}, {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.6$">>,[restart_new_emulator]}, @@ -44,15 +37,9 @@ {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.8$">>,[restart_new_emulator]}, {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}], - [{<<"^3\\.4$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.5(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.5$">>,[restart_new_emulator]}, + {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^3\\.8\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}], + [{<<"^3\\.5$">>,[restart_new_emulator]}, {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.6$">>,[restart_new_emulator]}, @@ -62,4 +49,5 @@ {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.8$">>,[restart_new_emulator]}, {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}. + {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^3\\.8\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}. diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index 80ec81b832..07224afdc9 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 3.8.2 +STDLIB_VSN = 3.9 diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml index 772f5e6e04..a2dd78f280 100644 --- a/lib/syntax_tools/doc/src/notes.xml +++ b/lib/syntax_tools/doc/src/notes.xml @@ -32,6 +32,34 @@ <p>This document describes the changes made to the Syntax_Tools application.</p> +<section><title>Syntax_Tools 2.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Correct links in the documentation. </p> + <p> + Own Id: OTP-15761</p> + </item> + </list> + </section> + +</section> + <section><title>Syntax_Tools 2.1.7</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk index 538c71dc24..0ace11772d 100644 --- a/lib/syntax_tools/vsn.mk +++ b/lib/syntax_tools/vsn.mk @@ -1 +1 @@ -SYNTAX_TOOLS_VSN = 2.1.7 +SYNTAX_TOOLS_VSN = 2.2 diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index 2191ebe2df..000c6e1ce7 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -31,6 +31,64 @@ </header> <p>This document describes the changes made to the Tools application.</p> +<section><title>Tools 3.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Add <c>cprof</c> and <c>tags</c> modules to .app file so + that they are included in releases.</p> + <p> + Own Id: OTP-15534 Aux Id: PR-2078 </p> + </item> + <item> + <p> + Improved documentation parsing in emacs erldoc + functionality.</p> + <p> + Own Id: OTP-15699 Aux Id: PR-2184 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>The <c>cover</c> tool now uses the <c>counters</c> + module instead of <c>ets</c> for updating the counters + for how many times a line has been executed. By default, + Cover will work with distributed nodes, but a new + function <c>cover:local_only/0</c> allows running the + Cover in a restricted but faster local-only mode.</p> + <p>The increase in speed will vary depending on the type + of code being cover-compiled, but as an example, the + compiler test suite runs more than twice as fast with the + new Cover.</p> + <p> + Own Id: OTP-15575</p> + </item> + </list> + </section> + +</section> + +<section><title>Tools 3.1.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p><c>cover</c> would fail to start if two processes + tried to start it at the exact same time.</p> + <p> + Own Id: OTP-15813 Aux Id: ERL-943 </p> + </item> + </list> + </section> + +</section> + <section><title>Tools 3.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 8fe866cb69..2b3af417b6 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -196,6 +196,8 @@ start() -> receive {?SERVER,started} -> {ok,Pid}; + {?SERVER,{error,Error}} -> + {error,Error}; {'DOWN', Ref, _Type, _Object, Info} -> {error,Info} end, @@ -645,19 +647,31 @@ remote_reply(MainNode,Reply) -> %%%---------------------------------------------------------------------- init_main(Starter) -> - register(?SERVER,self()), - ?COVER_MAPPING_TABLE = ets:new(?COVER_MAPPING_TABLE, - [ordered_set, public, named_table]), - ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public, - named_table]), - ?BINARY_TABLE = ets:new(?BINARY_TABLE, [set, public, named_table]), - ?COLLECTION_TABLE = ets:new(?COLLECTION_TABLE, [set, public, - named_table]), - ?COLLECTION_CLAUSE_TABLE = ets:new(?COLLECTION_CLAUSE_TABLE, [set, public, - named_table]), - ok = net_kernel:monitor_nodes(true), - Starter ! {?SERVER,started}, - main_process_loop(#main_state{}). + try register(?SERVER,self()) of + true -> + ?COVER_MAPPING_TABLE = ets:new(?COVER_MAPPING_TABLE, + [ordered_set, public, named_table]), + ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public, + named_table]), + ?BINARY_TABLE = ets:new(?BINARY_TABLE, [set, public, named_table]), + ?COLLECTION_TABLE = ets:new(?COLLECTION_TABLE, [set, public, + named_table]), + ?COLLECTION_CLAUSE_TABLE = ets:new(?COLLECTION_CLAUSE_TABLE, + [set, public, named_table]), + ok = net_kernel:monitor_nodes(true), + Starter ! {?SERVER,started}, + main_process_loop(#main_state{}) + catch + error:badarg -> + %% The server's already registered; either report that it's already + %% started or try again if it died before we could find its pid. + case whereis(?SERVER) of + undefined -> + init_main(Starter); + Pid -> + Starter ! {?SERVER, {error, {already_started, Pid}}} + end + end. main_process_loop(State) -> receive diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl index ee58fd7a10..462767f430 100644 --- a/lib/tools/test/cover_SUITE.erl +++ b/lib/tools/test/cover_SUITE.erl @@ -37,7 +37,7 @@ all() -> dont_reconnect_after_stop, stop_node_after_disconnect, export_import, otp_5031, otp_6115, otp_8270, otp_10979_hanging_node, otp_14817, - local_only], + local_only, startup_race], case whereis(cover_server) of undefined -> [coverage,StartStop ++ NoStartStop]; @@ -1775,7 +1775,32 @@ local_only(Config) -> {ok,Name} = test_server:start_node(?FUNCTION_NAME, slave, []), {error,local_only} = cover:start([Name]), test_server:stop_node(Name), + ok. +%% ERL-943; We should not crash on startup when multiple servers race to +%% register the server name. +startup_race(Config) when is_list(Config) -> + PidRefs = [spawn_monitor(fun() -> + case cover:start() of + {error, {already_started, _Pid}} -> + ok; + {ok, _Pid} -> + ok + end + end) || _<- lists:seq(1,8)], + startup_race_1(PidRefs). + +startup_race_1([{Pid, Ref} | PidRefs]) -> + receive + {'DOWN', Ref, process, Pid, normal} -> + startup_race_1(PidRefs); + {'DOWN', Ref, process, Pid, _Other} -> + ct:fail("Cover server crashed on startup.") + after 5000 -> + ct:fail("Timed out.") + end; +startup_race_1([]) -> + cover:stop(), ok. %%--Auxiliary------------------------------------------------------------ diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index 5700885549..191a458c62 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1 +1 @@ -TOOLS_VSN = 3.1 +TOOLS_VSN = 3.2 diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml index 33d02e22ba..0c3374091d 100644 --- a/lib/wx/doc/src/notes.xml +++ b/lib/wx/doc/src/notes.xml @@ -32,6 +32,23 @@ <p>This document describes the changes made to the wxErlang application.</p> +<section><title>Wx 1.8.8</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + <section><title>Wx 1.8.7</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk index dac219fa98..91d15de3a9 100644 --- a/lib/wx/vsn.mk +++ b/lib/wx/vsn.mk @@ -1 +1 @@ -WX_VSN = 1.8.7 +WX_VSN = 1.8.8 diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml index d6b6dfdfb5..9fb4a430e5 100644 --- a/lib/xmerl/doc/src/notes.xml +++ b/lib/xmerl/doc/src/notes.xml @@ -32,6 +32,38 @@ <p>This document describes the changes made to the Xmerl application.</p> +<section><title>Xmerl 1.3.21</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A typo in an error printout has been fixed.</p> + <p> + Own Id: OTP-14703 Aux Id: PR-1964 </p> + </item> + </list> + </section> + +</section> + +<section><title>Xmerl 1.3.20.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + <c>xmerl_sax_parser</c> crashed during charset detection + when the xml declarations attribute values was missing + the closing quotation (' or ").</p> + <p> + Own Id: OTP-15826</p> + </item> + </list> + </section> + +</section> + <section><title>Xmerl 1.3.20</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/xmerl/src/xmerl_sax_parser.erl b/lib/xmerl/src/xmerl_sax_parser.erl index fe836fd8cd..2767d02552 100644 --- a/lib/xmerl/src/xmerl_sax_parser.erl +++ b/lib/xmerl/src/xmerl_sax_parser.erl @@ -369,8 +369,8 @@ parse_eq(_, State) -> %%---------------------------------------------------------------------- parse_value(<<C, Rest/binary>>, State) when ?is_whitespace(C) -> parse_value(Rest, State); -parse_value(<<C, Rest/binary>>, _State) when C == $'; C == $" -> - parse_value_1(Rest, C, []); +parse_value(<<C, Rest/binary>>, State) when C == $'; C == $" -> + parse_value_1(Rest, C, [], State); parse_value(_, State) -> ?fatal_error(State, "\', \" or whitespace expected"). @@ -383,10 +383,12 @@ parse_value(_, State) -> %% Rest = binary() %% Description: Parsing an attribute value from the stream. %%---------------------------------------------------------------------- -parse_value_1(<<Stop, Rest/binary>>, Stop, Acc) -> +parse_value_1(<<Stop, Rest/binary>>, Stop, Acc, _State) -> {lists:reverse(Acc), Rest}; -parse_value_1(<<C, Rest/binary>>, Stop, Acc) -> - parse_value_1(Rest, Stop, [C |Acc]). +parse_value_1(<<C, Rest/binary>>, Stop, Acc, State) -> + parse_value_1(Rest, Stop, [C |Acc], State); +parse_value_1(_, _Stop, _Acc, State) -> + ?fatal_error(State, "end of input and no \' or \" found"). %%====================================================================== %% Default functions diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk index 31ffa6e749..08696606e6 100644 --- a/lib/xmerl/vsn.mk +++ b/lib/xmerl/vsn.mk @@ -1 +1 @@ -XMERL_VSN = 1.3.20 +XMERL_VSN = 1.3.21 |
