aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src')
-rw-r--r--lib/kernel/src/application_controller.erl14
-rw-r--r--lib/kernel/src/auth.erl4
-rw-r--r--lib/kernel/src/dist_util.erl6
-rw-r--r--lib/kernel/src/erl_distribution.erl1
-rw-r--r--lib/kernel/src/erts_debug.erl64
-rw-r--r--lib/kernel/src/file_io_server.erl114
-rw-r--r--lib/kernel/src/gen_udp.erl2
-rw-r--r--lib/kernel/src/global.erl18
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl17
-rw-r--r--lib/kernel/src/inet.erl4
-rw-r--r--lib/kernel/src/inet_db.erl3
-rw-r--r--lib/kernel/src/inet_res.erl14
-rw-r--r--lib/kernel/src/inet_tcp_dist.erl48
-rw-r--r--lib/kernel/src/kernel.app.src2
-rw-r--r--lib/kernel/src/os.erl14
-rw-r--r--lib/kernel/src/pg2.erl11
-rw-r--r--lib/kernel/src/standard_error.erl155
17 files changed, 283 insertions, 208 deletions
diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl
index daad45b6c2..6635885aaf 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_controller.erl
@@ -1615,7 +1615,6 @@ conv([Key, Val | T]) ->
[{make_term(Key), make_term(Val)} | conv(T)];
conv(_) -> [].
-%%% Fix some day: eliminate the duplicated code here
make_term(Str) ->
case erl_scan:string(Str) of
{ok, Tokens, _} ->
@@ -1623,16 +1622,17 @@ make_term(Str) ->
{ok, Term} ->
Term;
{error, {_,M,Reason}} ->
- error_logger:format("application_controller: ~ts: ~ts~n",
- [M:format_error(Reason), Str]),
- throw({error, {bad_environment_value, Str}})
+ handle_make_term_error(M, Reason, Str)
end;
{error, {_,M,Reason}, _} ->
- error_logger:format("application_controller: ~ts: ~ts~n",
- [M:format_error(Reason), Str]),
- throw({error, {bad_environment_value, Str}})
+ handle_make_term_error(M, Reason, Str)
end.
+handle_make_term_error(Mod, Reason, Str) ->
+ error_logger:format("application_controller: ~ts: ~ts~n",
+ [Mod:format_error(Reason), Str]),
+ throw({error, {bad_environment_value, Str}}).
+
get_env_i(Name, #state{conf_data = ConfData}) when is_list(ConfData) ->
case lists:keyfind(Name, 1, ConfData) of
{_Name, Env} -> Env;
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index eda35147d3..dbc486bee1 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -370,8 +370,8 @@ check_cookie1([], Result) ->
%% Creates a new, random cookie.
create_cookie(Name) ->
- {_, S1, S2} = now(),
- Seed = S2*10000+S1,
+ Seed = abs(erlang:monotonic_time()
+ bxor erlang:unique_integer()),
Cookie = random_cookie(20, Seed, []),
case file:open(Name, [write, raw]) of
{ok, File} ->
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index b127fe2e33..6b510bd0c3 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -298,7 +298,7 @@ shutdown(_Module, _Line, _Data, Reason) ->
exit(Reason).
%% Use this line to debug connection.
%% Set net_kernel verbose = 1 as well.
-%% exit({Reason, ?MODULE, _Line, _Data, erlang:now()}).
+%% exit({Reason, ?MODULE, _Line, _Data, erlang:timestamp()}).
flush_down() ->
@@ -373,7 +373,9 @@ gen_digest(Challenge, Cookie) when is_integer(Challenge), is_atom(Cookie) ->
%% gen_challenge() returns a "random" number
%% ---------------------------------------------------------------
gen_challenge() ->
- {A,B,C} = erlang:now(),
+ A = erlang:phash2([erlang:node()]),
+ B = erlang:monotonic_time(),
+ C = erlang:unique_integer(),
{D,_} = erlang:statistics(reductions),
{E,_} = erlang:statistics(runtime),
{F,_} = erlang:statistics(wall_clock),
diff --git a/lib/kernel/src/erl_distribution.erl b/lib/kernel/src/erl_distribution.erl
index 25ad34357a..3c4429129e 100644
--- a/lib/kernel/src/erl_distribution.erl
+++ b/lib/kernel/src/erl_distribution.erl
@@ -22,7 +22,6 @@
-export([start_link/0,start_link/1,init/1,start/1,stop/0]).
-%-define(DBG,io:format("~p:~p~n",[?MODULE,?LINE])).
-define(DBG,erlang:display([?MODULE,?LINE])).
start_link() ->
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index ef605d0bfe..8f81fcf825 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -20,7 +20,7 @@
%% Low-level debugging support. EXPERIMENTAL!
--export([size/1,df/1,df/2,df/3]).
+-export([size/1,df/1,df/2,df/3,ic/1]).
%% This module contains the following *experimental* BIFs:
%% disassemble/1
@@ -33,7 +33,7 @@
-export([breakpoint/2, disassemble/1, display/1, dist_ext_to_term/2,
dump_monitors/1, dump_links/1, flat_size/1,
get_internal_state/1, instructions/0, lock_counters/1,
- same/2, set_internal_state/2]).
+ map_info/1, same/2, set_internal_state/2]).
-spec breakpoint(MFA, Flag) -> non_neg_integer() when
MFA :: {Module :: module(),
@@ -114,6 +114,19 @@ get_internal_state(_) ->
instructions() ->
erlang:nif_error(undef).
+-spec ic(F) -> Result when
+ F :: function(),
+ Result :: term().
+
+ic(F) when is_function(F) ->
+ Is0 = erlang:system_info(instruction_counts),
+ R = F(),
+ Is1 = erlang:system_info(instruction_counts),
+ Is = lists:keysort(2,[{I,C1 - C0}||{{I,C1},{I,C0}} <- lists:zip(Is1,Is0)]),
+ _ = [io:format("~12w ~w~n", [C,I])||{I,C}<-Is],
+ io:format("Total: ~w~n",[lists:sum([C||{_I,C}<-Is])]),
+ R.
+
-spec lock_counters(info) -> term();
(clear) -> ok;
({copy_save, boolean()}) -> boolean();
@@ -164,8 +177,10 @@ set_internal_state(_, _) ->
-spec size(term()) -> non_neg_integer().
+-record(s, {seen, maps}).
+
size(Term) ->
- {Sum,_} = size(Term, gb_trees:empty(), 0),
+ {Sum,_} = size(Term, #s{seen=gb_trees:empty(),maps=[]}, 0),
Sum.
size([H|T]=Term, Seen0, Sum0) ->
@@ -209,10 +224,24 @@ tuple_size(I, Sz, Tuple, Seen0, Sum0) ->
tuple_size(I+1, Sz, Tuple, Seen, Sum).
map_size(Map,Seen0,Sum0) ->
- Kt = erts_internal:map_to_tuple_keys(Map),
- Vs = maps:values(Map),
- {Sum1,Seen1} = size(Kt,Seen0,Sum0),
- fold_size(Vs,Seen1,Sum1+length(Vs)+3).
+ %% Danger:
+ %% The internal nodes from erts_internal:map_hashmap_children/1
+ %% is not allowed to leak anywhere. They are only allowed in
+ %% containers (cons cells and tuples, not maps), in gc and
+ %% in erts_debug:same/2
+ case erts_internal:map_type(Map) of
+ flatmap ->
+ Kt = erts_internal:map_to_tuple_keys(Map),
+ Vs = maps:values(Map),
+ {Sum1,Seen1} = size(Kt,Seen0,Sum0),
+ fold_size(Vs,Seen1,Sum1+length(Vs)+3);
+ hashmap ->
+ Cs = erts_internal:map_hashmap_children(Map),
+ fold_size(Cs,Seen0,Sum0+length(Cs)+2);
+ hashmap_node ->
+ Cs = erts_internal:map_hashmap_children(Map),
+ fold_size(Cs,Seen0,Sum0+length(Cs)+1)
+ end.
fun_size(Fun, Seen, Sum) ->
case erlang:fun_info(Fun, type) of
@@ -229,13 +258,18 @@ fold_size([H|T], Seen0, Sum0) ->
fold_size(T, Seen, Sum);
fold_size([], Seen, Sum) -> {Sum,Seen}.
-remember_term(Term, Seen) ->
- case gb_trees:lookup(Term, Seen) of
- none -> gb_trees:insert(Term, [Term], Seen);
+remember_term(Term, #s{maps=Ms}=S) when is_map(Term) ->
+ case is_term_seen(Term, Ms) of
+ false -> S#s{maps=[Term|Ms]};
+ true -> seen
+ end;
+remember_term(Term, #s{seen=T}=S) ->
+ case gb_trees:lookup(Term,T) of
+ none -> S#s{seen=gb_trees:insert(Term,[Term],T)};
{value,Terms} ->
case is_term_seen(Term, Terms) of
- false -> gb_trees:update(Term, [Term|Terms], Seen);
- true -> seen
+ false -> S#s{seen=gb_trees:update(Term,[Term|Terms],T)};
+ true -> seen
end
end.
@@ -313,3 +347,9 @@ cont_dis(File, {Addr,Str,MFA}, MFA) ->
io:put_chars(File, binary_to_list(Str)),
cont_dis(File, erts_debug:disassemble(Addr), MFA);
cont_dis(_, {_,_,_}, _) -> ok.
+
+-spec map_info(Map) -> list() when
+ Map :: map().
+
+map_info(_) ->
+ erlang:nif_error(undef).
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index 0e9ff5bc0f..7d30e7e1d8 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -307,18 +307,18 @@ io_request({get_chars,Enc,_Prompt,N},
#state{}=State) ->
get_chars(N, Enc, State);
-%%
-%% This optimization gives almost nothing - needs more working...
-%% Disabled for now. /PaN
-%%
-%% io_request({get_line,Enc,_Prompt},
-%% #state{unic=latin1}=State) ->
-%% get_line(Enc,State);
-
-io_request({get_line,Enc,_Prompt},
- #state{}=State) ->
- get_chars(io_lib, collect_line, [], Enc, State);
-
+io_request({get_line,OutEnc,_Prompt}, #state{buf=Buf, read_mode=Mode, unic=InEnc} = State0) ->
+ try
+ %% Minimize the encoding conversions
+ WorkEnc = case InEnc of
+ {_,_} -> OutEnc; %% utf16 or utf32
+ _ -> InEnc %% Byte oriented utf8 or latin1
+ end,
+ {Res, State} = get_line(start, convert_enc(Buf, InEnc, WorkEnc), WorkEnc, State0),
+ {reply, cast(Res, Mode, WorkEnc, OutEnc), State}
+ catch exit:ExError ->
+ {stop,ExError,{error,ExError},State0#state{buf= <<>>}}
+ end;
io_request({setopts, Opts},
#state{}=State) when is_list(Opts) ->
@@ -386,56 +386,40 @@ put_chars(Chars, InEncoding, #state{handle=Handle, unic=OutEncoding}=State) ->
{stop,normal,{error,{no_translation, InEncoding, OutEncoding}},State}
end.
-%%
-%% Process the I/O request get_line for latin1 encoding of file specially
-%% Unfortunately this function gives almost nothing, it needs more work
-%% I disable it for now /PaN
-%%
-%% srch(<<>>,_,_) ->
-%% nomatch;
-%% srch(<<X:8,_/binary>>,X,N) ->
-%% {match,N};
-%% srch(<<_:8,T/binary>>,X,N) ->
-%% srch(T,X,N+1).
-%% get_line(OutEnc, #state{handle=Handle,buf = <<>>,unic=latin1}=State) ->
-%% case ?PRIM_FILE:read(Handle,?READ_SIZE_BINARY) of
-%% {ok, B} ->
-%% get_line(OutEnc, State#state{buf = B});
-%% eof ->
-%% {reply,eof,State};
-%% {error,Reason}=Error ->
-%% {stop,Reason,Error,State}
-%% end;
-%% get_line(OutEnc, #state{handle=Handle,buf=Buf,read_mode=ReadMode,unic=latin1}=State) ->
-%% case srch(Buf,$\n,0) of
-%% nomatch ->
-%% case ?PRIM_FILE:read(Handle,?READ_SIZE_BINARY) of
-%% {ok, B} ->
-%% get_line(OutEnc,State#state{buf = <<Buf/binary,B/binary>>});
-%% eof ->
-%% std_reply(cast(Buf, ReadMode,latin1,OutEnc), State);
-%% {error,Reason}=Error ->
-%% {stop,Reason,Error,State#state{buf= <<>>}}
-%% end;
-%% {match,Pos} when Pos >= 1->
-%% PosP1 = Pos + 1,
-%% <<Res0:PosP1/binary,NewBuf/binary>> = Buf,
-%% PosM1 = Pos - 1,
-%% Res = case Res0 of
-%% <<Chomped:PosM1/binary,$\r:8,$\n:8>> ->
-%% cat(Chomped, <<"\n">>, ReadMode,latin1,OutEnc);
-%% _Other ->
-%% cast(Res0, ReadMode,latin1,OutEnc)
-%% end,
-%% {reply,Res,State#state{buf=NewBuf}};
-%% {match,Pos} ->
-%% PosP1 = Pos + 1,
-%% <<Res:PosP1/binary,NewBuf/binary>> = Buf,
-%% {reply,Res,State#state{buf=NewBuf}}
-%% end;
-%% get_line(_, #state{}=State) ->
-%% {error,{error,get_line},State}.
-
+get_line(S, {<<>>, Cont}, OutEnc,
+ #state{handle=Handle, read_mode=Mode, unic=InEnc}=State) ->
+ case ?PRIM_FILE:read(Handle, read_size(Mode)) of
+ {ok,Bin} ->
+ get_line(S, convert_enc([Cont, Bin], InEnc, OutEnc), OutEnc, State);
+ eof ->
+ get_line(S, {eof, Cont}, OutEnc, State);
+ {error,Reason}=Error ->
+ {stop,Reason,Error,State}
+ end;
+get_line(S0, {Buf, BCont}, OutEnc, #state{unic=InEnc}=State) ->
+ case io_lib:collect_line(S0, Buf, OutEnc, []) of
+ {stop, Result, Cont0} ->
+ %% Convert both buffers back to file InEnc encoding
+ {Cont, <<>>} = convert_enc(Cont0, OutEnc, InEnc),
+ {Result, State#state{buf=cast_binary([Cont, BCont])}};
+ S ->
+ get_line(S, {<<>>, BCont}, OutEnc, State)
+ end.
+
+convert_enc(Bins, Enc, Enc) ->
+ {cast_binary(Bins), <<>>};
+convert_enc(eof, _, _) ->
+ {<<>>, <<>>};
+convert_enc(Bin, InEnc, OutEnc) ->
+ case unicode:characters_to_binary(Bin, InEnc, OutEnc) of
+ Res when is_binary(Res) ->
+ {Res, <<>>};
+ {incomplete, Res, Cont} ->
+ {Res, Cont};
+ {error, _, _} ->
+ exit({no_translation, InEnc, OutEnc})
+ end.
+
%%
%% Process the I/O request get_chars
%%
@@ -640,8 +624,6 @@ invalid_unicode_error(Mod, Func, XtraArg, S) ->
%% Convert error code to make it look as before
err_func(io_lib, get_until, {_,F,_}) ->
- F;
-err_func(_, F, _) ->
F.
@@ -713,6 +695,8 @@ cat(B1, B2, list, latin1,_) ->
binary_to_list(B1)++binary_to_list(B2).
%% Cast binary to list or binary
+cast(eof, _, _, _) ->
+ eof;
cast(B, binary, latin1, latin1) ->
B;
cast(B, binary, InEncoding, OutEncoding) ->
@@ -736,6 +720,8 @@ cast(B, list, InEncoding, OutEncoding) ->
%% Convert buffer to binary
cast_binary(Binary) when is_binary(Binary) ->
Binary;
+cast_binary([<<>>|List]) ->
+ cast_binary(List);
cast_binary(List) when is_list(List) ->
list_to_binary(List);
cast_binary(_EOF) ->
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 70dceb3679..860eec10a0 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -78,7 +78,7 @@
ipv6_v6only.
-type socket() :: port().
--export_type([option/0, option_name/0]).
+-export_type([option/0, option_name/0, socket/0]).
-spec open(Port) -> {ok, Socket} | {error, Reason} when
Port :: inet:port_number(),
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index 0a4edea452..6c36d417a2 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -881,11 +881,12 @@ handle_info({nodeup, Node}, S0) when S0#state.connect_all ->
false ->
resend_pre_connect(Node),
- %% now() is used as a tag to separate different synch sessions
+ %% erlang:unique_integer([monotonic]) is used as a tag to
+ %% separate different synch sessions
%% from each others. Global could be confused at bursty nodeups
%% because it couldn't separate the messages between the different
%% synch sessions started by a nodeup.
- MyTag = now(),
+ MyTag = erlang:unique_integer([monotonic]),
put({sync_tag_my, Node}, MyTag),
?trace({sending_nodeup_to_locker, {node,Node},{mytag,MyTag}}),
S1#state.the_locker ! {nodeup, Node, MyTag},
@@ -1772,8 +1773,8 @@ update_locker_known(Upd, S) ->
S#multi{known = Known, the_boss = TheBoss}.
random_element(L) ->
- {A,B,C} = now(),
- E = (A+B+C) rem length(L),
+ E = abs(erlang:monotonic_time()
+ bxor erlang:unique_integer()) rem length(L),
lists:nth(E+1, L).
exclude_known(Others, Known) ->
@@ -2072,9 +2073,10 @@ random_sleep(Times) ->
end,
case get(random_seed) of
undefined ->
- {A1, A2, A3} = now(),
- _ = random:seed(A1, A2, A3 + erlang:phash(node(), 100000)),
- ok;
+ _ = random:seed(erlang:phash2([erlang:node()]),
+ erlang:monotonic_time(),
+ erlang:unique_integer()),
+ ok;
_ -> ok
end,
%% First time 1/4 seconds, then doubling each time up to 8 seconds max.
@@ -2106,7 +2108,7 @@ trace_message(S, M, X) ->
S#state{trace = [trace_message(M, X) | S#state.trace]}.
trace_message(M, X) ->
- {node(), now(), M, nodes(), X}.
+ {node(), erlang:timestamp(), M, nodes(), X}.
%%-----------------------------------------------------------------
%% Each sync process corresponds to one call to sync. Each such
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index e5928c7b63..2d124d95b7 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -827,7 +827,6 @@ patch_to_emu_step1(Mod) ->
%% were added as the result of dynamic apply calls. We must
%% purge them too, but we have no explicit record of them.
%% Therefore invalidate all native addresses for the module.
- %% emu_make_stubs/1 will repair the ones for compiled static calls.
hipe_bifs:invalidate_funinfo_native_addresses(MFAs),
%% Find all call sites that call these MFAs. As a side-effect,
%% create native stubs for any MFAs that are referred.
@@ -841,7 +840,6 @@ patch_to_emu_step1(Mod) ->
%% Step 2 must occur after the new BEAM stub module is created.
patch_to_emu_step2(ReferencesToPatch) ->
- emu_make_stubs(ReferencesToPatch),
redirect(ReferencesToPatch).
-spec is_loaded(Module::atom()) -> boolean().
@@ -852,21 +850,6 @@ is_loaded(M) when is_atom(M) ->
catch _:_ -> false
end.
--ifdef(notdef).
-emu_make_stubs([{MFA,_Refs}|Rest]) ->
- make_stub(MFA),
- emu_make_stubs(Rest);
-emu_make_stubs([]) ->
- [].
-
-make_stub({_,_,A} = MFA) ->
- EmuAddress = hipe_bifs:get_emu_address(MFA),
- StubAddress = hipe_bifs:make_native_stub(EmuAddress, A),
- hipe_bifs:set_funinfo_native_address(MFA, StubAddress).
--else.
-emu_make_stubs(_) -> [].
--endif.
-
%%--------------------------------------------------------------------
%% Given a list of MFAs, tag them with their referred_from references.
%% The resulting {MFA,Refs} list is later passed to redirect/1, once
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 43bab8bcf0..ec2c350931 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2015. 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
@@ -1070,7 +1070,7 @@ gethostbyname_tm(Name, Type, Timer, [wins|_]=Opts) ->
gethostbyname_tm_native(Name, Type, Timer, Opts);
gethostbyname_tm(Name, Type, Timer, [native|_]=Opts) ->
gethostbyname_tm_native(Name, Type, Timer, Opts);
-gethostbyname_tm(Name, Type, Timer, [_|_]=Opts) ->
+gethostbyname_tm(Name, Type, Timer, [_|Opts]) ->
gethostbyname_tm(Name, Type, Timer, Opts);
%% Make sure we always can look up our own hostname.
gethostbyname_tm(Name, Type, Timer, []) ->
diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl
index 2ebdc0f554..abe207295f 100644
--- a/lib/kernel/src/inet_db.erl
+++ b/lib/kernel/src/inet_db.erl
@@ -1372,8 +1372,7 @@ cache_rr(_Db, Cache, RR) ->
ets:insert(Cache, RR).
times() ->
- {Mega,Secs,_} = erlang:now(),
- Mega*1000000 + Secs.
+ erlang:monotonic_time(1).
%% lookup and remove old entries
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index 6037da1d22..410128a16a 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -715,10 +715,10 @@ udp_send(#sock{inet=I}, {A,B,C,D}=IP, Port, Buffer)
udp_recv(#sock{inet6=I}, {A,B,C,D,E,F,G,H}=IP, Port, Timeout, Decode)
when ?ip6(A,B,C,D,E,F,G,H), ?port(Port) ->
- do_udp_recv(I, IP, Port, Timeout, Decode, erlang:now(), Timeout);
+ do_udp_recv(I, IP, Port, Timeout, Decode, time_now(), Timeout);
udp_recv(#sock{inet=I}, {A,B,C,D}=IP, Port, Timeout, Decode)
when ?ip(A,B,C,D), ?port(Port) ->
- do_udp_recv(I, IP, Port, Timeout, Decode, erlang:now(), Timeout).
+ do_udp_recv(I, IP, Port, Timeout, Decode, time_now(), Timeout).
do_udp_recv(_I, _IP, _Port, 0, _Decode, _Start, _T) ->
timeout;
@@ -742,7 +742,7 @@ do_udp_recv(I, IP, Port, Timeout, Decode, Start, T) ->
NewTimeout = erlang:max(0, Timeout - 50),
do_udp_recv(I, IP, Port, NewTimeout, Decode, Start, T);
false ->
- Now = erlang:now(),
+ Now = time_now(),
NewT = erlang:max(0, Timeout - now_ms(Now, Start)),
do_udp_recv(I, IP, Port, Timeout, Decode, Start, NewT);
Result ->
@@ -1057,5 +1057,9 @@ dns_msg(Msg) ->
end.
-compile({inline, [now_ms/2]}).
-now_ms({Meg1,Sec1,Mic1}, {Meg0,Sec0,Mic0}) ->
- ((Meg1-Meg0)*1000000 + (Sec1-Sec0))*1000 + ((Mic1-Mic0) div 1000).
+now_ms(Int1, Int0) ->
+ Int1 - Int0.
+
+-compile({inline, [time_now/0]}).
+time_now() ->
+ erlang:monotonic_time(1000).
diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl
index 63f236b069..835dcf2705 100644
--- a/lib/kernel/src/inet_tcp_dist.erl
+++ b/lib/kernel/src/inet_tcp_dist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2015. 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
@@ -77,7 +77,7 @@ listen(Name) ->
Error
end.
-do_listen(Options0) ->
+do_listen(Options) ->
{First,Last} = case application:get_env(kernel,inet_dist_listen_min) of
{ok,N} when is_integer(N) ->
case application:get_env(kernel,
@@ -90,13 +90,7 @@ do_listen(Options0) ->
_ ->
{0,0}
end,
- Options = case application:get_env(kernel, inet_dist_use_interface) of
- {ok, Ip} ->
- [{ip, Ip} | Options0];
- _ ->
- Options0
- end,
- do_listen(First, Last, [{backlog,128}|Options]).
+ do_listen(First, Last, listen_options([{backlog,128}|Options])).
do_listen(First,Last,_) when First > Last ->
{error,eaddrinuse};
@@ -108,6 +102,23 @@ do_listen(First,Last,Options) ->
Other
end.
+listen_options(Opts0) ->
+ Opts1 =
+ case application:get_env(kernel, inet_dist_use_interface) of
+ {ok, Ip} ->
+ [{ip, Ip} | Opts0];
+ _ ->
+ Opts0
+ end,
+ case application:get_env(kernel, inet_dist_listen_options) of
+ {ok,ListenOpts} ->
+ erlang:display({inet_dist_listen_options, ListenOpts}),
+ ListenOpts ++ Opts1;
+ _ ->
+ Opts1
+ end.
+
+
%% ------------------------------------------------------------
%% Accepts new connection attempts from other Erlang nodes.
%% ------------------------------------------------------------
@@ -219,7 +230,7 @@ nodelay() ->
_ ->
{nodelay, true}
end.
-
+
%% ------------------------------------------------------------
%% Get remote information about a Socket.
@@ -260,9 +271,11 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
?trace("port_please(~p) -> version ~p~n",
[Node,Version]),
dist_util:reset_timer(Timer),
- case inet_tcp:connect(Ip, TcpPort,
- [{active, false},
- {packet,2}]) of
+ case
+ inet_tcp:connect(
+ Ip, TcpPort,
+ connect_options([{active, false}, {packet, 2}]))
+ of
{ok, Socket} ->
HSData = #hs_data{
kernel_pid = Kernel,
@@ -324,6 +337,15 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
?shutdown(Node)
end.
+connect_options(Opts) ->
+ case application:get_env(kernel, inet_dist_connect_options) of
+ {ok,ConnectOpts} ->
+ erlang:display({inet_dist_listen_options, ConnectOpts}),
+ ConnectOpts ++ Opts;
+ _ ->
+ Opts
+ end.
+
%%
%% Close a socket.
%%
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 9f6c0f4624..0cb10791d7 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -115,6 +115,6 @@
{applications, []},
{env, [{error_logger, tty}]},
{mod, {kernel, []}},
- {runtime_dependencies, ["erts-6.1.2", "stdlib-2.0", "sasl-2.4"]}
+ {runtime_dependencies, ["erts-7.0", "stdlib-2.0", "sasl-2.4"]}
]
}.
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 7468a06f3c..3647545777 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -26,7 +26,8 @@
%%% BIFs
--export([getenv/0, getenv/1, getenv/2, getpid/0, putenv/2, timestamp/0, unsetenv/1]).
+-export([getenv/0, getenv/1, getenv/2, getpid/0, putenv/2, system_time/0, system_time/1,
+ timestamp/0, unsetenv/1]).
-spec getenv() -> [string()].
@@ -65,6 +66,17 @@ getpid() ->
putenv(_, _) ->
erlang:nif_error(undef).
+-spec system_time() -> integer().
+
+system_time() ->
+ erlang:nif_error(undef).
+
+-spec system_time(Unit) -> integer() when
+ Unit :: erlang:time_unit().
+
+system_time(_Unit) ->
+ erlang:nif_error(undef).
+
-spec timestamp() -> Timestamp when
Timestamp :: erlang:timestamp().
diff --git a/lib/kernel/src/pg2.erl b/lib/kernel/src/pg2.erl
index b562d4ffd2..70d7a75671 100644
--- a/lib/kernel/src/pg2.erl
+++ b/lib/kernel/src/pg2.erl
@@ -140,19 +140,22 @@ get_closest_pid(Name) ->
[Pid] ->
Pid;
[] ->
- {_,_,X} = erlang:now(),
case get_members(Name) of
[] -> {error, {no_process, Name}};
Members ->
- lists:nth((X rem length(Members))+1, Members)
+ random_element(Members)
end;
Members when is_list(Members) ->
- {_,_,X} = erlang:now(),
- lists:nth((X rem length(Members))+1, Members);
+ random_element(Members);
Else ->
Else
end.
+random_element(List) ->
+ X = abs(erlang:monotonic_time()
+ bxor erlang:unique_integer()),
+ lists:nth((X rem length(List)) + 1, List).
+
%%%
%%% Callback functions from gen_server
%%%
diff --git a/lib/kernel/src/standard_error.erl b/lib/kernel/src/standard_error.erl
index 10cf77e0d4..1c43063937 100644
--- a/lib/kernel/src/standard_error.erl
+++ b/lib/kernel/src/standard_error.erl
@@ -63,7 +63,7 @@ server(PortName,PortSettings) ->
run(Port).
run(P) ->
- put(unicode,false),
+ put(encoding, latin1),
server_loop(P).
server_loop(Port) ->
@@ -95,25 +95,47 @@ do_io_request(Req, From, ReplyAs, Port) ->
io_reply(From, ReplyAs, Reply).
%% New in R13B
-% Wide characters (Unicode)
-io_request({put_chars,Encoding,Chars}, Port) -> % Binary new in R9C
- put_chars(wrap_characters_to_binary(Chars,Encoding,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end), Port);
-io_request({put_chars,Encoding,Mod,Func,Args}, Port) ->
- Result = case catch apply(Mod,Func,Args) of
- Data when is_list(Data); is_binary(Data) ->
- wrap_characters_to_binary(Data,Encoding,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end);
- Undef ->
- Undef
- end,
- put_chars(Result, Port);
+%% Encoding option (unicode/latin1)
+io_request({put_chars,unicode,Chars}, Port) ->
+ case wrap_characters_to_binary(Chars, unicode, get(encoding)) of
+ error ->
+ {error,{error,put_chars}};
+ Bin ->
+ put_chars(Bin, Port)
+ end;
+io_request({put_chars,unicode,Mod,Func,Args}, Port) ->
+ case catch apply(Mod, Func, Args) of
+ Data when is_list(Data); is_binary(Data) ->
+ case wrap_characters_to_binary(Data, unicode, get(encoding)) of
+ Bin when is_binary(Bin) ->
+ put_chars(Bin, Port);
+ error ->
+ {error,{error,put_chars}}
+ end;
+ _ ->
+ {error,{error,put_chars}}
+ end;
+io_request({put_chars,latin1,Chars}, Port) ->
+ case catch unicode:characters_to_binary(Chars, latin1, get(encoding)) of
+ Data when is_binary(Data) ->
+ put_chars(Data, Port);
+ _ ->
+ {error,{error,put_chars}}
+ end;
+io_request({put_chars,latin1,Mod,Func,Args}, Port) ->
+ case catch apply(Mod, Func, Args) of
+ Data when is_list(Data); is_binary(Data) ->
+ case
+ catch unicode:characters_to_binary(Data, latin1, get(encoding))
+ of
+ Bin when is_binary(Bin) ->
+ put_chars(Bin, Port);
+ _ ->
+ {error,{error,put_chars}}
+ end;
+ _ ->
+ {error,{error,put_chars}}
+ end;
%% BC if called from pre-R13 node
io_request({put_chars,Chars}, Port) ->
io_request({put_chars,latin1,Chars}, Port);
@@ -134,10 +156,10 @@ io_request({get_geometry,rows},Port) ->
_ ->
{error,{error,enotsup}}
end;
-io_request({getopts,[]}, Port) ->
- getopts(Port);
-io_request({setopts,Opts}, Port) when is_list(Opts) ->
- setopts(Opts, Port);
+io_request(getopts, _Port) ->
+ getopts();
+io_request({setopts,Opts}, _Port) when is_list(Opts) ->
+ setopts(Opts);
io_request({requests,Reqs}, Port) ->
io_requests(Reqs, {ok,ok}, Port);
io_request(R, _Port) -> %Unknown request
@@ -176,47 +198,48 @@ io_reply(From, ReplyAs, Reply) ->
%% put_chars
put_chars(Chars, Port) when is_binary(Chars) ->
_ = put_port(Chars, Port),
- {ok,ok};
-put_chars(Chars, Port) ->
- case catch list_to_binary(Chars) of
- Binary when is_binary(Binary) ->
- put_chars(Binary, Port);
- _ ->
- {error,{error,put_chars}}
- end.
+ {ok,ok}.
%% setopts
-setopts(Opts0,Port) ->
- Opts = proplists:unfold(
- proplists:substitute_negations(
- [{latin1,unicode}],
- Opts0)),
+setopts(Opts0) ->
+ Opts = expand_encoding(Opts0),
case check_valid_opts(Opts) of
- true ->
- do_setopts(Opts,Port);
- false ->
- {error,{error,enotsup}}
+ true ->
+ do_setopts(Opts);
+ false ->
+ {error,{error,enotsup}}
end.
+
check_valid_opts([]) ->
true;
-check_valid_opts([{unicode,Valid}|T]) when Valid =:= true; Valid =:= utf8; Valid =:= false ->
+check_valid_opts([{encoding,Valid}|T]) when Valid =:= unicode;
+ Valid =:= utf8; Valid =:= latin1 ->
check_valid_opts(T);
check_valid_opts(_) ->
false.
-do_setopts(Opts, _Port) ->
- case proplists:get_value(unicode,Opts) of
- Valid when Valid =:= true; Valid =:= utf8 ->
- put(unicode,true);
- false ->
- put(unicode,false);
- undefined ->
- ok
+expand_encoding([]) ->
+ [];
+expand_encoding([latin1 | T]) ->
+ [{encoding,latin1} | expand_encoding(T)];
+expand_encoding([unicode | T]) ->
+ [{encoding,unicode} | expand_encoding(T)];
+expand_encoding([H|T]) ->
+ [H|expand_encoding(T)].
+
+do_setopts(Opts) ->
+ case proplists:get_value(encoding, Opts) of
+ Valid when Valid =:= unicode; Valid =:= utf8 ->
+ put(encoding, unicode);
+ latin1 ->
+ put(encoding, latin1);
+ undefined ->
+ ok
end,
{ok,ok}.
-getopts(_Port) ->
- Uni = {unicode, get(unicode) =:= true},
+getopts() ->
+ Uni = {encoding,get(encoding)},
{ok,[Uni]}.
wrap_characters_to_binary(Chars,From,To) ->
@@ -227,17 +250,17 @@ wrap_characters_to_binary(Chars,From,To) ->
_Else ->
16#10ffff
end,
- unicode:characters_to_binary(
- [ case X of
- $\n ->
- if
- TrNl ->
- "\r\n";
- true ->
- $\n
- end;
- High when High > Limit ->
- ["\\x{",erlang:integer_to_list(X, 16),$}];
- Ordinary ->
- Ordinary
- end || X <- unicode:characters_to_list(Chars,From) ],unicode,To).
+ case catch unicode:characters_to_list(Chars, From) of
+ L when is_list(L) ->
+ unicode:characters_to_binary(
+ [ case X of
+ $\n when TrNl ->
+ "\r\n";
+ High when High > Limit ->
+ ["\\x{",erlang:integer_to_list(X, 16),$}];
+ Low ->
+ Low
+ end || X <- L ], unicode, To);
+ _ ->
+ error
+ end.