diff options
30 files changed, 266 insertions, 194 deletions
diff --git a/.gitignore b/.gitignore index 5804e36f9c..a3e03dc46f 100644 --- a/.gitignore +++ b/.gitignore @@ -155,6 +155,7 @@ JAVADOC-GENERATED /lib/*/doc/html/*.css /lib/*/doc/html/js /lib/*/doc/html/*.gif +/lib/*/doc/html/*.jpg /lib/*/doc/html/*.png /lib/*/doc/html/*.eix /lib/*/doc/man[0-9]/*.[0-9] @@ -212,7 +213,7 @@ JAVADOC-GENERATED # debugger -/lib/debugger/doc/html/images/*.gif +/lib/debugger/doc/html/images/*.jpg # edoc @@ -224,6 +225,7 @@ JAVADOC-GENERATED /erts/info /erts/doc/html/*.html /erts/doc/html/*.gif +/erts/doc/html/*.jpg /erts/doc/html/*.eix /erts/doc/pdf/*.fo /erts/doc/pdf/*.pdf @@ -329,6 +331,7 @@ JAVADOC-GENERATED /system/doc/html/js /system/doc/html/*/*.html /system/doc/html/*/*.gif +/system/doc/html/*/*.jpg /system/doc/html/*/*.eix /system/doc/top/PR.template /system/doc/top/erlresolvelinks.js diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex aee6f631cf..7903f01f76 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex ea80d47eb6..29fb8aaebf 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam Binary files differindex 6b2593e427..c907ead38a 100644 --- a/erts/preloaded/ebin/erts_internal.beam +++ b/erts/preloaded/ebin/erts_internal.beam diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam Binary files differindex 7fe1685ef3..c2bd80df1a 100644 --- a/erts/preloaded/ebin/init.beam +++ b/erts/preloaded/ebin/init.beam diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam Binary files differindex 57dafb9ce7..226e5a4134 100644 --- a/erts/preloaded/ebin/otp_ring0.beam +++ b/erts/preloaded/ebin/otp_ring0.beam diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex 7558a713ae..67e62e53f1 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex f836473cb4..7b9da42e4f 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam Binary files differindex 35acb59096..589f45e75e 100644 --- a/erts/preloaded/ebin/prim_zip.beam +++ b/erts/preloaded/ebin/prim_zip.beam diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex c100d1755b..72d1090a52 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index a88a8831ea..fefe0f21e0 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -1785,7 +1785,7 @@ process_flag(_Flag, _Value) -> links | last_calls | memory | - message_que_len | + message_queue_len | messages | min_heap_size | min_bin_vheap_size | @@ -1824,7 +1824,7 @@ process_flag(_Flag, _Value) -> {links, PidsAndPorts :: [pid() | port()]} | {last_calls, false | (Calls :: [mfa()])} | {memory, Size :: non_neg_integer()} | - {message_que_len, MessageQueueLen :: non_neg_integer()} | + {message_queue_len, MessageQueueLen :: non_neg_integer()} | {messages, MessageQueue :: [term()]} | {min_heap_size, MinHeapSize :: non_neg_integer()} | {min_bin_vheap_size, MinBinVHeapSize :: non_neg_integer()} | diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index 0b204a681a..752033fdff 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -639,20 +639,21 @@ logger_loop(State) -> case erlang:is_process_alive(TCGL) of true -> State1 = print_to_log(SyncOrAsync, Pid, + Category, TCGL, List, State), logger_loop(State1#logger_state{ tc_groupleaders = TCGLs}); false -> %% Group leader is dead, so write to the - %% CtLog instead - Fd = State#logger_state.ct_log_fd, - [begin io:format(Fd,Str,Args), - io:nl(Fd) end || {Str,Args} <- List], + %% CtLog or unexpected_io log instead + unexpected_io(Pid,Category,List,State), logger_loop(State) end; - {ct_log,Fd,TCGLs} -> - [begin io:format(Fd,Str,Args),io:nl(Fd) end || - {Str,Args} <- List], + {ct_log,_Fd,TCGLs} -> + %% If category is ct_internal then write + %% to ct_log, else write to unexpected_io + %% log + unexpected_io(Pid,Category,List,State), logger_loop(State#logger_state{ tc_groupleaders = TCGLs}) end; @@ -746,27 +747,32 @@ create_io_fun(FromPid, State) -> end end. -print_to_log(sync, FromPid, TCGL, List, State) -> - IoFun = create_io_fun(FromPid, State), +print_to_log(sync, FromPid, Category, TCGL, List, State) -> %% in some situations (exceptions), the printout is made from the %% test server IO process and there's no valid group leader to send to - IoProc = if FromPid /= TCGL -> TCGL; - true -> State#logger_state.ct_log_fd - end, - io:format(IoProc, "~ts", [lists:foldl(IoFun, [], List)]), + if FromPid /= TCGL -> + IoFun = create_io_fun(FromPid, State), + io:format(TCGL,"~ts", [lists:foldl(IoFun, [], List)]); + true -> + unexpected_io(FromPid,Category,List,State) + end, State; -print_to_log(async, FromPid, TCGL, List, State) -> - IoFun = create_io_fun(FromPid, State), +print_to_log(async, FromPid, Category, TCGL, List, State) -> %% in some situations (exceptions), the printout is made from the %% test server IO process and there's no valid group leader to send to - IoProc = if FromPid /= TCGL -> TCGL; - true -> State#logger_state.ct_log_fd - end, - Printer = fun() -> - test_server:permit_io(IoProc, self()), - io:format(IoProc, "~ts", [lists:foldl(IoFun, [], List)]) - end, + Printer = + if FromPid /= TCGL -> + IoFun = create_io_fun(FromPid, State), + fun() -> + test_server:permit_io(TCGL, self()), + io:format(TCGL, "~ts", [lists:foldl(IoFun, [], List)]) + end; + true -> + fun() -> + unexpected_io(FromPid,Category,List,State) + end + end, case State#logger_state.async_print_jobs of [] -> {_Pid,Ref} = spawn_monitor(Printer), @@ -2514,3 +2520,11 @@ html_encoding(latin1) -> "iso-8859-1"; html_encoding(utf8) -> "utf-8". + +unexpected_io(Pid,ct_internal,List,#logger_state{ct_log_fd=Fd}=State) -> + IoFun = create_io_fun(Pid,State), + io:format(Fd, "~ts", [lists:foldl(IoFun, [], List)]); +unexpected_io(Pid,_Category,List,State) -> + IoFun = create_io_fun(Pid,State), + Data = io_lib:format("~ts", [lists:foldl(IoFun, [], List)]), + test_server_io:print_unexpected(Data). diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl index 02186864a5..beb3c1d649 100644 --- a/lib/common_test/src/ct_telnet.erl +++ b/lib/common_test/src/ct_telnet.erl @@ -728,7 +728,8 @@ teln_get_all_data(Pid,Prx,Data,Acc,LastLine) -> haltpatterns=[], seq=false, repeat=false, - found_prompt=false}). + found_prompt=false, + wait_for_linebreak=true}). %% @hidden %% @doc Externally the silent_teln_expect function shall only be used @@ -754,20 +755,25 @@ silent_teln_expect(Pid,Data,Pattern,Prx,Opts) -> %% condition is fullfilled. %% 3b) Repeat (sequence): 2) is repeated either N times or until a %% halt condition is fullfilled. -teln_expect(Pid,Data,Pattern0,Prx,Opts) -> HaltPatterns = case - get_ignore_prompt(Opts) of true -> get_haltpatterns(Opts); false - -> [prompt | get_haltpatterns(Opts)] end, - +teln_expect(Pid,Data,Pattern0,Prx,Opts) -> + HaltPatterns = case get_ignore_prompt(Opts) of + true -> + get_haltpatterns(Opts); + false -> + [prompt | get_haltpatterns(Opts)] + end, + WaitForLineBreak = get_line_break_opt(Opts), Seq = get_seq(Opts), Pattern = convert_pattern(Pattern0,Seq), - + Timeout = get_timeout(Opts), - + EO = #eo{teln_pid=Pid, prx=Prx, timeout=Timeout, seq=Seq, - haltpatterns=HaltPatterns}, + haltpatterns=HaltPatterns, + wait_for_linebreak=WaitForLineBreak}, case get_repeat(Opts) of false -> @@ -808,6 +814,11 @@ get_timeout(Opts) -> {value,{timeout,T}} -> T; false -> ?DEFAULT_TIMEOUT end. +get_line_break_opt(Opts) -> + case lists:keysearch(wait_for_linebreak,1,Opts) of + {value,{wait_for_linebreak,false}} -> false; + _ -> true + end. get_repeat(Opts) -> case lists:keysearch(repeat,1,Opts) of {value,{repeat,N}} when is_integer(N) -> @@ -1004,8 +1015,9 @@ seq_expect1(Data,[],Acc,Rest,_EO) -> %% Split prompt-chunk at lines match_lines(Data,Patterns,EO) -> FoundPrompt = EO#eo.found_prompt, + NeedLineBreak = EO#eo.wait_for_linebreak, case one_line(Data,[]) of - {noline,Rest} when FoundPrompt=/=false -> + {noline,Rest} when FoundPrompt=/=false, NeedLineBreak =:= true -> %% This is the line including the prompt case match_line(Rest,Patterns,FoundPrompt,EO) of nomatch -> @@ -1013,7 +1025,14 @@ match_lines(Data,Patterns,EO) -> {Tag,Match} -> {Tag,Match,[]} end; - {noline,Rest} -> + {noline,Rest} when NeedLineBreak =:= false -> + case match_line(Rest,Patterns,FoundPrompt,EO) of + nomatch -> + {nomatch,prompt}; + {Tag,Match} -> + {Tag,Match,[]} + end; + {noline, Rest} -> {nomatch,Rest}; {Line,Rest} -> case match_line(Line,Patterns,false,EO) of diff --git a/lib/common_test/test/ct_group_leader_SUITE.erl b/lib/common_test/test/ct_group_leader_SUITE.erl index cde3061d6a..6d54a4c004 100644 --- a/lib/common_test/test/ct_group_leader_SUITE.erl +++ b/lib/common_test/test/ct_group_leader_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -176,6 +176,10 @@ events_to_check(_Test) -> {?eh,tc_done,{group_leader_SUITE,cap1,ok}}, {?eh,tc_start,{group_leader_SUITE,cap2}}, {?eh,tc_done,{group_leader_SUITE,cap2,ok}}]}, + {parallel,[{?eh,tc_start,{group_leader_SUITE,unexp1}}, + {?eh,tc_done,{group_leader_SUITE,unexp1,ok}}, + {?eh,tc_start,{group_leader_SUITE,unexp2}}, + {?eh,tc_done,{group_leader_SUITE,unexp2,ok}}]}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} ]. diff --git a/lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl b/lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl index 3f1844b4ae..804f722081 100644 --- a/lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl +++ b/lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012. All Rights Reserved. +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -112,7 +112,8 @@ groups() -> {seq,[],[s1,s2,s3]}, {seq2,[],[s4,s5]}, {seq_in_par,[parallel],[p10,p11,{group,seq},p12,{group,seq2},p13]}, - {capture_io,[parallel],[cap1,cap2]}]. + {capture_io,[parallel],[cap1,cap2]}, + {unexpected_io,[parallel],[unexp1,unexp2]}]. %%-------------------------------------------------------------------- %% @spec all() -> GroupsAndTestCases | {skip,Reason} @@ -126,7 +127,8 @@ all() -> [tc1,{group,p},{group,p_restart},p3, {group,seq_in_par}, cap1,cap2, - {group,capture_io}]. + {group,capture_io}, + {group,unexpected_io}]. tc1(_C) -> ok. @@ -250,3 +252,36 @@ gen_io(Label, N, Acc) -> S = lists:flatten(io_lib:format("~s: ~p\n", [Label,N])), io:put_chars(S), gen_io(Label, N-1, [S|Acc]). + +%% Test that unexpected I/O is sent to test_server's unexpeced_io log. +%% To trigger this, run two test cases in parallel and send a printout +%% (via ct logging functions) from an external process which has a +%% different group leader than the test cases. +unexp1(Config) -> + timer:sleep(1000), + gen_unexp_io(), + timer:sleep(1000), + check_unexp_io(Config), + ok. + +unexp2(_) -> + timer:sleep(2000), + ok. + +gen_unexp_io() -> + spawn(fun() -> + group_leader(whereis(user),self()), + ct:log("-x- Unexpected io ct:log -x-",[]), + ct:pal("-x- Unexpected io ct:pal -x-",[]), + ok + end). + +check_unexp_io(Config) -> + SuiteLog = ?config(tc_logfile,Config), + Dir = filename:dirname(SuiteLog), + UnexpLog = filename:join(Dir,"unexpected_io.log.html"), + {ok,SuiteBin} = file:read_file(SuiteLog), + nomatch = re:run(SuiteBin,"-x- Unexpected io ",[global,{capture,none}]), + {ok,UnexpBin} = file:read_file(UnexpLog), + {match,[_,_]} = re:run(UnexpBin,"-x- Unexpected io ",[global]), + ok. diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index ca6b403ac9..affb89385e 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -255,10 +255,13 @@ compile_and_store(Files, #analysis_state{codeserver = CServer, CServer2 = dialyzer_codeserver:set_next_core_label(NextLabel, CServer), case Failed =:= [] of true -> - NewFiles = lists:zip(lists:reverse(Modules), Files), ModDict = - lists:foldl(fun({Mod, F}, Dict) -> dict:append(Mod, F, Dict) end, - dict:new(), NewFiles), + lists:foldl(fun(F, Dict) -> + ModFile = lists:last(filename:split(F)), + Mod = filename:basename(ModFile, ".beam"), + dict:append(Mod, F, Dict) + end, + dict:new(), Files), check_for_duplicate_modules(ModDict); false -> Msg = io_lib:format("Could not scan the following file(s):~n~s", diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index 2456585bd0..365c0b36d4 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -509,7 +509,7 @@ hipe_compile(Files, #options{erlang_mode = ErlangMode} = Options) -> dialyzer_codeserver, dialyzer_contracts, dialyzer_coordinator, dialyzer_dataflow, dialyzer_dep, dialyzer_plt, dialyzer_succ_typings, dialyzer_typesig, - dialyzer_typesig, dialyzer_worker], + dialyzer_worker], report_native_comp(Options), {T1, _} = statistics(wall_clock), native_compile(Mods), diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 17a292a7d6..a418a11e65 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -246,18 +246,27 @@ traverse(Tree, DefinedVars, State) -> Val = cerl:bitstr_val(Tree), {State1, [SizeType, ValType]} = traverse_list([Size, Val], DefinedVars, State), - {State2, TypeConstr} = + {State2, TypeConstr, BinValTypeConstr} = case cerl:bitstr_bitsize(Tree) of - all -> {State1, t_bitstr(UnitVal, 0)}; - utf -> {State1, t_binary()}; % contains an integer number of bytes - N when is_integer(N) -> {State1, t_bitstr(0, N)}; + all -> + T = t_bitstr(UnitVal, 0), + {State1, T, T}; + utf -> + %% contains an integer number of bytes + T = t_binary(), + {State1, T, T}; + N when is_integer(N) -> + {State1, t_bitstr(0, N), t_bitstr(1, N)}; any -> % Size is not a literal + T1 = ?mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType]), + T2 = + ?mk_fun_var(bitstr_constr(SizeType, UnitVal, match), [SizeType]), {state__store_conj(SizeType, sub, t_non_neg_integer(), State1), - ?mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType])} + T1, T2} end, ValTypeConstr = case cerl:concrete(cerl:bitstr_type(Tree)) of - binary -> TypeConstr; + binary -> BinValTypeConstr; float -> case state__is_in_match(State1) of true -> t_float(); @@ -947,12 +956,20 @@ get_type_test({erlang, is_tuple, 1}) -> {ok, t_tuple()}; get_type_test({M, F, A}) when is_atom(M), is_atom(F), is_integer(A) -> error. bitstr_constr(SizeType, UnitVal) -> + bitstr_constr(SizeType, UnitVal, construct). + +bitstr_constr(SizeType, UnitVal, ConstructOrMatch) -> + Unit = + case ConstructOrMatch of + construct -> 0; + match -> 1 + end, fun(Map) -> TmpSizeType = lookup_type(SizeType, Map), case t_is_subtype(TmpSizeType, t_non_neg_integer()) of true -> case t_number_vals(TmpSizeType) of - [OneSize] -> t_bitstr(0, OneSize * UnitVal); + [OneSize] -> t_bitstr(Unit, OneSize * UnitVal); _ -> MinSize = erl_types:number_min(TmpSizeType), t_bitstr(UnitVal, MinSize * UnitVal) @@ -1770,8 +1787,9 @@ minimize_state(#state{ opaques = Opaques, solvers = Solvers }) -> - ETSCMap = ets:new(cmap,[{read_concurrency, true}]), - ETSPropTypes = ets:new(prop_types,[{read_concurrency, true}]), + Opts = [{read_concurrency, true}], + ETSCMap = ets:new(cmap, Opts), + ETSPropTypes = ets:new(prop_types, Opts), true = ets:insert(ETSCMap, dict:to_list(CMap)), true = ets:insert(ETSPropTypes, dict:to_list(PropTypes)), #state @@ -2111,11 +2129,11 @@ restore_local_map(#v2_state{constr_data = ConData}, Id, Map0) -> {ok, failed} -> Map0; {ok, {[],_}} -> Map0; {ok, {Part0,U}} -> - Part = [{K,V} || {K,V} <- Part0, not lists:member(K, U)], + Part = [KV || {K,_V} = KV <- Part0, not lists:member(K, U)], ?debug("restore local map Id=~w U=~w\n", [Id, U]), pp_map("Part", dict:from_list(Part)), pp_map("Map0", Map0), - Map = lists:foldl(fun({K,V}, D) -> dict:store(K, V, D)end, Map0, Part), + Map = lists:foldl(fun({K,V}, D) -> dict:store(K, V, D) end, Map0, Part), pp_map("Map", Map), Map end. @@ -3374,16 +3392,6 @@ pp_constraints([#constraint{}=C], Level, MaxDepth, _State) -> pp_constraints([#constraint{}=C|Tail], Level, MaxDepth, State) -> pp_op(C, Level), pp_constraints(Tail, Level, MaxDepth, State); -pp_constraints([#constraint_list{type = Type, list = List, id = Id}], - Level, MaxDepth, State) -> - pp_indent(Level), - case Type of - conj -> io:format("Conj ~w (", [Id]); - disj -> io:format("Disj ~w (", [Id]) - end, - NewMaxDepth = pp_constraints(List, Level + 1, MaxDepth, State), - io:format(")", []), - NewMaxDepth; pp_constraints([#constraint_list{type = Type, list = List, id = Id}|Tail], Level, MaxDepth, State) -> pp_indent(Level), @@ -3392,8 +3400,11 @@ pp_constraints([#constraint_list{type = Type, list = List, id = Id}|Tail], disj -> io:format("Disj ~w (", [Id]) end, NewMaxDepth = pp_constraints(List, Level+1, MaxDepth, State), - io:format(")", []), - pp_constraints(Tail, Level, NewMaxDepth, State). + io:format(")"), + case Tail =:= [] of + true -> NewMaxDepth + 1; + false -> pp_constraints(Tail, Level, NewMaxDepth, State) + end. pp_op(#constraint{lhs = Lhs, op = Op, rhs = Rhs}, Level) -> pp_indent(Level), diff --git a/lib/dialyzer/test/small_SUITE_data/src/bs_constraints.erl b/lib/dialyzer/test/small_SUITE_data/src/bs_constraints.erl new file mode 100644 index 0000000000..08dfb0808d --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/bs_constraints.erl @@ -0,0 +1,32 @@ +%% Program which shows that the handling of binaries was not correct. +%% The success typing inferred was: +%% -spec bits1(<<_:3>>) -> <<_:3>>. +%% while it should be: +%% -spec bits1(<<_:3,_:_*1>>) -> <<_:3>>. +%% because the only constraint which exists for the head variable is +%% that it must be a bitstring of bit size at least 3, not a bitstring +%% of bit size 3. +-module(bs_constraints). + +-export([bits1/1, bits2/1, bits3/1, bins/1, test/0]). + +bits1(B) -> + <<B:3/bits>>. + +bits2(B) -> + <<B:4/bits>>. + +bits3(B) -> + {bits1(B), bits2(B)}. + +%% Same problem with the one below. The success typing should be: +%% -spec bins(<<_:16,_:_*1>>) -> <<_:16>>. +bins(B) -> + <<B:2/binary>>. + +%% Same problem, when unit size is a variable: +test() -> + foo(8, 0, <<42>>). + +foo(N, S, A) -> + <<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>. diff --git a/lib/hipe/icode/hipe_icode_coordinator.erl b/lib/hipe/icode/hipe_icode_coordinator.erl index d8c82cf01c..79e3304e6f 100644 --- a/lib/hipe/icode/hipe_icode_coordinator.erl +++ b/lib/hipe/icode/hipe_icode_coordinator.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -36,18 +36,16 @@ %%--------------------------------------------------------------------- --spec coordinate(hipe_digraph:hdg(), [{mfa(),boolean()}], [mfa()], module()) -> +-spec coordinate(hipe_digraph:hdg(), [mfa()], [mfa()], module()) -> no_return(). coordinate(CG, Escaping, NonEscaping, Mod) -> ServerPid = initialize_server(Escaping, Mod), - Clean = [MFA || {MFA, _} <- Escaping], - All = NonEscaping ++ Clean, - Restart = - fun (MFALists, PM) -> restart_funs(MFALists, PM, All, ServerPid) end, - LastAction = - fun (PM) -> last_action(PM, ServerPid, Mod, All) end, - coordinate({Clean,All}, CG, gb_trees:empty(), Restart, LastAction, ServerPid). + All = ordsets:from_list(Escaping ++ NonEscaping), + Restart = fun (MFALs, PM) -> restart_funs(MFALs, PM, All, ServerPid) end, + LastAction = fun (PM) -> last_action(PM, ServerPid, Mod, All) end, + MFALists = {Escaping, All}, + coordinate(MFALists, CG, gb_trees:empty(), Restart, LastAction, ServerPid). -type mfalists() :: {[mfa()], [mfa()]}. @@ -129,7 +127,7 @@ restart_funs({Queue, Busy} = QB, PM, All, ServerPid) -> initialize_server(Escaping, Mod) -> Pid = spawn_link(fun () -> info_server(Mod) end), - lists:foreach(fun ({MFA, _}) -> Pid ! {set_escaping, MFA} end, Escaping), + lists:foreach(fun (MFA) -> Pid ! {set_escaping, MFA} end, Escaping), Pid. safe_get_args(MFA, Cfg, Pid, Mod) -> diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index 6e00b13292..434d5c3061 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2012. All Rights Reserved. +%% Copyright Ericsson AB 2001-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -242,8 +242,7 @@ %% %% @see load/2 --spec load(Mod) -> {'module', Mod} | {'error', term()} - when is_subtype(Mod, mod()). +-spec load(Mod) -> {'module', Mod} | {'error', term()} when Mod :: mod(). load(Mod) -> load(Mod, beam_file(Mod)). @@ -265,7 +264,7 @@ load(Mod) -> %% @see load/1 -spec load(Mod, string()) -> {'module', Mod} | {'error', term()} - when is_subtype(Mod, mod()). + when Mod :: mod(). load(Mod, BeamFileName) when is_list(BeamFileName) -> Architecture = erlang:system_info(hipe_architecture), @@ -522,7 +521,7 @@ compile(Name, Core, File, Opts) when is_atom(Name) -> %% @equiv file(File, []) -spec file(Mod) -> {'ok', Mod, compile_ret()} | {'error', term()} - when is_subtype(Mod, mod()). + when Mod :: mod(). file(File) -> file(File, []). @@ -542,7 +541,7 @@ file(File) -> -spec file(Mod, comp_options()) -> {'ok', Mod, compile_ret()} | {'error', term()} - when is_subtype(Mod, mod()). + when Mod :: mod(). file(File, Options) when is_atom(File) -> case beam_lib:info(File) of L when is_list(L) -> @@ -760,13 +759,15 @@ finalize_fun_concurrent(MfaIcodeList, Exports, Opts) -> case MfaIcodeList of [{{M,_,_},_}|_] -> CallGraph = hipe_icode_callgraph:construct_callgraph(MfaIcodeList), - Closures = [{MFA, true} || {MFA, Icode} <- MfaIcodeList, - hipe_icode:icode_is_closure(Icode)], - Exported = [{{M, F, A}, false} || {F, A} <- Exports], + Exported = [{M, F, A} || {F, A} <- Exports], + Closures = [MFA || {MFA, Icode} <- MfaIcodeList, + hipe_icode:icode_is_closure(Icode)], + %% In principle, a function could both be exported and used as a + %% closure so make sure to add it only once in Escaping below + Escaping = ordsets:from_list(Exported ++ Closures), NonEscaping = [MFA || {{_M, F, A} = MFA, Icode} <- MfaIcodeList, not lists:member({F, A}, Exports), not hipe_icode:icode_is_closure(Icode)], - Escaping = Closures ++ Exported, TypeServerFun = fun() -> hipe_icode_coordinator:coordinate(CallGraph, Escaping, diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml index a177b80739..0ffc5bc433 100644 --- a/lib/stdlib/doc/src/sys.xml +++ b/lib/stdlib/doc/src/sys.xml @@ -234,8 +234,8 @@ <p>These functions are intended only to help with debugging. They are provided for convenience, allowing developers to avoid having to create their own state extraction functions and also avoid having to interactively extract state from the return values of - <c><seealso marker="get_status/1">get_status/1</seealso></c> or - <c><seealso marker="get_status/2">get_status/2</seealso></c> while debugging.</p> + <c><seealso marker="#get_status-1">get_status/1</seealso></c> or + <c><seealso marker="#get_status-2">get_status/2</seealso></c> while debugging.</p> </note> <p>The value of <c><anno>State</anno></c> varies for different types of processes. For a <c>gen_server</c> process, the returned <c><anno>State</anno></c> @@ -247,8 +247,8 @@ <c>Id</c> is the handler's ID (which is the value <c>false</c> if it was registered without an ID), and <c>HandlerState</c> is the handler's state.</p> <p>To obtain more information about a process, including its state, see - <seealso marker="get_status/1">get_status/1</seealso> and - <seealso marker="get_status/2">get_status/2</seealso>.</p> + <seealso marker="#get_status-1">get_status/1</seealso> and + <seealso marker="#get_status-2">get_status/2</seealso>.</p> </desc> </func> <func> diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl index 42555aedd7..5df5530ba1 100644 --- a/lib/stdlib/src/gen.erl +++ b/lib/stdlib/src/gen.erl @@ -17,6 +17,7 @@ %% %CopyrightEnd% %% -module(gen). +-compile({inline,[get_node/1]}). %%%----------------------------------------------------------------- %%% This module implements the really generic stuff of the generic @@ -194,16 +195,6 @@ call({_Name, Node}=Process, Label, Request, Timeout) end. do_call(Process, Label, Request, Timeout) -> - %% We trust the arguments to be correct, i.e - %% Process is either a local or remote pid, - %% or a {Name, Node} tuple (of atoms) and in this - %% case this node (node()) _is_ distributed and Node =/= node(). - Node = case Process of - {_S, N} when is_atom(N) -> - N; - _ when is_pid(Process) -> - node(Process) - end, try erlang:monitor(process, Process) of Mref -> %% If the monitor/2 call failed to set up a connection to a @@ -222,15 +213,12 @@ do_call(Process, Label, Request, Timeout) -> erlang:demonitor(Mref, [flush]), {ok, Reply}; {'DOWN', Mref, _, _, noconnection} -> + Node = get_node(Process), exit({nodedown, Node}); {'DOWN', Mref, _, _, Reason} -> exit(Reason) after Timeout -> - erlang:demonitor(Mref), - receive - {'DOWN', Mref, _, _, _} -> true - after 0 -> true - end, + erlang:demonitor(Mref, [flush]), exit(timeout) end catch @@ -241,6 +229,7 @@ do_call(Process, Label, Request, Timeout) -> %% Do the best possible with monitor_node/2. %% This code may hang indefinitely if the Process %% does not exist. It is only used for featureweak remote nodes. + Node = get_node(Process), monitor_node(Node, true), receive {nodedown, Node} -> @@ -253,6 +242,18 @@ do_call(Process, Label, Request, Timeout) -> end end. +get_node(Process) -> + %% We trust the arguments to be correct, i.e + %% Process is either a local or remote pid, + %% or a {Name, Node} tuple (of atoms) and in this + %% case this node (node()) _is_ distributed and Node =/= node(). + case Process of + {_S, N} when is_atom(N) -> + N; + _ when is_pid(Process) -> + node(Process) + end. + wait_resp(Node, Tag, Timeout) -> receive {Tag, Reply} -> diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl index 065b74ad41..8ff7c3ccc9 100644 --- a/lib/stdlib/test/dets_SUITE.erl +++ b/lib/stdlib/test/dets_SUITE.erl @@ -33,8 +33,6 @@ -define(datadir(Conf), ?config(data_dir, Conf)). -endif. --compile(r13). % OTP-9607 - -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, newly_started/1, basic_v8/1, basic_v9/1, @@ -54,7 +52,7 @@ simultaneous_open/1, insert_new/1, repair_continuation/1, otp_5487/1, otp_6206/1, otp_6359/1, otp_4738/1, otp_7146/1, otp_8070/1, otp_8856/1, otp_8898/1, otp_8899/1, otp_8903/1, - otp_8923/1, otp_9282/1, otp_9607/1]). + otp_8923/1, otp_9282/1]). -export([dets_dirty_loop/0]). @@ -111,7 +109,7 @@ all() -> many_clients, otp_4906, otp_5402, simultaneous_open, insert_new, repair_continuation, otp_5487, otp_6206, otp_6359, otp_4738, otp_7146, otp_8070, otp_8856, otp_8898, - otp_8899, otp_8903, otp_8923, otp_9282, otp_9607 + otp_8899, otp_8903, otp_8923, otp_9282 ]. groups() -> @@ -3899,77 +3897,6 @@ some_calls(Tab, Config) -> ok = dets:close(T), file:delete(File). -otp_9607(doc) -> - ["OTP-9607. Test downgrading the slightly changed format."]; -otp_9607(suite) -> - []; -otp_9607(Config) when is_list(Config) -> - %% Note: the bug is about almost full tables. The fix of that - %% problem is *not* tested here. - Version = r13b, - case ?t:is_release_available(atom_to_list(Version)) of - true -> - T = otp_9607, - File = filename(T, Config), - Key = a, - Value = 1, - Args = [{file,File}], - {ok, T} = dets:open_file(T, Args), - ok = dets:insert(T, {Key, Value}), - ok = dets:close(T), - - Call = fun(P, A) -> - P ! {self(), A}, - receive - {P, Ans} -> - Ans - after 5000 -> - exit(other_process_dead) - end - end, - %% Create a file on the modified format, read the file - %% with an emulator that doesn't know about the modified - %% format. - {ok, Node} = start_node_rel(Version, Version, slave), - Pid = rpc:call(Node, erlang, spawn, - [?MODULE, dets_dirty_loop, []]), - {error,{needs_repair, File}} = - Call(Pid, [open, T, Args++[{repair,false}]]), - io:format("Expect repair:~n"), - {ok, T} = Call(Pid, [open, T, Args]), - [{Key,Value}] = Call(Pid, [read, T, Key]), - ok = Call(Pid, [close, T]), - file:delete(File), - - %% Create a file on the unmodified format. Modify the file - %% using an emulator that must not turn the file into the - %% modified format. Read the file and make sure it is not - %% repaired. - {ok, T} = Call(Pid, [open, T, Args]), - ok = Call(Pid, [write, T, {Key,Value}]), - [{Key,Value}] = Call(Pid, [read, T, Key]), - ok = Call(Pid, [close, T]), - - Key2 = b, - Value2 = 2, - - {ok, T} = dets:open_file(T, Args), - [{Key,Value}] = dets:lookup(T, Key), - ok = dets:insert(T, {Key2,Value2}), - ok = dets:close(T), - - {ok, T} = Call(Pid, [open, T, Args++[{repair,false}]]), - [{Key2,Value2}] = Call(Pid, [read, T, Key2]), - ok = Call(Pid, [close, T]), - - ?t:stop_node(Node), - file:delete(File), - ok; - false -> - {skipped, "No support for old node"} - end. - - %% %% Parts common to several test cases diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index d40609eeb0..af5d5a8f21 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -3268,15 +3268,14 @@ delete_large_named_table_1(Name, Flags, Data, Fix) -> end, Parent = self(), {Pid, MRef} = my_spawn_opt(fun() -> - receive - {trace,Parent,call,_} -> - ets_new(Name, [named_table]) - end - end, [link, monitor]), - ?line erlang:trace(self(), true, [call,{tracer,Pid}]), - ?line erlang:trace_pattern({ets,delete,1}, true, [global]), - ?line erlang:yield(), true = ets:delete(Tab), - ?line erlang:trace_pattern({ets,delete,1}, false, [global]), + receive + ets_new -> + ets_new(Name, [named_table]) + end + end, + [link, monitor]), + true = ets:delete(Tab), + Pid ! ets_new, receive {'DOWN',MRef,process,Pid,_} -> ok end, ok. diff --git a/lib/test_server/src/test_server_gl.erl b/lib/test_server/src/test_server_gl.erl index 2e4f223811..1f7317c51d 100644 --- a/lib/test_server/src/test_server_gl.erl +++ b/lib/test_server/src/test_server_gl.erl @@ -166,7 +166,7 @@ handle_info({'DOWN',Ref,process,_,Reason}=D, #st{minor_monitor=Ref}=St) -> Data = io_lib:format("=== WARNING === TC: ~w\n" "Got down from minor Fd ~w: ~w\n\n", [St#st.tc,St#st.minor,D]), - test_server_io:print(xxxFrom, unexpected_io, Data) + test_server_io:print_unexpected(Data) end, {noreply,St#st{minor=none,minor_monitor=none}}; handle_info({permit_io,Pid}, #st{permit_io=P}=St) -> diff --git a/lib/test_server/src/test_server_io.erl b/lib/test_server/src/test_server_io.erl index 242c08f765..a979deffc3 100644 --- a/lib/test_server/src/test_server_io.erl +++ b/lib/test_server/src/test_server_io.erl @@ -30,7 +30,8 @@ -module(test_server_io). -export([start_link/0,stop/0,get_gl/1,set_fd/2, - start_transaction/0,end_transaction/0,print_buffered/1,print/3, + start_transaction/0,end_transaction/0, + print_buffered/1,print/3,print_unexpected/1, set_footer/1,set_job_name/1,set_gl_props/1]). -export([init/1,handle_call/3,handle_info/2,terminate/2]). @@ -124,6 +125,14 @@ print(From, Tag, Msg) -> print_buffered(Pid) -> req({print_buffered,Pid}). +%% print_unexpected(Msg) +%% Msg = string or iolist +%% +%% Print the given string in the unexpected_io log. + +print_unexpected(Msg) -> + print(xxxFrom,unexpected_io,Msg). + %% set_footer(IoData) %% %% Set a footer for the file associated with the 'html' tag. diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl index cf1df6df34..3db2f5f9f1 100644 --- a/lib/test_server/test/test_server_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE.erl @@ -104,7 +104,7 @@ test_server_SUITE(Config) -> % rpc:call(Node,dbg, tpl,[test_server_ctrl,x]), run_test_server_tests("test_server_SUITE", [{test_server_SUITE,skip_case7,"SKIPPED!"}], - 39, 1, 31, 20, 9, 1, 11, 2, 26, Config). + 40, 1, 32, 21, 9, 1, 11, 2, 27, Config). test_server_parallel01_SUITE(Config) -> run_test_server_tests("test_server_parallel01_SUITE", [], diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE_data/test_server_SUITE.erl index 6c50efa712..541e8fdefc 100644 --- a/lib/test_server/test/test_server_SUITE_data/test_server_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE_data/test_server_SUITE.erl @@ -39,7 +39,7 @@ check_old_conf/1, conf_init_fail/1, start_stop_node/1, cleanup_nodes_init/1, check_survive_nodes/1, cleanup_nodes_fin/1, commercial/1, - io_invalid_data/1]). + io_invalid_data/1, print_unexpected/1]). -export([dummy_function/0,dummy_function/1,doer/1]). @@ -48,7 +48,7 @@ all(suite) -> [config, comment, timetrap, timetrap_cancel, multiply_timetrap, init_per_s, init_per_tc, end_per_tc, timeconv, msgs, capture, timecall, do_times, skip_cases, - commercial, io_invalid_data, + commercial, io_invalid_data, print_unexpected, {conf, conf_init, [check_new_conf], conf_cleanup}, check_old_conf, {conf, conf_init_fail,[conf_member_skip],conf_cleanup_skip}, @@ -503,3 +503,12 @@ io_invalid_data(Config) when is_list(Config) -> %% OTP-10991 caused this to hang and produce a timetrap timeout: {'EXIT',{badarg,_}} = (catch io:put_chars("invalid: " ++ [42.0])), ok. + +print_unexpected(Config) when is_list(Config) -> + Str = "-x-x-x- test_server_SUITE:print_unexpected -> Unexpected data -x-x-x-", + test_server_io:print_unexpected(Str), + UnexpectedLog = filename:join(filename:dirname(?config(tc_logfile,Config)), + "unexpected_io.log.html"), + {ok,Bin} = file:read_file(UnexpectedLog), + match = re:run(Bin, Str, [global,{capture,none}]), + ok. diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index c2c627abe0..bf21aa6b48 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -721,6 +721,11 @@ main_process_loop(State) -> end, State#main_state.nodes), reload_originals(State#main_state.compiled), + ets:delete(?COVER_TABLE), + ets:delete(?COVER_CLAUSE_TABLE), + ets:delete(?BINARY_TABLE), + ets:delete(?COLLECTION_TABLE), + ets:delete(?COLLECTION_CLAUSE_TABLE), unregister(?SERVER), reply(From, ok); @@ -876,6 +881,8 @@ remote_process_loop(State) -> {remote,stop} -> reload_originals(State#remote_state.compiled), + ets:delete(?COVER_TABLE), + ets:delete(?COVER_CLAUSE_TABLE), unregister(?SERVER), ok; % not replying since 'DOWN' message will be received anyway |