aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/common_test/src/ct_logs.erl58
-rw-r--r--lib/common_test/src/ct_telnet.erl39
-rw-r--r--lib/common_test/test/ct_group_leader_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl41
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl9
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl57
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bs_constraints.erl32
-rw-r--r--lib/hipe/icode/hipe_icode_coordinator.erl18
-rw-r--r--lib/hipe/main/hipe.erl21
-rw-r--r--lib/stdlib/doc/src/sys.xml8
-rw-r--r--lib/stdlib/src/gen.erl31
-rw-r--r--lib/stdlib/test/dets_SUITE.erl77
-rw-r--r--lib/stdlib/test/ets_SUITE.erl17
-rw-r--r--lib/test_server/src/test_server_gl.erl2
-rw-r--r--lib/test_server/src/test_server_io.erl11
-rw-r--r--lib/test_server/test/test_server_SUITE.erl2
-rw-r--r--lib/test_server/test/test_server_SUITE_data/test_server_SUITE.erl13
-rw-r--r--lib/tools/src/cover.erl7
19 files changed, 260 insertions, 191 deletions
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