aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src')
-rw-r--r--lib/kernel/src/Makefile1
-rw-r--r--lib/kernel/src/application_controller.erl43
-rw-r--r--lib/kernel/src/application_master.erl6
-rw-r--r--lib/kernel/src/code_server.erl7
-rw-r--r--lib/kernel/src/erl_boot_server.erl6
-rw-r--r--lib/kernel/src/erl_distribution.erl1
-rw-r--r--lib/kernel/src/erl_epmd.erl15
-rw-r--r--lib/kernel/src/erts_debug.erl21
-rw-r--r--lib/kernel/src/file.erl72
-rw-r--r--lib/kernel/src/gen_udp.erl2
-rw-r--r--lib/kernel/src/inet.erl81
-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/kernel.appup.src6
-rw-r--r--lib/kernel/src/net_adm.erl9
-rw-r--r--lib/kernel/src/standard_error.erl155
16 files changed, 287 insertions, 188 deletions
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index cb3c0a49f4..c7c70ad257 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -122,6 +122,7 @@ HRL_FILES= ../include/file.hrl ../include/inet.hrl ../include/inet_sctp.hrl \
../include/net_address.hrl
INTERNAL_HRL_FILES= application_master.hrl disk_log.hrl \
+ erl_epmd.hrl hipe_ext_format.hrl \
inet_dns.hrl inet_res.hrl \
inet_boot.hrl inet_config.hrl inet_int.hrl \
inet_dns_record_adts.hrl
diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl
index ed13035104..6635885aaf 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_controller.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2014. 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
@@ -829,12 +829,12 @@ handle_call({change_application_data, Applications, Config}, _From, S) ->
{reply, Error, S};
{'EXIT', R} ->
{reply, {error, R}, S};
- NewAppls ->
+ {NewAppls, NewConfig} ->
lists:foreach(fun(Appl) ->
ets:insert(ac_tab, {{loaded, Appl#appl.name},
Appl})
end, NewAppls),
- {reply, ok, S#state{conf_data = Config}}
+ {reply, ok, S#state{conf_data = NewConfig}}
end;
handle_call(prep_config_change, _From, S) ->
@@ -1550,18 +1550,19 @@ do_change_apps(Applications, Config, OldAppls) ->
end,
Errors),
- map(fun(Appl) ->
- AppName = Appl#appl.name,
- case is_loaded_app(AppName, Applications) of
- {true, Application} ->
- do_change_appl(make_appl(Application),
- Appl, SysConfig);
+ {map(fun(Appl) ->
+ AppName = Appl#appl.name,
+ case is_loaded_app(AppName, Applications) of
+ {true, Application} ->
+ do_change_appl(make_appl(Application),
+ Appl, SysConfig);
- %% ignored removed apps - handled elsewhere
- false ->
- Appl
- end
- end, OldAppls).
+ %% ignored removed apps - handled elsewhere
+ false ->
+ Appl
+ end
+ end, OldAppls),
+ SysConfig}.
is_loaded_app(AppName, [{application, AppName, App} | _]) ->
{true, {application, AppName, App}};
@@ -1614,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, _} ->
@@ -1622,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/application_master.erl b/lib/kernel/src/application_master.erl
index bc15b5a7de..7cdbe31ab2 100644
--- a/lib/kernel/src/application_master.erl
+++ b/lib/kernel/src/application_master.erl
@@ -103,9 +103,9 @@ call(AppMaster, Req) ->
%%% The reason for not using the logical structrure is that
%%% the application start function is synchronous, and
%%% that the AM is GL. This means that if AM executed the start
-%%% function, and this function uses spawn_request/1
-%%% or io, deadlock would occur. Therefore, this function is
-%%% executed by the process X. Also, AM needs three loops;
+%%% function, and this function uses io, deadlock would occur.
+%%% Therefore, this function is executed by the process X.
+%%% Also, AM needs three loops;
%%% init_loop (waiting for the start function to return)
%%% main_loop
%%% terminate_loop (waiting for the process to die)
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index fc7ac08699..819554ce74 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -63,7 +63,10 @@ init(Ref, Parent, [Root,Mode0]) ->
process_flag(trap_exit, true),
Db = ets:new(code, [private]),
- foreach(fun (M) -> ets:insert(Db, {M,preloaded}) end, erlang:pre_loaded()),
+ foreach(fun (M) ->
+ %% Pre-loaded modules are always sticky.
+ ets:insert(Db, [{M,preloaded},{{sticky,M},true}])
+ end, erlang:pre_loaded()),
ets:insert(Db, init:fetch_loaded()),
Mode =
@@ -988,7 +991,7 @@ try_archive_subdirs(_Archive, Base, []) ->
%% the complete directory name.
%%
del_path(Name0,Path,NameDb) ->
- case catch to_list(Name0)of
+ case catch filename:join([to_list(Name0)]) of
{'EXIT',_} ->
{{error,bad_name},Path};
Name ->
diff --git a/lib/kernel/src/erl_boot_server.erl b/lib/kernel/src/erl_boot_server.erl
index 9a49655a9f..ef09d86ca4 100644
--- a/lib/kernel/src/erl_boot_server.erl
+++ b/lib/kernel/src/erl_boot_server.erl
@@ -341,9 +341,13 @@ handle_command(S, PS, Msg) ->
send_file_result(S, list_dir, Res),
PS2;
{read_file_info,File} ->
- {Res, PS2} = erl_prim_loader:prim_read_file_info(PS, File),
+ {Res, PS2} = erl_prim_loader:prim_read_file_info(PS, File, true),
send_file_result(S, read_file_info, Res),
PS2;
+ {read_link_info,File} ->
+ {Res, PS2} = erl_prim_loader:prim_read_file_info(PS, File, false),
+ send_file_result(S, read_link_info, Res),
+ PS2;
get_cwd ->
{Res, PS2} = erl_prim_loader:prim_get_cwd(PS, []),
send_file_result(S, get_cwd, Res),
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/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl
index b4fae24ef3..f6e2ca0954 100644
--- a/lib/kernel/src/erl_epmd.erl
+++ b/lib/kernel/src/erl_epmd.erl
@@ -85,24 +85,19 @@ port_please1(Node,HostName, Timeout) ->
Else
end.
-names() ->
+names() ->
{ok, H} = inet:gethostname(),
names(H).
-names(HostName) when is_atom(HostName) ->
- names1(atom_to_list(HostName));
-names(HostName) when is_list(HostName) ->
- names1(HostName);
-names(EpmdAddr) ->
- get_names(EpmdAddr).
-
-names1(HostName) ->
+names(HostName) when is_atom(HostName); is_list(HostName) ->
case inet:gethostbyname(HostName) of
{ok,{hostent, _Name, _ , _Af, _Size, [EpmdAddr | _]}} ->
get_names(EpmdAddr);
Else ->
Else
- end.
+ end;
+names(EpmdAddr) ->
+ get_names(EpmdAddr).
register_node(Name, PortNo) ->
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index f7a815882b..ef605d0bfe 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -182,6 +182,11 @@ size(Tuple, Seen0, Sum0) when is_tuple(Tuple) ->
Sum = Sum0 + 1 + tuple_size(Tuple),
tuple_size(1, tuple_size(Tuple), Tuple, Seen, Sum)
end;
+size(Map, Seen0, Sum) when is_map(Map) ->
+ case remember_term(Map, Seen0) of
+ seen -> {Sum,Seen0};
+ Seen -> map_size(Map, Seen, Sum)
+ end;
size(Fun, Seen0, Sum) when is_function(Fun) ->
case remember_term(Fun, Seen0) of
seen -> {Sum,Seen0};
@@ -203,6 +208,12 @@ tuple_size(I, Sz, Tuple, Seen0, Sum0) ->
{Sum,Seen} = size(element(I, 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).
+
fun_size(Fun, Seen, Sum) ->
case erlang:fun_info(Fun, type) of
{type,external} ->
@@ -210,14 +221,14 @@ fun_size(Fun, Seen, Sum) ->
{type,local} ->
Sz = erts_debug:flat_size(fun() -> ok end),
{env,Env} = erlang:fun_info(Fun, env),
- fun_size_1(Env, Seen, Sum+Sz+length(Env))
+ fold_size(Env, Seen, Sum+Sz+length(Env))
end.
-fun_size_1([H|T], Seen0, Sum0) ->
+fold_size([H|T], Seen0, Sum0) ->
{Sum,Seen} = size(H, Seen0, Sum0),
- fun_size_1(T, Seen, Sum);
-fun_size_1([], Seen, Sum) -> {Sum,Seen}.
-
+ 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);
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 20b703e084..3d6665a36a 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -114,18 +114,10 @@
-type sendfile_option() :: {chunk_size, non_neg_integer()}
| {use_threads, boolean()}.
-type file_info_option() :: {'time', 'local'} | {'time', 'universal'}
- | {'time', 'posix'}.
+ | {'time', 'posix'} | raw.
%%% BIFs
--export([file_info/1, native_name_encoding/0]).
-
--spec file_info(Filename) -> {ok, FileInfo} | {error, Reason} when
- Filename :: name_all(),
- FileInfo :: file_info(),
- Reason :: posix() | badarg.
-
-file_info(_) ->
- erlang:nif_error(undef).
+-export([native_name_encoding/0]).
-spec native_name_encoding() -> latin1 | utf8.
@@ -250,7 +242,19 @@ read_file_info(Name) ->
Reason :: posix() | badarg.
read_file_info(Name, Opts) when is_list(Opts) ->
- check_and_call(read_file_info, [file_name(Name), Opts]).
+ Args = [file_name(Name), Opts],
+ case check_args(Args) of
+ ok ->
+ case lists:member(raw, Opts) of
+ true ->
+ [FileName|_] = Args,
+ ?PRIM_FILE:read_file_info(FileName, Opts);
+ false ->
+ call(read_file_info, Args)
+ end;
+ Error ->
+ Error
+ end.
-spec altname(Name :: name_all()) -> any().
@@ -272,7 +276,19 @@ read_link_info(Name) ->
Reason :: posix() | badarg.
read_link_info(Name, Opts) when is_list(Opts) ->
- check_and_call(read_link_info, [file_name(Name),Opts]).
+ Args = [file_name(Name), Opts],
+ case check_args(Args) of
+ ok ->
+ case lists:member(raw, Opts) of
+ true ->
+ [FileName|_] = Args,
+ ?PRIM_FILE:read_link_info(FileName, Opts);
+ false ->
+ call(read_link_info, Args)
+ end;
+ Error ->
+ Error
+ end.
-spec read_link(Name) -> {ok, Filename} | {error, Reason} when
@@ -306,7 +322,19 @@ write_file_info(Name, Info = #file_info{}) ->
Reason :: posix() | badarg.
write_file_info(Name, Info = #file_info{}, Opts) when is_list(Opts) ->
- check_and_call(write_file_info, [file_name(Name), Info, Opts]).
+ Args = [file_name(Name), Info, Opts],
+ case check_args(Args) of
+ ok ->
+ case lists:member(raw, Opts) of
+ true ->
+ [FileName|_] = Args,
+ ?PRIM_FILE:write_file_info(FileName, Info, Opts);
+ false ->
+ call(write_file_info, Args)
+ end;
+ Error ->
+ Error
+ end.
-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when
Dir :: name_all(),
@@ -392,26 +420,12 @@ write_file(Name, Bin, ModeList) when is_list(ModeList) ->
%% Obsolete, undocumented, local node only, don't use!.
%% XXX to be removed.
raw_read_file_info(Name) ->
- Args = [file_name(Name)],
- case check_args(Args) of
- ok ->
- [FileName] = Args,
- ?PRIM_FILE:read_file_info(FileName);
- Error ->
- Error
- end.
+ read_file_info(Name, [raw]).
%% Obsolete, undocumented, local node only, don't use!.
%% XXX to be removed.
raw_write_file_info(Name, #file_info{} = Info) ->
- Args = [file_name(Name)],
- case check_args(Args) of
- ok ->
- [FileName] = Args,
- ?PRIM_FILE:write_file_info(FileName, Info);
- Error ->
- Error
- end.
+ write_file_info(Name, Info, [raw]).
%%%-----------------------------------------------------------------
%%% File io server functions.
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/inet.erl b/lib/kernel/src/inet.erl
index 41d422d7d4..9211134c75 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
@@ -690,14 +690,15 @@ connect_options(Opts, Family) ->
case con_opt(Opts, BaseOpts, connect_options()) of
{ok, R} ->
{ok, R#connect_opts {
+ opts = lists:reverse(R#connect_opts.opts),
ifaddr = translate_ip(R#connect_opts.ifaddr, Family)
}};
Error -> Error
end.
-con_opt([{raw,A,B,C}|Opts],R,As) ->
+con_opt([{raw,A,B,C}|Opts],#connect_opts{} = R,As) ->
con_opt([{raw,{A,B,C}}|Opts],R,As);
-con_opt([Opt | Opts], R, As) ->
+con_opt([Opt | Opts], #connect_opts{} = R, As) ->
case Opt of
{ip,IP} -> con_opt(Opts, R#connect_opts { ifaddr = IP }, As);
{ifaddr,IP} -> con_opt(Opts, R#connect_opts { ifaddr = IP }, As);
@@ -722,10 +723,10 @@ con_opt([Opt | Opts], R, As) ->
{Name,Val} when is_atom(Name) -> con_add(Name, Val, R, Opts, As);
_ -> {error, badarg}
end;
-con_opt([], R, _) ->
+con_opt([], #connect_opts{} = R, _) ->
{ok, R}.
-con_add(Name, Val, R, Opts, AllOpts) ->
+con_add(Name, Val, #connect_opts{} = R, Opts, AllOpts) ->
case add_opt(Name, Val, R#connect_opts.opts, AllOpts) of
{ok, SOpts} ->
con_opt(Opts, R#connect_opts { opts = SOpts }, AllOpts);
@@ -758,14 +759,15 @@ listen_options(Opts, Family) ->
case list_opt(Opts, BaseOpts, listen_options()) of
{ok, R} ->
{ok, R#listen_opts {
+ opts = lists:reverse(R#listen_opts.opts),
ifaddr = translate_ip(R#listen_opts.ifaddr, Family)
}};
Error -> Error
end.
-list_opt([{raw,A,B,C}|Opts], R, As) ->
+list_opt([{raw,A,B,C}|Opts], #listen_opts{} = R, As) ->
list_opt([{raw,{A,B,C}}|Opts], R, As);
-list_opt([Opt | Opts], R, As) ->
+list_opt([Opt | Opts], #listen_opts{} = R, As) ->
case Opt of
{ip,IP} -> list_opt(Opts, R#listen_opts { ifaddr = IP }, As);
{ifaddr,IP} -> list_opt(Opts, R#listen_opts { ifaddr = IP }, As);
@@ -791,10 +793,10 @@ list_opt([Opt | Opts], R, As) ->
{Name,Val} when is_atom(Name) -> list_add(Name, Val, R, Opts, As);
_ -> {error, badarg}
end;
-list_opt([], R, _SockOpts) ->
+list_opt([], #listen_opts{} = R, _SockOpts) ->
{ok, R}.
-list_add(Name, Val, R, Opts, As) ->
+list_add(Name, Val, #listen_opts{} = R, Opts, As) ->
case add_opt(Name, Val, R#listen_opts.opts, As) of
{ok, SOpts} ->
list_opt(Opts, R#listen_opts { opts = SOpts }, As);
@@ -816,14 +818,15 @@ udp_options(Opts, Family) ->
case udp_opt(Opts, #udp_opts { }, udp_options()) of
{ok, R} ->
{ok, R#udp_opts {
+ opts = lists:reverse(R#udp_opts.opts),
ifaddr = translate_ip(R#udp_opts.ifaddr, Family)
}};
Error -> Error
end.
-udp_opt([{raw,A,B,C}|Opts], R, As) ->
+udp_opt([{raw,A,B,C}|Opts], #udp_opts{} = R, As) ->
udp_opt([{raw,{A,B,C}}|Opts], R, As);
-udp_opt([Opt | Opts], R, As) ->
+udp_opt([Opt | Opts], #udp_opts{} = R, As) ->
case Opt of
{ip,IP} -> udp_opt(Opts, R#udp_opts { ifaddr = IP }, As);
{ifaddr,IP} -> udp_opt(Opts, R#udp_opts { ifaddr = IP }, As);
@@ -838,7 +841,7 @@ udp_opt([Opt | Opts], R, As) ->
BinNS = filename2binary(NS),
case prim_inet:is_sockopt_val(netns, BinNS) of
true ->
- list_opt(Opts, R#udp_opts { fd = [{netns,BinNS}] }, As);
+ udp_opt(Opts, R#udp_opts { fd = [{netns,BinNS}] }, As);
false ->
{error, badarg}
end;
@@ -848,10 +851,10 @@ udp_opt([Opt | Opts], R, As) ->
{Name,Val} when is_atom(Name) -> udp_add(Name, Val, R, Opts, As);
_ -> {error, badarg}
end;
-udp_opt([], R, _SockOpts) ->
+udp_opt([], #udp_opts{} = R, _SockOpts) ->
{ok, R}.
-udp_add(Name, Val, R, Opts, As) ->
+udp_add(Name, Val, #udp_opts{} = R, Opts, As) ->
case add_opt(Name, Val, R#udp_opts.opts, As) of
{ok, SOpts} ->
udp_opt(Opts, R#udp_opts { opts = SOpts }, As);
@@ -889,13 +892,16 @@ sctp_options() ->
sctp_options(Opts, Mod) ->
case sctp_opt(Opts, Mod, #sctp_opts{}, sctp_options()) of
{ok,#sctp_opts{ifaddr=undefined}=SO} ->
- {ok,SO#sctp_opts{ifaddr=Mod:translate_ip(?SCTP_DEF_IFADDR)}};
- {ok,_}=OK ->
- OK;
+ {ok,
+ SO#sctp_opts{
+ opts=lists:reverse(SO#sctp_opts.opts),
+ ifaddr=Mod:translate_ip(?SCTP_DEF_IFADDR)}};
+ {ok,SO} ->
+ {ok,SO#sctp_opts{opts=lists:reverse(SO#sctp_opts.opts)}};
Error -> Error
end.
-sctp_opt([Opt|Opts], Mod, R, As) ->
+sctp_opt([Opt|Opts], Mod, #sctp_opts{} = R, As) ->
case Opt of
{ip,IP} ->
sctp_opt_ifaddr(Opts, Mod, R, As, IP);
@@ -938,7 +944,7 @@ sctp_opt([], _Mod, #sctp_opts{ifaddr=IfAddr}=R, _SockOpts) ->
{ok, R}
end.
-sctp_opt(Opts, Mod, R, As, Name, Val) ->
+sctp_opt(Opts, Mod, #sctp_opts{} = R, As, Name, Val) ->
case add_opt(Name, Val, R#sctp_opts.opts, As) of
{ok,SocketOpts} ->
sctp_opt(Opts, Mod, R#sctp_opts{opts=SocketOpts}, As);
@@ -963,6 +969,8 @@ add_opt(Name, Val, Opts, As) ->
case lists:member(Name, As) of
true ->
case prim_inet:is_sockopt_val(Name, Val) of
+ true when Name =:= raw ->
+ {ok, [{Name,Val} | Opts]};
true ->
Opts1 = lists:keydelete(Name, 1, Opts),
{ok, [{Name,Val} | Opts1]};
@@ -1070,7 +1078,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, []) ->
@@ -1257,9 +1265,9 @@ open(FdO, Addr, Port, Opts, Protocol, Family, Type, Module)
Error ->
Error
end;
-open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module)
+open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module)
when is_integer(Fd) ->
- fdopen(Fd, Opts, Protocol, Family, Type, Module).
+ fdopen(Fd, Addr, Port, Opts, Protocol, Family, Type, Module).
bindx(S, [Addr], Port0) ->
{IP, Port} = set_bindx_port(Addr, Port0),
@@ -1298,12 +1306,35 @@ change_bindx_0_port({_IP, _Port}=Addr, _AssignedPort) ->
{'ok', socket()} | {'error', posix()}.
fdopen(Fd, Opts, Protocol, Family, Type, Module) ->
- case prim_inet:fdopen(Protocol, Family, Type, Fd) of
+ fdopen(Fd, any, 0, Opts, Protocol, Family, Type, Module).
+
+fdopen(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) ->
+ IsAnyAddr = (Addr == {0,0,0,0} orelse Addr == {0,0,0,0,0,0,0,0}
+ orelse Addr == any),
+ Bound = Port == 0 andalso IsAnyAddr,
+ case prim_inet:fdopen(Protocol, Family, Type, Fd, Bound) of
{ok, S} ->
case prim_inet:setopts(S, Opts) of
ok ->
- inet_db:register_socket(S, Module),
- {ok, S};
+ case if
+ Bound ->
+ %% We do not do any binding if default
+ %% port+addr options where given in order
+ %% to keep backwards compatability with
+ %% pre Erlang/TOP 17
+ {ok, ok};
+ is_list(Addr) ->
+ bindx(S, Addr, Port);
+ true ->
+ prim_inet:bind(S, Addr, Port)
+ end of
+ {ok, _} ->
+ inet_db:register_socket(S, Module),
+ {ok, S};
+ Error ->
+ prim_inet:close(S),
+ Error
+ end;
Error ->
prim_inet:close(S), Error
end;
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 5658c6b6cf..9f6c0f4624 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.0", "stdlib-2.0", "sasl-2.4"]}
+ {runtime_dependencies, ["erts-6.1.2", "stdlib-2.0", "sasl-2.4"]}
]
}.
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index f8f4cc1ec2..652f39c092 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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
@@ -17,9 +17,9 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17
+ [{<<"3\\.[0-9]+(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17
{<<"2\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R16
%% Down to - max one major revision back
- [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17
+ [{<<"3\\.[0-9]+(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17
{<<"2\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R16
}.
diff --git a/lib/kernel/src/net_adm.erl b/lib/kernel/src/net_adm.erl
index 3f5eac7822..2cdfb76417 100644
--- a/lib/kernel/src/net_adm.erl
+++ b/lib/kernel/src/net_adm.erl
@@ -89,18 +89,13 @@ names() ->
-spec names(Host) -> {ok, [{Name, Port}]} | {error, Reason} when
- Host :: atom() | string(),
+ Host :: atom() | string() | inet:ip_address(),
Name :: string(),
Port :: non_neg_integer(),
Reason :: address | file:posix().
names(Hostname) ->
- case inet:gethostbyname(Hostname) of
- {ok, {hostent, _Name, _ , _Af, _Size, [Addr | _]}} ->
- erl_epmd:names(Addr);
- Else ->
- Else
- end.
+ erl_epmd:names(Hostname).
-spec dns_hostname(Host) -> {ok, Name} | {error, Host} when
Host :: atom() | string(),
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.