From 3f8e6c24e8c2a77b1339d5ed416c288318dcff22 Mon Sep 17 00:00:00 2001 From: okumin Date: Sat, 2 Jul 2016 22:09:35 +0900 Subject: Remove a duplicated pattern matching in erl_epmd.erl `select_best_version` has the duplicated case. --- lib/kernel/src/erl_epmd.erl | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl index f8ef4a475d..e1154ef235 100644 --- a/lib/kernel/src/erl_epmd.erl +++ b/lib/kernel/src/erl_epmd.erl @@ -403,8 +403,6 @@ select_best_version(L1, _H1, _L2, H2) when L1 > H2 -> 0; select_best_version(_L1, H1, L2, _H2) when L2 > H1 -> 0; -select_best_version(_L1, H1, L2, _H2) when L2 > H1 -> - 0; select_best_version(_L1, H1, _L2, H2) -> erlang:min(H1, H2). -- cgit v1.2.3 From a0686ba8dec9c57f455fda4ee14e1f9954b8b434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Mart=C3=ADnez?= Date: Thu, 14 Jul 2016 12:52:10 +0200 Subject: Fix code_server crash when adding some code paths ERL-194 --- lib/kernel/src/code_server.erl | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 6174136507..1792f9e908 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -933,14 +933,20 @@ del_ebin(Dir) -> filename:join(del_ebin_1(filename:split(Dir))). del_ebin_1([Parent,App,"ebin"]) -> - Ext = archive_extension(), - case filename:basename(Parent, Ext) of - Parent -> - %% Plain directory. + case filename:basename(Parent) of + [] -> + %% Parent is the root directory [Parent,App]; - Archive -> - %% Archive. - [Archive] + _ -> + Ext = archive_extension(), + case filename:basename(Parent, Ext) of + Parent -> + %% Plain directory. + [Parent,App]; + Archive -> + %% Archive. + [Archive] + end end; del_ebin_1([H|T]) -> [H|del_ebin_1(T)]; -- cgit v1.2.3 From 84549af1c996657aedee1263afec28b21bfa42a4 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Thu, 14 Jul 2016 17:51:16 +0300 Subject: Respect -proto_dist switch while connection to EPMD Signed-off-by: Peter Lemenkov --- lib/kernel/src/erl_epmd.erl | 4 ++++ lib/kernel/src/inet_tcp_dist.erl | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl index f8ef4a475d..79a026ab67 100644 --- a/lib/kernel/src/erl_epmd.erl +++ b/lib/kernel/src/erl_epmd.erl @@ -103,6 +103,10 @@ names(EpmdAddr) -> register_node(Name, PortNo) -> register_node(Name, PortNo, inet). +register_node(Name, PortNo, inet_tcp) -> + register_node(Name, PortNo, inet); +register_node(Name, PortNo, inet6_tcp) -> + register_node(Name, PortNo, inet6); register_node(Name, PortNo, Family) -> gen_server:call(erl_epmd, {register, Name, PortNo, Family}, infinity). diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl index f91d7ef7c3..94bde55133 100644 --- a/lib/kernel/src/inet_tcp_dist.erl +++ b/lib/kernel/src/inet_tcp_dist.erl @@ -74,7 +74,7 @@ gen_listen(Driver, Name) -> TcpAddress = get_tcp_address(Driver, Socket), {_,Port} = TcpAddress#net_address.address, ErlEpmd = net_kernel:epmd_module(), - case ErlEpmd:register_node(Name, Port) of + case ErlEpmd:register_node(Name, Port, Driver) of {ok, Creation} -> {ok, {Socket, TcpAddress, Creation}}; Error -> -- cgit v1.2.3 From 96d877d53333e5031c7f751123593886819d7fc7 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 28 Jul 2016 08:58:44 +0200 Subject: Fix test suite compilation warnings --- lib/kernel/test/gen_sctp_SUITE.erl | 130 +++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 64 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl index f836b2aa94..d38e5a35e7 100644 --- a/lib/kernel/test/gen_sctp_SUITE.erl +++ b/lib/kernel/test/gen_sctp_SUITE.erl @@ -383,26 +383,28 @@ def_sndrcvinfo(Config) when is_list(Config) -> assoc_id=S2AssocId} = S2AssocChange = log_ok(gen_sctp:connect(S2, Loopback, P1, [])), ?LOGVAR(S2AssocChange), - case recv_event(log_ok(gen_sctp:recv(S1))) of - {Loopback,P2, - #sctp_assoc_change{ - state=comm_up, - error=0, - assoc_id=S1AssocId}} -> - ?LOGVAR(S1AssocId); - {Loopback,P2, - #sctp_paddr_change{ - state=addr_confirmed, - error=0, - assoc_id=S1AssocId}} -> - ?LOGVAR(S1AssocId), + S1AssocId = + case recv_event(log_ok(gen_sctp:recv(S1))) of {Loopback,P2, #sctp_assoc_change{ state=comm_up, error=0, - assoc_id=S1AssocId}} = - recv_event(log_ok(gen_sctp:recv(S1))) - end, + assoc_id=AssocId}} -> + AssocId; + {Loopback,P2, + #sctp_paddr_change{ + state=addr_confirmed, + error=0, + assoc_id=AssocId}} -> + {Loopback,P2, + #sctp_assoc_change{ + state=comm_up, + error=0, + assoc_id=AssocId}} = + recv_event(log_ok(gen_sctp:recv(S1))), + AssocId + end, + ?LOGVAR(S1AssocId), #sctp_sndrcvinfo{ ppid=17, context=0, timetolive=0} = %, assoc_id=S1AssocId} = @@ -1055,6 +1057,7 @@ peeloff(Config, SockOpts) when is_list(Config) -> Addr = {127,0,0,1}, Stream = 0, Timeout = 333, + StartTime = timestamp(), S1 = socket_open([{ifaddr,Addr}|SockOpts], Timeout), ?LOGVAR(S1), P1 = socket_call(S1, get_port), @@ -1077,7 +1080,7 @@ peeloff(Config, SockOpts) when is_list(Config) -> state=comm_up, assoc_id=AssocId2}}} -> AssocId2 after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, ?LOGVAR(S2Ai), S1Ai = @@ -1087,7 +1090,7 @@ peeloff(Config, SockOpts) when is_list(Config) -> state=comm_up, assoc_id=AssocId1}}} -> AssocId1 after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, ?LOGVAR(S1Ai), %% @@ -1095,13 +1098,13 @@ peeloff(Config, SockOpts) when is_list(Config) -> receive {S1,{Addr,P2,S1Ai,Stream,<<"Number one">>}} -> ok after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Number two">>}), receive {S2,{Addr,P1,S2Ai,Stream,<<"Number two">>}} -> ok after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, %% S3 = socket_peeloff(Socket1, S1Ai, SockOpts, Timeout), @@ -1120,31 +1123,31 @@ peeloff(Config, SockOpts) when is_list(Config) -> receive {S2,{Addr,P3,S2Ai,Stream,<<"Number three">>}} -> ok after Timeout -> - socket_bailout([S1,S2,S3]) + socket_bailout([S1,S2,S3], StartTime) end, socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Number four">>}), receive {S3,{Addr,P2,S3Ai,Stream,<<"Number four">>}} -> ok after Timeout -> - socket_bailout([S1,S2,S3]) + socket_bailout([S1,S2,S3], StartTime) end, %% inet:i(sctp), - socket_close_verbose(S1), - socket_close_verbose(S2), + socket_close_verbose(S1, StartTime), + socket_close_verbose(S2, StartTime), receive {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai_X}}} -> match_unless_solaris(S3Ai, S3Ai_X) after Timeout -> - socket_bailout([S3]) + socket_bailout([S3], StartTime) end, receive {S3,{Addr,P2,#sctp_assoc_change{state=shutdown_comp, assoc_id=S3Ai}}} -> ok after Timeout -> - socket_bailout([S3]) + socket_bailout([S3], StartTime) end, - socket_close_verbose(S3), + socket_close_verbose(S3, StartTime), [] = flush(), ok. @@ -1156,6 +1159,7 @@ buffers(Config) when is_list(Config) -> Addr = {127,0,0,1}, Stream = 1, Timeout = 3333, + StartTime = timestamp(), S1 = socket_open([{ip,Addr}], Timeout), ?LOGVAR(S1), P1 = socket_call(S1, get_port), @@ -1174,7 +1178,7 @@ buffers(Config) when is_list(Config) -> state=comm_up, assoc_id=AssocId2}}} -> AssocId2 after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, S1Ai = receive @@ -1183,7 +1187,7 @@ buffers(Config) when is_list(Config) -> state=comm_up, assoc_id=AssocId1}}} -> AssocId1 after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, %% socket_call(S1, {setopts,[{recbuf,Limit}]}), @@ -1197,22 +1201,22 @@ buffers(Config) when is_list(Config) -> receive {S1,{Addr,P2,S1Ai,Stream,Data}} -> ok after Timeout -> - socket_bailout([S1,S2]) + socket_bailout([S1,S2], StartTime) end, %% - socket_close_verbose(S1), + socket_close_verbose(S1, StartTime), receive {S2,{Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}}} -> ok after Timeout -> - socket_bailout([S2]) + socket_bailout([S2], StartTime) end, receive {S2,{Addr,P1,#sctp_assoc_change{state=shutdown_comp, assoc_id=S2Ai}}} -> ok after Timeout -> - socket_bailout([S2]) + socket_bailout([S2], StartTime) end, - socket_close_verbose(S2), + socket_close_verbose(S2, StartTime), [] = flush(), ok. @@ -1521,8 +1525,8 @@ socket_peeloff(Socket, AssocId, SocketOpts, Timeout) -> end, s_start(Starter, Timeout). -socket_close_verbose(S) -> - History = socket_history(socket_close(S)), +socket_close_verbose(S, StartTime) -> + History = socket_history(socket_close(S), StartTime), io:format("socket_close ~p:~n ~p.~n", [S,History]), History. @@ -1535,19 +1539,19 @@ socket_call(S, Request) -> %% socket_get(S, Key) -> %% s_req(S, {get,Key}). -socket_bailout([S|Ss]) -> - History = socket_history(socket_close(S)), +socket_bailout([S|Ss], StartTime) -> + History = socket_history(socket_close(S), StartTime), io:format("bailout ~p:~n ~p.~n", [S,History]), - socket_bailout(Ss); -socket_bailout([]) -> + socket_bailout(Ss, StartTime); +socket_bailout([], _) -> io:format("flush: ~p.~n", [flush()]), ct:fail(socket_bailout). -socket_history({State,Flush}) -> +socket_history({State,Flush}, StartTime) -> {lists:keysort( 2, lists:flatten( - [[{Key,Val} || Val <- Vals] + [[{Key,{TS-StartTime,Val}} || {TS,Val} <- Vals] || {Key,Vals} <- gb_trees:to_list(State)])), Flush}. @@ -1610,14 +1614,12 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> {Parent,Ref,exit} -> ok = gen_sctp:close(Socket), Key = exit, - Val = {now(),Socket}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, Socket, State), Parent ! {self(),Ref,{NewState,flush()}}; {Parent,Ref,{Msg}} -> Result = Handler(Msg), Key = req, - Val = {now(),{Msg,Result}}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Msg,Result}, State), Parent ! {self(),Ref,Result}, s_loop(Socket, Timeout, Parent, Handler, NewState); %% {Parent,Ref,{get,Key}} -> @@ -1627,16 +1629,15 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> {[#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}=SRI],Data}} when not is_tuple(Data) -> case gb_get({assoc_change,AssocId}, State) of - [{_,{Addr,Port, - #sctp_assoc_change{ - state=comm_up, - inbound_streams=Is}}}|_] + [{Addr,Port, + #sctp_assoc_change{ + state=comm_up, + inbound_streams=Is}}|_] when 0 =< Stream, Stream < Is-> ok; [] -> ok end, Key = {msg,AssocId,Stream}, - Val = {now(),{Addr,Port,SRI,Data}}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Addr,Port,SRI,Data}, State), Parent ! {self(),{Addr,Port,AssocId,Stream,Data}}, again(Socket), s_loop(Socket, Timeout, Parent, Handler, NewState); @@ -1647,13 +1648,12 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> [] -> ok end, Key = {assoc_change,AssocId}, - Val = {now(),{Addr,Port,SAC}}, case {gb_get(Key, State),St} of {[],_} -> ok; - {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],_} + {[{Addr,Port,#sctp_assoc_change{state=comm_up}}|_],_} when St =:= comm_lost; St =:= shutdown_comp -> ok end, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Addr,Port,SAC}, State), Parent ! {self(),{Addr,Port,SAC}}, again(Socket), s_loop(Socket, Timeout, Parent, Handler, NewState); @@ -1667,14 +1667,13 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> [] -> ok end, case {gb_get({assoc_change,AssocId}, State),St} of - {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],_} + {[{Addr,Port,#sctp_assoc_change{state=comm_up}}|_],_} when St =:= addr_available; St =:= addr_confirmed -> ok; {[],addr_confirmed} -> ok end, Key = {paddr_change,AssocId}, - Val = {now(),{Addr,Port,SPC}}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Addr,Port,SPC}, State), again(Socket), s_loop(Socket, Timeout, Parent, Handler, NewState); {sctp,Socket,Addr,Port, @@ -1684,12 +1683,11 @@ s_loop(Socket, Timeout, Parent, Handler, State) -> [] -> ok end, case gb_get({assoc_change,AssocId}, State) of - [{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_] -> ok; + [{Addr,Port,#sctp_assoc_change{state=comm_up}}|_] -> ok; [] -> ok end, Key = {shutdown_event,AssocId}, - Val = {now(),{Addr,Port}}, - NewState = gb_push(Key, Val, State), + NewState = gb_push(Key, {Addr,Port}, State), Parent ! {self(), {Addr,Port,SSE}}, again(Socket), s_loop(Socket, Timeout, Parent, Handler, NewState); @@ -1707,11 +1705,12 @@ again(Socket) -> end. gb_push(Key, Val, GBT) -> + TS = timestamp(), case gb_trees:lookup(Key, GBT) of none -> - gb_trees:insert(Key, [Val], GBT); + gb_trees:insert(Key, [{TS,Val}], GBT); {value,V} -> - gb_trees:update(Key, [Val|V], GBT) + gb_trees:update(Key, [{TS,Val}|V], GBT) end. gb_get(Key, GBT) -> @@ -1719,7 +1718,7 @@ gb_get(Key, GBT) -> none -> []; {value,V} -> - V + [Val || {_TS,Val} <- V] end. match_unless_solaris(A, B) -> @@ -1727,3 +1726,6 @@ match_unless_solaris(A, B) -> {unix,sunos} -> B; _ -> A = B end. + +timestamp() -> + erlang:monotonic_time(). -- cgit v1.2.3 From 2580e4f9e59baf4205f550f55392391668b441cd Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 28 Jul 2016 10:16:28 +0200 Subject: Test inet:getstat/1 dead for SCTP send --- lib/kernel/test/gen_sctp_SUITE.erl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl index d38e5a35e7..620ab235a0 100644 --- a/lib/kernel/test/gen_sctp_SUITE.erl +++ b/lib/kernel/test/gen_sctp_SUITE.erl @@ -117,7 +117,11 @@ xfer_min(Config) when is_list(Config) -> Stream = 0, Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>, Loopback = {127,0,0,1}, + StatOpts = + [recv_avg,recv_cnt,recv_max,recv_oct, + send_avg,send_cnt,send_max,send_oct], {ok,Sb} = gen_sctp:open([{type,seqpacket}]), + {ok,SbStat1} = inet:getstat(Sb, StatOpts), {ok,Pb} = inet:port(Sb), ok = gen_sctp:listen(Sb, true), @@ -212,6 +216,8 @@ xfer_min(Config) when is_list(Config) -> assoc_id=SbAssocId}} = recv_event(log_ok(gen_sctp:recv(Sb, infinity))), ok = gen_sctp:close(Sa), + {ok,SbStat2} = inet:getstat(Sb, StatOpts), + [] = filter_stat_eq(SbStat1, SbStat2), ok = gen_sctp:close(Sb), receive @@ -220,6 +226,18 @@ xfer_min(Config) when is_list(Config) -> end, ok. +filter_stat_eq([], []) -> + []; +filter_stat_eq([{Tag,Val1}=Stat|SbStat1], [{Tag,Val2}|SbStat2]) -> + if + Val1 == Val2 -> + [Stat|filter_stat_eq(SbStat1, SbStat2)]; + true -> + filter_stat_eq(SbStat1, SbStat2) + end. + + + %% Minimal data transfer in active mode. xfer_active(Config) when is_list(Config) -> Timeout = 2000, -- cgit v1.2.3 From f1ca806498bc7f7dad96f2c7e188fdc55e0124cb Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 14 Jul 2016 12:24:49 +0200 Subject: kernel: Use ^D as eot for os:cmd on unix platforms This is needed as doing only an 'exit' will only exit the program, but any children started in the program that have stdout/stderr still open will keep the port open until they terminate. i.e. os:cmd("while true; do echo sleep 1; sleep 1; done&"). would block os:cmd forever because the while loop keeps its copies of stdout/stderr open forever. It could be argued that this is correct behaviour, and it is the way it works on windows, but changing this breaks backwards compatability for os:cmd which is not acceptable. --- lib/kernel/src/os.erl | 48 ++++++++++++++++++++++++++++++++------------ lib/kernel/test/os_SUITE.erl | 22 +++++++++++++++++--- 2 files changed, 54 insertions(+), 16 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index f0ad26b1f2..81b70a7fee 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -226,11 +226,13 @@ extensions() -> Command :: atom() | io_lib:chars(). cmd(Cmd) -> validate(Cmd), - {SpawnCmd, SpawnOpts, SpawnInput} = mk_cmd(os:type(), Cmd), + {SpawnCmd, SpawnOpts, SpawnInput, Eot} = mk_cmd(os:type(), Cmd), Port = open_port({spawn, SpawnCmd}, [binary, stderr_to_stdout, - stream, in, eof, hide | SpawnOpts]), + stream, in, hide | SpawnOpts]), + MonRef = erlang:monitor(port, Port), true = port_command(Port, SpawnInput), - Bytes = get_data(Port, []), + Bytes = get_data(Port, MonRef, Eot, []), + demonitor(MonRef, [flush]), String = unicode:characters_to_list(Bytes), if %% Convert to unicode list if possible otherwise return bytes is_list(String) -> String; @@ -243,7 +245,7 @@ mk_cmd({win32,Wtype}, Cmd) -> {false,_} -> lists:concat(["cmd /c", Cmd]); {Cspec,_} -> lists:concat([Cspec," /c",Cmd]) end, - {Command, [], []}; + {Command, [], [], <<>>}; mk_cmd(OsType,Cmd) when is_atom(Cmd) -> mk_cmd(OsType, atom_to_list(Cmd)); mk_cmd(_,Cmd) -> @@ -252,7 +254,8 @@ mk_cmd(_,Cmd) -> {"/bin/sh -s unix:cmd", [out], %% We insert a new line after the command, in case the command %% contains a comment character. - ["(", unicode:characters_to_binary(Cmd), "\n); exit\n"]}. + ["(", unicode:characters_to_binary(Cmd), "\n); echo \"\^D\"\n"], + <<$\^D>>}. validate(Atom) when is_atom(Atom) -> ok; @@ -267,16 +270,18 @@ validate1([List|Rest]) when is_list(List) -> validate1([]) -> ok. -get_data(Port, Sofar) -> +get_data(Port, MonRef, Eot, Sofar) -> receive {Port, {data, Bytes}} -> - get_data(Port, [Sofar,Bytes]); - {Port, eof} -> - Port ! {self(), close}, - receive - {Port, closed} -> - true - end, + case eot(Bytes, Eot) of + more -> + get_data(Port, MonRef, Eot, [Sofar,Bytes]); + Last -> + Port ! {self(), close}, + flush_until_closed(Port), + iolist_to_binary([Sofar, Last]) + end; + {'DOWN', MonRef, _, _ , _} -> receive {'EXIT', Port, _} -> ok @@ -285,3 +290,20 @@ get_data(Port, Sofar) -> end, iolist_to_binary(Sofar) end. + +eot(_Bs, <<>>) -> + more; +eot(Bs, Eot) -> + case binary:match(Bs, Eot) of + nomatch -> more; + {Pos, _} -> + binary:part(Bs,{0, Pos}) + end. + +flush_until_closed(Port) -> + receive + {Port, {data, _Bytes}} -> + flush_until_closed(Port); + {Port, closed} -> + true + end. diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 2a1e5016ec..8f3e511941 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -24,7 +24,8 @@ init_per_testcase/2,end_per_testcase/2]). -export([space_in_cwd/1, quoting/1, cmd_unicode/1, space_in_name/1, bad_command/1, find_executable/1, unix_comment_in_command/1, deep_list_command/1, - large_output_command/1, perf_counter_api/1]). + large_output_command/1, background_command/0, background_command/1, + perf_counter_api/1]). -include_lib("common_test/include/ct.hrl"). @@ -35,7 +36,7 @@ suite() -> all() -> [space_in_cwd, quoting, cmd_unicode, space_in_name, bad_command, find_executable, unix_comment_in_command, deep_list_command, - large_output_command, perf_counter_api]. + large_output_command, background_command, perf_counter_api]. groups() -> []. @@ -52,6 +53,13 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +init_per_testcase(background_command, Config) -> + case os:type() of + {win32, _} -> + {skip,"Should not work on windows"}; + _ -> + Config + end; init_per_testcase(_TC,Config) -> Config. @@ -261,13 +269,21 @@ deep_list_command(Config) when is_list(Config) -> %% FYI: [$e, $c, "ho"] =:= io_lib:format("ec~s", ["ho"]) ok. -%% Test to take sure that the correct data is +%% Test to make sure that the correct data is %% received when doing large commands. large_output_command(Config) when is_list(Config) -> %% Maximum allowed on windows is 8192, so we test well below that AAA = lists:duplicate(7000, $a), comp(AAA,os:cmd("echo " ++ AAA)). +%% Test that it is possible on unix to start a background task using os:cmd. +background_command() -> + [{timetrap, {seconds, 5}}]. +background_command(_Config) -> + %% This testcase fails when the os:cmd takes + %% longer then the 5 second timeout + os:cmd("sleep 10&"). + %% Test that the os:perf_counter api works as expected perf_counter_api(_Config) -> -- cgit v1.2.3 From 796bf022df397d09494d6198102d203d01efc8f6 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Mon, 8 Aug 2016 16:36:36 +0200 Subject: Prepare release --- lib/kernel/doc/src/notes.xml | 18 ++++++++++++++++++ lib/kernel/vsn.mk | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index f37433110c..0e3914b083 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,24 @@

This document describes the changes made to the Kernel application.

+
Kernel 5.0.1 + +
Fixed Bugs and Malfunctions + + +

+ Fix a os:cmd bug where creating a background job using + & would cause os:cmd to hang until the background job + terminated or closed its stdout and stderr file + descriptors. This bug has existed from kernel 5.0.

+

+ Own Id: OTP-13741

+
+
+
+ +
+
Kernel 5.0
Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index e7d422d03c..e88e4f9170 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.0 +KERNEL_VSN = 5.0.1 -- cgit v1.2.3 From f508378290a8b1cac4f54d9a9d6f1ce61dcad800 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Tue, 9 Aug 2016 21:37:16 +0100 Subject: zlib: Add test case for inflateGetDictionary --- lib/kernel/test/zlib_SUITE.erl | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl index f8257bd20c..4720a7f5ea 100644 --- a/lib/kernel/test/zlib_SUITE.erl +++ b/lib/kernel/test/zlib_SUITE.erl @@ -83,7 +83,7 @@ groups() -> [api_open_close, api_deflateInit, api_deflateSetDictionary, api_deflateReset, api_deflateParams, api_deflate, api_deflateEnd, - api_inflateInit, api_inflateSetDictionary, + api_inflateInit, api_inflateSetDictionary, api_inflateGetDictionary, api_inflateSync, api_inflateReset, api_inflate, api_inflateChunk, api_inflateEnd, api_setBufsz, api_getBufsz, api_crc32, api_adler32, api_getQSize, api_un_compress, api_un_zip, @@ -288,6 +288,30 @@ api_inflateSetDictionary(Config) when is_list(Config) -> ?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z1,Dict)), ?m(ok, zlib:close(Z1)). +%% Test inflateGetDictionary. +api_inflateGetDictionary(Config) when is_list(Config) -> + % Compress payload using custom dictionary + Z1 = zlib:open(), + ?m(ok, zlib:deflateInit(Z1)), + Dict = <<"foobar barfoo foo bar far boo">>, + ?m(_, zlib:deflateSetDictionary(Z1, Dict)), + Payload = <<"foobarbarbar">>, + Compressed = zlib:deflate(Z1, Payload, finish), + ?m(ok, zlib:close(Z1)), + + % Decompress and test dictionary extraction + Z2 = zlib:open(), + ?m(ok, zlib:inflateInit(Z2)), + ?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z2))), + ?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z2, Dict)), + ?m({'EXIT',{{need_dictionary,_},_}}, zlib:inflate(Z2, Compressed)), + ?m(ok, zlib:inflateSetDictionary(Z2, Dict)), + ?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z2))), + ?m(Payload, iolist_to_binary(zlib:inflate(Z2, Compressed))), + ?m(ok, zlib:close(Z2)), + ?m(?BARG, zlib:inflateSetDictionary(Z2, Dict)), + ok. + %% Test inflateSync. api_inflateSync(Config) when is_list(Config) -> {skip,"inflateSync/1 sucks"}. -- cgit v1.2.3 From 1def6a4b0eeb5d5a78fd76e97a5b7b4bcd06f185 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 11 Aug 2016 17:18:24 +0200 Subject: kernel: Cleanup code with fancy record syntax --- lib/kernel/src/net_kernel.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl index ac19f4935b..6687d64787 100644 --- a/lib/kernel/src/net_kernel.erl +++ b/lib/kernel/src/net_kernel.erl @@ -384,7 +384,7 @@ init({Name, LongOrShortNames, TickT, CleanHalt}) -> connections = ets:new(sys_dist,[named_table, protected, - {keypos, 2}]), + {keypos, #connection.node}]), listen = Listeners, allowed = [], verbose = 0 -- cgit v1.2.3 From b1b0fe831e1e3a048f09db0c6b0a601e0db62779 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 2 Jun 2016 17:50:41 +0200 Subject: kernel: Refactor dist_util:con_loop by separating the constant values into tuple ConData. and that exposed the fact that TcpAddress and MyNode where not used. --- lib/kernel/src/dist_util.erl | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index 47d0c1b861..8509a01608 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -350,15 +350,13 @@ connection(#hs_data{other_node = Node, mark_nodeup(HSData,Address), case FPostNodeup(Socket) of ok -> - con_loop(HSData#hs_data.kernel_pid, - Node, - Socket, - Address, - HSData#hs_data.this_node, - PType, - #tick{}, - HSData#hs_data.mf_tick, - HSData#hs_data.mf_getstat); + con_loop({HSData#hs_data.kernel_pid, + Node, + Socket, + PType, + HSData#hs_data.mf_tick, + HSData#hs_data.mf_getstat}, + #tick{}); _ -> ?shutdown2(Node, connection_setup_failed) end; @@ -454,8 +452,8 @@ mark_nodeup(#hs_data{kernel_pid = Kernel, ?shutdown(Node) end. -con_loop(Kernel, Node, Socket, TcpAddress, - MyNode, Type, Tick, MFTick, MFGetstat) -> +con_loop({Kernel, Node, Socket, Type, MFTick, MFGetstat}=ConData, + Tick) -> receive {tcp_closed, Socket} -> ?shutdown2(Node, connection_closed); @@ -468,15 +466,12 @@ con_loop(Kernel, Node, Socket, TcpAddress, _ -> ignore_it end, - con_loop(Kernel, Node, Socket, TcpAddress, MyNode, Type, - Tick, MFTick, MFGetstat); + con_loop(ConData, Tick); {Kernel, tick} -> case send_tick(Socket, Tick, Type, MFTick, MFGetstat) of {ok, NewTick} -> - con_loop(Kernel, Node, Socket, TcpAddress, - MyNode, Type, NewTick, MFTick, - MFGetstat); + con_loop(ConData, NewTick); {error, not_responding} -> error_msg("** Node ~p not responding **~n" "** Removing (timedout) connection **~n", @@ -489,10 +484,7 @@ con_loop(Kernel, Node, Socket, TcpAddress, case MFGetstat(Socket) of {ok, Read, Write, _} -> From ! {self(), get_status, {ok, Read, Write}}, - con_loop(Kernel, Node, Socket, TcpAddress, - MyNode, - Type, Tick, - MFTick, MFGetstat); + con_loop(ConData, Tick); _ -> ?shutdown2(Node, get_status_failed) end -- cgit v1.2.3 From fec9c26cf1746898a76043df7f2d0bebfa36c927 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 9 Aug 2016 20:05:37 +0200 Subject: kernel: Export inet types socket_getopt and socket_setopt --- lib/kernel/doc/src/inet.xml | 9 ++++++--- lib/kernel/src/inet.erl | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index c0dce2f50c..8cc21bf3e2 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -150,6 +150,12 @@ fe80::204:acff:fe17:bf38 + + + + + + @@ -327,8 +333,6 @@ fe80::204:acff:fe17:bf38 Get one or more options for a socket. - -

Gets one or more options for a socket. For a list of available options, see @@ -580,7 +584,6 @@ get_tcpi_sacked(Sock) -> Set one or more options for a socket. -

Sets one or more options for a socket.

The following options are available:

diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index a91a6ed517..75dd800c6b 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -75,6 +75,7 @@ -export_type([address_family/0, hostent/0, hostname/0, ip4_address/0, ip6_address/0, ip_address/0, port_number/0, local_address/0, socket_address/0, returned_non_ip_address/0, + socket_setopt/0, socket_getopt/0, posix/0, socket/0, stat_option/0]). %% imports -import(lists, [append/1, duplicate/2, filter/2, foldl/3]). -- cgit v1.2.3 From 53a487cd5019e7f7e3abee6b4a5e2d0b05aa34c6 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 4 Jul 2016 11:56:20 +0200 Subject: erts/kernel: Fix code loading deadlock during init:stop When init:stop is called it walks the application hierarchy and terminates each process. Some of these processes may do something while terminating and sometimes that something needs to load some new code in order to work. When this happens the code_server could just be in the process of terminating or the erl_prim_loader could be active. In both these cases the request to load the new code would cause a deadlock in the termination of the system. This commit fixes this by init rejecting attempts to load new code when init:stop has been called and fixing a termination race in the code_server. This however means that the process that tried to do something when told to terminate (for instance logging that it is terminating) will crash instead of loading the code. --- lib/kernel/src/code_server.erl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 6174136507..c7d0c3299a 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -135,10 +135,14 @@ split_paths([], _S, Path, Paths) -> -spec call(term()) -> term(). call(Req) -> + Ref = erlang:monitor(process, ?MODULE), ?MODULE ! {code_call, self(), Req}, receive {?MODULE, Reply} -> - Reply + erlang:demonitor(Ref,[flush]), + Reply; + {'DOWN',Ref,process,_,_} -> + exit({'DOWN',code_server,Req}) end. reply(Pid, Res) -> -- cgit v1.2.3 From 8f03f5dc4c8bc2804acfaec5d3558456d27282b0 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 14 Jun 2016 18:42:33 +0200 Subject: kernel: Add net_kernel:setopts/2 and getopts/2 --- lib/kernel/include/dist_util.hrl | 8 ++- lib/kernel/src/dist_util.erl | 22 ++++++- lib/kernel/src/inet6_tcp_dist.erl | 7 +++ lib/kernel/src/inet_tcp_dist.erl | 27 ++++++-- lib/kernel/src/net_kernel.erl | 126 +++++++++++++++++++++++++++++++++++++- 5 files changed, 179 insertions(+), 11 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/include/dist_util.hrl b/lib/kernel/include/dist_util.hrl index 43e50d4325..320e916c04 100644 --- a/lib/kernel/include/dist_util.hrl +++ b/lib/kernel/include/dist_util.hrl @@ -63,7 +63,7 @@ f_getll, %% Get low level port or pid. f_address, %% The address of the "socket", %% generated from Socket,Node - %% These two are used in the tick loop, + %% These three are used in the tick loop, %% so they are not fun's to avoid holding old code. mf_tick, %% Takes the socket as parameters and %% sends a tick, this is no fun, it @@ -74,7 +74,11 @@ %% {ok, RecvCnt, SendCnt, SendPend} for %% a given socket. This is a {M,F}, %% returning {error, Reason on failure} - request_type = normal + request_type = normal, + + %% New in kernel-5.1 (OTP 19.1): + mf_setopts, %% netkernel:setopts on active connection + mf_getopts %% netkernel:getopts on active connection }). diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index 8509a01608..d8e4705e6b 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -355,7 +355,9 @@ connection(#hs_data{other_node = Node, Socket, PType, HSData#hs_data.mf_tick, - HSData#hs_data.mf_getstat}, + HSData#hs_data.mf_getstat, + HSData#hs_data.mf_setopts, + HSData#hs_data.mf_getopts}, #tick{}); _ -> ?shutdown2(Node, connection_setup_failed) @@ -452,7 +454,7 @@ mark_nodeup(#hs_data{kernel_pid = Kernel, ?shutdown(Node) end. -con_loop({Kernel, Node, Socket, Type, MFTick, MFGetstat}=ConData, +con_loop({Kernel, Node, Socket, Type, MFTick, MFGetstat, MFSetOpts, MFGetOpts}=ConData, Tick) -> receive {tcp_closed, Socket} -> @@ -487,7 +489,21 @@ con_loop({Kernel, Node, Socket, Type, MFTick, MFGetstat}=ConData, con_loop(ConData, Tick); _ -> ?shutdown2(Node, get_status_failed) - end + end; + {From, Ref, {setopts, Opts}} -> + Ret = case MFSetOpts of + undefined -> {error, enotsup}; + _ -> MFSetOpts(Socket, Opts) + end, + From ! {Ref, Ret}, + con_loop(ConData, Tick); + {From, Ref, {getopts, Opts}} -> + Ret = case MFGetOpts of + undefined -> {error, enotsup}; + _ -> MFGetOpts(Socket, Opts) + end, + From ! {Ref, Ret}, + con_loop(ConData, Tick) end. diff --git a/lib/kernel/src/inet6_tcp_dist.erl b/lib/kernel/src/inet6_tcp_dist.erl index 3aa61973af..9b6c2745d5 100644 --- a/lib/kernel/src/inet6_tcp_dist.erl +++ b/lib/kernel/src/inet6_tcp_dist.erl @@ -24,6 +24,7 @@ -export([listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1, is_node_name/1]). +-export([setopts/2, getopts/2]). %% ------------------------------------------------------------ %% Select this protocol based on node name @@ -72,3 +73,9 @@ close(Socket) -> is_node_name(Node) when is_atom(Node) -> inet_tcp_dist:is_node_name(Node). + +setopts(S, Opts) -> + inet_tcp_dist:setopts(S, Opts). + +getopts(S, Opts) -> + inet_tcp_dist:getopts(S, Opts). diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl index f91d7ef7c3..3ca62cc1f1 100644 --- a/lib/kernel/src/inet_tcp_dist.erl +++ b/lib/kernel/src/inet_tcp_dist.erl @@ -24,13 +24,16 @@ -export([listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1, is_node_name/1]). +%% Optional +-export([setopts/2, getopts/2]). + %% Generalized dist API -export([gen_listen/2, gen_accept/2, gen_accept_connection/6, gen_setup/6, gen_select/2]). %% internal exports --export([accept_loop/3,do_accept/7,do_setup/7,getstat/1]). +-export([accept_loop/3,do_accept/7,do_setup/7,getstat/1,tick/2]). -import(error_logger,[error_msg/2]). @@ -215,8 +218,10 @@ do_accept(Driver, Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> inet:getll(S) end, f_address = fun(S, Node) -> get_remote_id(Driver, S, Node) end, - mf_tick = fun(S) -> tick(Driver, S) end, - mf_getstat = fun ?MODULE:getstat/1 + mf_tick = fun(S) -> ?MODULE:tick(Driver, S) end, + mf_getstat = fun ?MODULE:getstat/1, + mf_setopts = fun ?MODULE:setopts/2, + mf_getopts = fun ?MODULE:getopts/2 }, dist_util:handshake_other_started(HSData); {false,IP} -> @@ -320,6 +325,7 @@ do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> {packet, 4}, nodelay()]) end, + f_getll = fun inet:getll/1, f_address = fun(_,_) -> @@ -329,9 +335,11 @@ do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> protocol = tcp, family = AddressFamily} end, - mf_tick = fun(S) -> tick(Driver, S) end, + mf_tick = fun(S) -> ?MODULE:tick(Driver, S) end, mf_getstat = fun ?MODULE:getstat/1, - request_type = Type + request_type = Type, + mf_setopts = fun ?MODULE:setopts/2, + mf_getopts = fun ?MODULE:getopts/2 }, dist_util:handshake_we_started(HSData); _ -> @@ -492,3 +500,12 @@ split_stat([], R, W, P) -> {ok, R, W, P}. +setopts(S, Opts) -> + case [Opt || {K,_}=Opt <- Opts, + K =:= active orelse K =:= deliver orelse K =:= packet] of + [] -> inet:setopts(S,Opts); + Opts1 -> {error, {badopts,Opts1}} + end. + +getopts(S, Opts) -> + inet:getopts(S, Opts). diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl index 6687d64787..0c679e7349 100644 --- a/lib/kernel/src/net_kernel.erl +++ b/lib/kernel/src/net_kernel.erl @@ -59,6 +59,8 @@ connect_node/1, monitor_nodes/1, monitor_nodes/2, + setopts/2, + getopts/2, start/1, stop/0]). @@ -111,7 +113,7 @@ }). -record(listen, { - listen, %% listen pid + listen, %% listen socket accept, %% accepting pid address, %% #net_address module %% proto module @@ -554,6 +556,38 @@ handle_call({new_ticktime,_T,_TP}, #state{tick = #tick_change{time = T}} = State) -> async_reply({reply, {ongoing_change_to, T}, State}, From); +handle_call({setopts, new, Opts}, From, State) -> + Ret = setopts_new(Opts, State), + async_reply({reply, Ret, State}, From); + +handle_call({setopts, Node, Opts}, From, State) -> + Return = + case ets:lookup(sys_dist, Node) of + [Conn] when Conn#connection.state =:= up -> + case call_owner(Conn#connection.owner, {setopts, Opts}) of + {ok, Ret} -> Ret; + _ -> {error, noconnection} + end; + + _ -> + {error, noconnection} + end, + async_reply({reply, Return, State}, From); + +handle_call({getopts, Node, Opts}, From, State) -> + Return = + case ets:lookup(sys_dist, Node) of + [Conn] when Conn#connection.state =:= up -> + case call_owner(Conn#connection.owner, {getopts, Opts}) of + {ok, Ret} -> Ret; + _ -> {error, noconnection} + end; + + _ -> + {error, noconnection} + end, + async_reply({reply, Return, State}, From); + handle_call(_Msg, _From, State) -> {noreply, State}. @@ -1608,3 +1642,93 @@ async_gen_server_reply(From, Msg) -> {'EXIT', _} -> ok end. + +call_owner(Owner, Msg) -> + Mref = monitor(process, Owner), + Owner ! {self(), Mref, Msg}, + receive + {Mref, Reply} -> + erlang:demonitor(Mref, [flush]), + {ok, Reply}; + {'DOWN', Mref, _, _, _} -> + error + end. + + +-spec setopts(Node, Options) -> ok | {error, Reason} | ignored when + Node :: node() | new, + Options :: [inet:socket_setopt()], + Reason :: inet:posix() | noconnection. + +setopts(Node, Opts) when is_atom(Node), is_list(Opts) -> + request({setopts, Node, Opts}). + +setopts_new(Opts, State) -> + %% First try setopts on listening socket(s) + %% Bail out on failure. + %% If successful, we are pretty sure Opts are ok + %% and we continue with config params and pending connections. + case setopts_on_listen(Opts, State#state.listen) of + ok -> + setopts_new_1(Opts); + Fail -> Fail + end. + +setopts_on_listen(_, []) -> ok; +setopts_on_listen(Opts, [#listen {listen = LSocket, module = Mod} | T]) -> + try Mod:setopts(LSocket, Opts) of + ok -> + setopts_on_listen(Opts, T); + Fail -> Fail + catch + error:undef -> {error, enotsup} + end. + +setopts_new_1(Opts) -> + ConnectOpts = case application:get_env(kernel, inet_dist_connect_options) of + {ok, CO} -> CO; + _ -> [] + end, + application:set_env(kernel, inet_dist_connect_options, + merge_opts(Opts,ConnectOpts)), + ListenOpts = case application:get_env(kernel, inet_dist_listen_options) of + {ok, LO} -> LO; + _ -> [] + end, + application:set_env(kernel, inet_dist_listen_options, + merge_opts(Opts, ListenOpts)), + case lists:keyfind(nodelay, 1, Opts) of + {nodelay, ND} when is_boolean(ND) -> + application:set_env(kernel, dist_nodelay, ND); + _ -> ignore + end, + + %% Update any pending connections + PendingConns = ets:select(sys_dist, [{'_', + [{'=/=',{element,#connection.state,'$_'},up}], + ['$_']}]), + lists:foreach(fun(#connection{state = pending, owner = Owner}) -> + call_owner(Owner, {setopts, Opts}); + (#connection{state = up_pending, pending_owner = Owner}) -> + call_owner(Owner, {setopts, Opts}); + (_) -> ignore + end, PendingConns), + ok. + +merge_opts([], B) -> + B; +merge_opts([H|T], B0) -> + {Key, _} = H, + B1 = lists:filter(fun({K,_}) -> K =/= Key end, B0), + merge_opts(T, [H | B1]). + +-spec getopts(Node, Options) -> + {'ok', OptionValues} | {'error', Reason} | ignored when + Node :: node(), + Options :: [inet:socket_getopt()], + OptionValues :: [inet:socket_setopt()], + Reason :: inet:posix() | noconnection. + +getopts(Node, Opts) when is_atom(Node), is_list(Opts) -> + request({getopts, Node, Opts}). + -- cgit v1.2.3 From 0aef8a3ea46834e1a943d4ac7981802a6146bdd4 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 15 Aug 2016 16:42:00 +0200 Subject: kernel: Accept and convert old hs_data record --- lib/kernel/src/dist_util.erl | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index d8e4705e6b..8d2fc4d4b7 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -143,7 +143,11 @@ handshake_other_started(#hs_data{request_type=ReqType}=HSData0) -> ChallengeB = recv_challenge_reply(HSData, ChallengeA, MyCookie), send_challenge_ack(HSData, gen_digest(ChallengeB, HisCookie)), ?debug({dist_util, self(), accept_connection, Node}), - connection(HSData). + connection(HSData); + +handshake_other_started(OldHsData) when element(1,OldHsData) =:= hs_data -> + handshake_other_started(convert_old_hsdata(OldHsData)). + %% %% check if connecting node is allowed to connect @@ -330,7 +334,20 @@ handshake_we_started(#hs_data{request_type=ReqType, gen_digest(ChallengeA,HisCookie)), reset_timer(NewHSData#hs_data.timer), recv_challenge_ack(NewHSData, MyChallenge, MyCookie), - connection(NewHSData). + connection(NewHSData); + +handshake_we_started(OldHsData) when element(1,OldHsData) =:= hs_data -> + handshake_we_started(convert_old_hsdata(OldHsData)). + +convert_old_hsdata({hs_data, KP, ON, TN, S, T, TF, A, OV, OF, OS, FS, FR, + FS_PRE, FS_POST, FG, FA, MFT, MFG, RT}) -> + #hs_data{ + kernel_pid = KP, other_node = ON, this_node = TN, socket = S, timer = T, + this_flags = TF, allowed = A, other_version = OV, other_flags = OF, + other_started = OS, f_send = FS, f_recv = FR, f_setopts_pre_nodeup = FS_PRE, + f_setopts_post_nodeup = FS_POST, f_getll = FG, f_address = FA, + mf_tick = MFT, mf_getstat = MFG, request_type = RT}. + %% -------------------------------------------------------------- %% The connection has been established. -- cgit v1.2.3 From 69645a467d7fe91b38265f9ff4a6e7f192580a2d Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 7 Jun 2016 19:28:41 +0200 Subject: kernel: Add erl_distribution_SUITE:setopts to test net_kernel:setopts and getopts. --- lib/kernel/test/erl_distribution_SUITE.erl | 163 +++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index eb58e92224..e43be77428 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -25,6 +25,7 @@ init_per_group/2,end_per_group/2]). -export([tick/1, tick_change/1, illegal_nodenames/1, hidden_node/1, + setopts/1, table_waste/1, net_setuptime/1, inet_dist_options_options/1, @@ -42,6 +43,8 @@ -export([get_socket_priorities/0, tick_cli_test/1, tick_cli_test1/1, tick_serv_test/2, tick_serv_test1/1, + run_remote_test/1, + setopts_do/2, keep_conn/1, time_ping/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -66,6 +69,7 @@ suite() -> all() -> [tick, tick_change, illegal_nodenames, hidden_node, + setopts, table_waste, net_setuptime, inet_dist_options_options, {group, monitor_nodes}]. @@ -282,6 +286,165 @@ tick_cli_test1(Node) -> end end. +setopts(Config) when is_list(Config) -> + register(setopts_regname, self()), + [N1,N2,N3,N4] = get_nodenames(4, setopts), + + {_N1F,Port1} = start_node_unconnected(N1, ?MODULE, run_remote_test, + ["setopts_do", atom_to_list(node()), "1", "ping"]), + 0 = wait_for_port_exit(Port1), + + {_N2F,Port2} = start_node_unconnected(N2, ?MODULE, run_remote_test, + ["setopts_do", atom_to_list(node()), "2", "ping"]), + 0 = wait_for_port_exit(Port2), + + {ok, LSock} = gen_tcp:listen(0, [{packet,2}, {active,false}]), + {ok, LTcpPort} = inet:port(LSock), + + {N3F,Port3} = start_node_unconnected(N3, ?MODULE, run_remote_test, + ["setopts_do", atom_to_list(node()), + "1", integer_to_list(LTcpPort)]), + wait_and_connect(LSock, N3F, Port3), + 0 = wait_for_port_exit(Port3), + + {N4F,Port4} = start_node_unconnected(N4, ?MODULE, run_remote_test, + ["setopts_do", atom_to_list(node()), + "2", integer_to_list(LTcpPort)]), + wait_and_connect(LSock, N4F, Port4), + 0 = wait_for_port_exit(Port4), + + ok. + +wait_and_connect(LSock, NodeName, NodePort) -> + {ok, Sock} = gen_tcp:accept(LSock), + {ok, "Connect please"} = gen_tcp:recv(Sock, 0), + flush_from_port(NodePort), + pong = net_adm:ping(NodeName), + gen_tcp:send(Sock, "Connect done"), + gen_tcp:close(Sock). + + +flush_from_port(Port) -> + flush_from_port(Port, 10). + +flush_from_port(Port, Timeout) -> + receive + {Port,{data,String}} -> + io:format("~p: ~s\n", [Port, String]), + flush_from_port(Port, Timeout) + after Timeout -> + timeout + end. + +wait_for_port_exit(Port) -> + case (receive M -> M end) of + {Port,{exit_status,Status}} -> + Status; + {Port,{data,String}} -> + io:format("~p: ~s\n", [Port, String]), + wait_for_port_exit(Port) + end. + +run_remote_test([FuncStr, TestNodeStr | Args]) -> + Status = try + io:format("Node ~p started~n", [node()]), + TestNode = list_to_atom(TestNodeStr), + io:format("Node ~p spawning function ~p~n", [node(), FuncStr]), + {Pid,Ref} = spawn_monitor(?MODULE, list_to_atom(FuncStr), [TestNode, Args]), + io:format("Node ~p waiting for function ~p~n", [node(), FuncStr]), + receive + {'DOWN', Ref, process, Pid, normal} -> + 0; + Other -> + io:format("Node ~p got unexpected msg: ~p\n",[node(), Other]), + 1 + end + catch + C:E -> + io:format("Node ~p got EXCEPTION ~p:~p\nat ~p\n", + [node(), C, E, erlang:get_stacktrace()]), + 2 + end, + io:format("Node ~p doing halt(~p).\n",[node(), Status]), + erlang:halt(Status). + +% Do the actual test on the remote node +setopts_do(TestNode, [OptNr, ConnectData]) -> + [] = nodes(), + {Opt, Val} = opt_from_nr(OptNr), + ok = net_kernel:setopts(new, [{Opt, Val}]), + + [] = nodes(), + {error, noconnection} = net_kernel:getopts(TestNode, [Opt]), + + case ConnectData of + "ping" -> % We connect + net_adm:ping(TestNode); + TcpPort -> % Other connect + {ok, Sock} = gen_tcp:connect("localhost", list_to_integer(TcpPort), + [{active,false},{packet,2}]), + ok = gen_tcp:send(Sock, "Connect please"), + {ok, "Connect done"} = gen_tcp:recv(Sock, 0), + gen_tcp:close(Sock) + end, + [TestNode] = nodes(), + {ok, [{Opt,Val}]} = net_kernel:getopts(TestNode, [Opt]), + {error, noconnection} = net_kernel:getopts('pixie@fairyland', [Opt]), + + NewVal = change_val(Val), + ok = net_kernel:setopts(TestNode, [{Opt, NewVal}]), + {ok, [{Opt,NewVal}]} = net_kernel:getopts(TestNode, [Opt]), + + ok = net_kernel:setopts(TestNode, [{Opt, Val}]), + {ok, [{Opt,Val}]} = net_kernel:getopts(TestNode, [Opt]), + + ok. + +opt_from_nr("1") -> {nodelay, true}; +opt_from_nr("2") -> {nodelay, false}. + +change_val(true) -> false; +change_val(false) -> true. + +start_node_unconnected(Name, Mod, Func, Args) -> + FullName = full_node_name(Name), + CmdLine = mk_node_cmdline(Name,Mod,Func,Args), + io:format("Starting node ~p: ~s~n", [FullName, CmdLine]), + case open_port({spawn, CmdLine}, [exit_status]) of + Port when is_port(Port) -> + {FullName, Port}; + Error -> + exit({failed_to_start_node, FullName, Error}) + end. + +full_node_name(PreName) -> + HostSuffix = lists:dropwhile(fun ($@) -> false; (_) -> true end, + atom_to_list(node())), + list_to_atom(atom_to_list(PreName) ++ HostSuffix). + +mk_node_cmdline(Name,Mod,Func,Args) -> + Static = "-noinput", + Pa = filename:dirname(code:which(?MODULE)), + Prog = case catch init:get_argument(progname) of + {ok,[[P]]} -> P; + _ -> exit(no_progname_argument_found) + end, + NameSw = case net_kernel:longnames() of + false -> "-sname "; + true -> "-name "; + _ -> exit(not_distributed_node) + end, + {ok, Pwd} = file:get_cwd(), + NameStr = atom_to_list(Name), + Prog ++ " " + ++ Static ++ " " + ++ NameSw ++ " " ++ NameStr + ++ " -pa " ++ Pa + ++ " -env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ NameStr + ++ " -setcookie " ++ atom_to_list(erlang:get_cookie()) + ++ " -run " ++ atom_to_list(Mod) ++ " " ++ atom_to_list(Func) + ++ " " ++ string:join(Args, " "). + %% OTP-4255. tick_change(Config) when is_list(Config) -> -- cgit v1.2.3 From e96a373c9699296ade966c601bb0e7185f4a163d Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 9 Aug 2016 20:07:47 +0200 Subject: kernel: Document net_kernel:getopts and setopts --- lib/kernel/doc/src/kernel_app.xml | 2 ++ lib/kernel/doc/src/net_kernel.xml | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 9e6fb60bb7..dc0291babe 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -215,12 +215,14 @@

Defines the First..Last port range for the listener socket of a distributed Erlang node.

+ {inet_dist_listen_options, Opts}

Defines a list of extra socket options to be used when opening the listening socket for a distributed Erlang node. See gen_tcp:listen/2.

+ {inet_dist_connect_options, Opts}

Defines a list of extra socket options to be used when connecting to diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml index f48a534d4f..3c1b3d5190 100644 --- a/lib/kernel/doc/src/net_kernel.xml +++ b/lib/kernel/doc/src/net_kernel.xml @@ -115,6 +115,21 @@ $ erl -sname foobar + + + Get distribution socket options. + +

Get one or more options for the distribution socket + connected to Node.

+

If Node is a connected node + the return value is the same as from + inet:getopts(Sock, Options) + where Sock is the distribution socket for Node.

+

Returns ignored if the local node is not alive or + {error, noconnection} if Node is not connected.

+
+
+ @@ -288,6 +303,27 @@ $ erl -sname foobar
+ + + Set distribution socket options. + +

Set one or more options for distribution sockets. + Argument Node can be either one node name + or the atom new to affect the distribution sockets of all + future connected nodes.

+

The return value is the same as from + inet:setopts/2 + or {error, noconnection} if Node is not + a connected node or new.

+

If Node is new the Options + will then also be added to kernel configration parameters + inet_dist_listen_options + and + inet_dist_connect_options.

+

Returns ignored if the local node is not alive.

+
+
+ start([Name]) -> {ok, pid()} | {error, Reason} start([Name, NameType]) -> {ok, pid()} | {error, Reason} -- cgit v1.2.3 From cad08127834757a48ad85b8f6e177c2d1a7f8589 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 16 Aug 2016 10:17:50 +0200 Subject: erts: Make sure to flush potential exit message --- lib/kernel/src/os.erl | 16 ++++++++++------ lib/kernel/test/os_SUITE.erl | 22 ++++++++++++++++++++-- 2 files changed, 30 insertions(+), 8 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 81b70a7fee..05bbf1069e 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -279,15 +279,11 @@ get_data(Port, MonRef, Eot, Sofar) -> Last -> Port ! {self(), close}, flush_until_closed(Port), + flush_exit(Port), iolist_to_binary([Sofar, Last]) end; {'DOWN', MonRef, _, _ , _} -> - receive - {'EXIT', Port, _} -> - ok - after 1 -> % force context switch - ok - end, + flush_exit(Port), iolist_to_binary(Sofar) end. @@ -307,3 +303,11 @@ flush_until_closed(Port) -> {Port, closed} -> true end. + +flush_exit(Port) -> + receive + {'EXIT', Port, _} -> + ok + after 1 -> % force context switch + ok + end. diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 8f3e511941..19ab3713a1 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -25,7 +25,7 @@ -export([space_in_cwd/1, quoting/1, cmd_unicode/1, space_in_name/1, bad_command/1, find_executable/1, unix_comment_in_command/1, deep_list_command/1, large_output_command/1, background_command/0, background_command/1, - perf_counter_api/1]). + message_leak/1, perf_counter_api/1]). -include_lib("common_test/include/ct.hrl"). @@ -36,7 +36,8 @@ suite() -> all() -> [space_in_cwd, quoting, cmd_unicode, space_in_name, bad_command, find_executable, unix_comment_in_command, deep_list_command, - large_output_command, background_command, perf_counter_api]. + large_output_command, background_command, message_leak, + perf_counter_api]. groups() -> []. @@ -284,6 +285,23 @@ background_command(_Config) -> %% longer then the 5 second timeout os:cmd("sleep 10&"). +%% Test that message does not leak to the calling process +message_leak(_Config) -> + process_flag(trap_exit, true), + + os:cmd("echo hello"), + [] = receive_all(), + + case os:type() of + {unix, _} -> + os:cmd("while true; do echo hello; done&"), + [] = receive_all(); + _ -> + ok % Cannot background on non-unix + end, + + process_flag(trap_exit, false). + %% Test that the os:perf_counter api works as expected perf_counter_api(_Config) -> -- cgit v1.2.3 From f8ee2883dbc0243128c812ef259c1c36c0fba34f Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 16 Aug 2016 10:25:32 +0200 Subject: Prepare release --- lib/kernel/doc/src/notes.xml | 17 +++++++++++++++++ lib/kernel/vsn.mk | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 0e3914b083..3d35f6f57f 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,23 @@

This document describes the changes made to the Kernel application.

+
Kernel 5.0.2 + +
Fixed Bugs and Malfunctions + + +

+ When calling os:cmd from a process that has set trap_exit + to true an 'EXIT' message would be left in the message + queue. This bug was introduced in kernel vsn 5.0.1.

+

+ Own Id: OTP-13813

+
+
+
+ +
+
Kernel 5.0.1
Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index e88e4f9170..cdd200a234 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.0.1 +KERNEL_VSN = 5.0.2 -- cgit v1.2.3 From dc322963be1e20c153413fe964a59cffe21971b9 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sat, 20 Aug 2016 23:26:07 +0100 Subject: Skip inflateGetDictionary test case if unsupported --- lib/kernel/test/zlib_SUITE.erl | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl index 4720a7f5ea..4b67fce9a8 100644 --- a/lib/kernel/test/zlib_SUITE.erl +++ b/lib/kernel/test/zlib_SUITE.erl @@ -290,6 +290,18 @@ api_inflateSetDictionary(Config) when is_list(Config) -> %% Test inflateGetDictionary. api_inflateGetDictionary(Config) when is_list(Config) -> + Z1 = zlib:open(), + IsOperationSupported = + case catch zlib:inflateGetDictionary(Z1) of + {'EXIT',{einval,_}} -> true; + {'EXIT',{enotsup,_}} -> false + end, + _ = zlib:close(Z1), + api_inflateGetDictionary_if_supported(IsOperationSupported). + +api_inflateGetDictionary_if_supported(false) -> + {skip, "inflateGetDictionary/1 unsupported in current setup"}; +api_inflateGetDictionary_if_supported(true) -> % Compress payload using custom dictionary Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1)), -- cgit v1.2.3 From 5e57b3faccba1ae66ebd40fed23f5770eee71b04 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 24 Aug 2016 15:57:53 +0200 Subject: Replace usage of deprecated time units --- lib/kernel/doc/src/seq_trace.xml | 4 ++-- lib/kernel/src/inet_db.erl | 3 ++- lib/kernel/src/kernel.app.src | 2 +- lib/kernel/test/erl_distribution_SUITE.erl | 4 ++-- lib/kernel/test/file_SUITE.erl | 2 +- lib/kernel/test/gen_tcp_misc_SUITE.erl | 2 +- lib/kernel/test/interactive_shell_SUITE.erl | 2 +- lib/kernel/test/os_SUITE.erl | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml index 5ac199b6a7..ba7259219d 100644 --- a/lib/kernel/doc/src/seq_trace.xml +++ b/lib/kernel/doc/src/seq_trace.xml @@ -129,7 +129,7 @@ seq_trace:set_token(OldToken), % activate the trace token again Erlang monotonic time and a monotonically increasing integer. The time-stamp has the same format and value - as produced by {erlang:monotonic_time(nano_seconds), + as produced by {erlang:monotonic_time(nanosecond), erlang:unique_integer([monotonic])}.

set_token(monotonic_timestamp, Bool) @@ -141,7 +141,7 @@ seq_trace:set_token(OldToken), % activate the trace token again Erlang monotonic time. The time-stamp has the same format and value as produced by - erlang:monotonic_time(nano_seconds).

+ erlang:monotonic_time(nanosecond).

If multiple timestamp flags are passed, timestamp has diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl index 465cec1b45..6cbb6ac2da 100644 --- a/lib/kernel/src/inet_db.erl +++ b/lib/kernel/src/inet_db.erl @@ -1379,7 +1379,8 @@ cache_rr(_Db, Cache, RR) -> ets:insert(Cache, RR). times() -> - erlang:convert_time_unit(erlang:monotonic_time() - erlang:system_info(start_time),native,seconds). + erlang:convert_time_unit(erlang:monotonic_time() - erlang:system_info(start_time), + native, second). %% lookup and remove old entries diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 56d1699656..4d08a55c7c 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -118,6 +118,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-8.0", "stdlib-3.0", "sasl-3.0"]} + {runtime_dependencies, ["erts-9.0", "stdlib-3.0", "sasl-3.0"]} ] }. diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index eb58e92224..bd62096684 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -226,7 +226,7 @@ time_ping(Node) -> T0 = erlang:monotonic_time(), pang = net_adm:ping(Node), T1 = erlang:monotonic_time(), - erlang:convert_time_unit(T1 - T0, native, milli_seconds). + erlang:convert_time_unit(T1 - T0, native, millisecond). %% Keep the connection with the client node up. %% This is neccessary as the client node runs with much shorter @@ -270,7 +270,7 @@ tick_cli_test1(Node) -> receive {whats_the_result, From} -> Diff = erlang:convert_time_unit(T2-T1, native, - milli_seconds), + millisecond), case Diff of T when T > 8000, T < 16000 -> From ! {tick_test, T}; diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 5f049c6f99..375899987e 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -3730,7 +3730,7 @@ response_analysis(Module, Function, Arguments) -> {Result, Comment}. micro_ts() -> - erlang:monotonic_time(micro_seconds). + erlang:monotonic_time(microsecond). response_stat(init, Ts) -> {0, 0, Ts, 0, 0}; diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 6b64c83fc2..929f66d400 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -1914,7 +1914,7 @@ so_priority(Config) when is_list(Config) -> %% Accept test utilities (suites are below) millis() -> - erlang:monotonic_time(milli_seconds). + erlang:monotonic_time(millisecond). collect_accepts(0,_) -> []; collect_accepts(N,Tmo) -> diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl index fc3706ba1e..298a364a91 100644 --- a/lib/kernel/test/interactive_shell_SUITE.erl +++ b/lib/kernel/test/interactive_shell_SUITE.erl @@ -711,7 +711,7 @@ toerl_loop(Port,Acc) -> end. millistamp() -> - erlang:monotonic_time(milli_seconds). + erlang:monotonic_time(millisecond). get_data_within(Port, X, Acc) when X =< 0 -> ?dbg({get_data_within, X, Acc, ?LINE}), diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 19ab3713a1..b9ddc3bf48 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -311,7 +311,7 @@ perf_counter_api(_Config) -> T1 = os:perf_counter(), timer:sleep(100), T2 = os:perf_counter(), - TsDiff = erlang:convert_time_unit(T2 - T1, perf_counter, nano_seconds), + TsDiff = erlang:convert_time_unit(T2 - T1, perf_counter, nanosecond), ct:pal("T1: ~p~n" "T2: ~p~n" "TsDiff: ~p~n", -- cgit v1.2.3 From 2fe03e832adb11c50bcfc62679cf17779b284124 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 27 Jul 2016 19:45:41 +0200 Subject: Reclaim literal area after purge has completed --- lib/kernel/test/init_SUITE.erl | 48 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index 1370e23195..b96de94427 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -27,7 +27,8 @@ -export([get_arguments/1, get_argument/1, boot_var/1, restart/1, many_restarts/0, many_restarts/1, get_plain_arguments/1, - reboot/1, stop_status/1, stop/1, get_status/1, script_id/1]). + reboot/1, stop_status/1, stop/1, get_status/1, script_id/1, + find_system_processes/0]). -export([boot1/1, boot2/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -355,12 +356,16 @@ wait_for(N,Node,EHPid) -> restart(Config) when is_list(Config) -> Args = args(), + Pa = " -pa " ++ filename:dirname(code:which(?MODULE)), + %% Currently test_server:start_node cannot be used. The restarted %% node immediately halts due to the implementation of %% test_server:start_node. - {ok, Node} = loose_node:start(init_test, Args, ?DEFAULT_TIMEOUT_SEC), + {ok, Node} = loose_node:start(init_test, Args ++ Pa, ?DEFAULT_TIMEOUT_SEC), %% Ok, the node is up, now the real test test begins. erlang:monitor_node(Node, true), + SysProcs0 = rpc:call(Node, ?MODULE, find_system_processes, []), + [InitPid, PurgerPid, LitCollectorPid] = SysProcs0, InitPid = rpc:call(Node, erlang, whereis, [init]), PurgerPid = rpc:call(Node, erlang, whereis, [erts_code_purger]), Procs = rpc:call(Node, erlang, processes, []), @@ -375,6 +380,9 @@ restart(Config) when is_list(Config) -> end, ok = wait_restart(30, Node), + SysProcs1 = rpc:call(Node, ?MODULE, find_system_processes, []), + [InitPid1, PurgerPid1, LitCollectorPid1] = SysProcs1, + %% Still the same init process! InitPid1 = rpc:call(Node, erlang, whereis, [init]), InitP = pid_to_list(InitPid), @@ -385,8 +393,16 @@ restart(Config) when is_list(Config) -> PurgerP = pid_to_list(PurgerPid), PurgerP = pid_to_list(PurgerPid1), + %% and same literal area collector process! + case LitCollectorPid of + undefined -> undefined = LitCollectorPid1; + _ -> + LitCollectorP = pid_to_list(LitCollectorPid), + LitCollectorP = pid_to_list(LitCollectorPid1) + end, + NewProcs0 = rpc:call(Node, erlang, processes, []), - NewProcs = NewProcs0 -- [InitPid1, PurgerPid1], + NewProcs = NewProcs0 -- SysProcs1, case check_processes(NewProcs, MaxPid) of true -> ok; @@ -406,6 +422,32 @@ restart(Config) when is_list(Config) -> loose_node:stop(Node), ok. +-record(sys_procs, {init, + code_purger, + literal_collector}). + +find_system_processes() -> + find_system_procs(processes(), #sys_procs{}). + +find_system_procs([], SysProcs) -> + [SysProcs#sys_procs.init, + SysProcs#sys_procs.code_purger, + SysProcs#sys_procs.literal_collector]; +find_system_procs([P|Ps], SysProcs) -> + case process_info(P, initial_call) of + {initial_call,{otp_ring0,start,2}} -> + undefined = SysProcs#sys_procs.init, + find_system_procs(Ps, SysProcs#sys_procs{init = P}); + {initial_call,{erts_code_purger,start,0}} -> + undefined = SysProcs#sys_procs.code_purger, + find_system_procs(Ps, SysProcs#sys_procs{code_purger = P}); + {initial_call,{erts_literal_area_collector,start,0}} -> + undefined = SysProcs#sys_procs.literal_collector, + find_system_procs(Ps, SysProcs#sys_procs{literal_collector = P}); + _ -> + find_system_procs(Ps, SysProcs) + end. + wait_restart(0, _Node) -> ct:fail(not_restarted); wait_restart(N, Node) -> -- cgit v1.2.3 From 9d0638216d35ca0f21c1eea20f8daa3992ac4f71 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 2 Aug 2016 15:58:06 +0200 Subject: Fix purge of code Ensure that we cannot get any dangling pointers into code that has been purged. This is done by a two phase purge. At first phase all fun entries pointing into the code to purge are marked for purge. All processes trying to call these funs will be suspended and by this we avoid getting new direct references into the code. When all processes has been checked, these processes are resumed. The new purge strategy now also completely ignore the existence of indirect references to the code (funs). If such exist, they will cause bad fun exceptions to the caller, but will not prevent a soft purge or cause a kill of a process having such live references during a hard purge. This since it is impossible to give any guarantees that no processes in the system have such indirect references. Even when the system is completely clean from such references, new ones can appear via distribution and/or disk. --- lib/kernel/doc/src/code.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index d3611d6a03..21f8a2d54a 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -651,6 +651,11 @@ ok = code:finish_loading(Prepared),

Purges the code for Module, that is, removes code marked as old. If some processes still linger in the old code, these processes are killed before the code is removed.

+

As of ERTS version 9.0, a process is only considered + to be lingering in the code if it has direct references to the code. + For more information see documentation of + erlang:check_process_code/3, + which is used in order to determine this.

Returns true if successful and any process is needed to be killed, otherwise false.

@@ -661,6 +666,11 @@ ok = code:finish_loading(Prepared),

Purges the code for Module, that is, removes code marked as old, but only if no processes linger in it.

+

As of ERTS version 9.0, a process is only considered + to be lingering in the code if it has direct references to the code. + For more information see documentation of + erlang:check_process_code/3, + which is used in order to determine this.

Returns false if the module cannot be purged because of processes lingering in old code, otherwise true.

-- cgit v1.2.3 From 0e04e76df2ea71e2e2e116afef04c497d84b1024 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 8 Aug 2016 17:13:24 +0200 Subject: Perform check_process_code while process is executing dirty --- lib/kernel/test/init_SUITE.erl | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index b96de94427..2b59eb2bfe 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -365,7 +365,7 @@ restart(Config) when is_list(Config) -> %% Ok, the node is up, now the real test test begins. erlang:monitor_node(Node, true), SysProcs0 = rpc:call(Node, ?MODULE, find_system_processes, []), - [InitPid, PurgerPid, LitCollectorPid] = SysProcs0, + [InitPid, PurgerPid, LitCollectorPid, DirtyCodePid] = SysProcs0, InitPid = rpc:call(Node, erlang, whereis, [init]), PurgerPid = rpc:call(Node, erlang, whereis, [erts_code_purger]), Procs = rpc:call(Node, erlang, processes, []), @@ -381,7 +381,7 @@ restart(Config) when is_list(Config) -> ok = wait_restart(30, Node), SysProcs1 = rpc:call(Node, ?MODULE, find_system_processes, []), - [InitPid1, PurgerPid1, LitCollectorPid1] = SysProcs1, + [InitPid1, PurgerPid1, LitCollectorPid1, DirtyCodePid1] = SysProcs1, %% Still the same init process! InitPid1 = rpc:call(Node, erlang, whereis, [init]), @@ -401,6 +401,14 @@ restart(Config) when is_list(Config) -> LitCollectorP = pid_to_list(LitCollectorPid1) end, + %% and same dirty process code checker process! + case DirtyCodePid of + undefined -> undefined = DirtyCodePid1; + _ -> + DirtyCodeP = pid_to_list(DirtyCodePid), + DirtyCodeP = pid_to_list(DirtyCodePid1) + end, + NewProcs0 = rpc:call(Node, erlang, processes, []), NewProcs = NewProcs0 -- SysProcs1, case check_processes(NewProcs, MaxPid) of @@ -424,7 +432,8 @@ restart(Config) when is_list(Config) -> -record(sys_procs, {init, code_purger, - literal_collector}). + literal_collector, + dirty_proc_checker}). find_system_processes() -> find_system_procs(processes(), #sys_procs{}). @@ -432,7 +441,8 @@ find_system_processes() -> find_system_procs([], SysProcs) -> [SysProcs#sys_procs.init, SysProcs#sys_procs.code_purger, - SysProcs#sys_procs.literal_collector]; + SysProcs#sys_procs.literal_collector, + SysProcs#sys_procs.dirty_proc_checker]; find_system_procs([P|Ps], SysProcs) -> case process_info(P, initial_call) of {initial_call,{otp_ring0,start,2}} -> @@ -444,6 +454,9 @@ find_system_procs([P|Ps], SysProcs) -> {initial_call,{erts_literal_area_collector,start,0}} -> undefined = SysProcs#sys_procs.literal_collector, find_system_procs(Ps, SysProcs#sys_procs{literal_collector = P}); + {initial_call,{erts_dirty_process_code_checker,start,0}} -> + undefined = SysProcs#sys_procs.dirty_proc_checker, + find_system_procs(Ps, SysProcs#sys_procs{dirty_proc_checker = P}); _ -> find_system_procs(Ps, SysProcs) end. -- cgit v1.2.3 From 1ecf5e62d59624cad7e095d46243ec149cb1fcbc Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 31 Aug 2016 11:21:17 +0200 Subject: kernerl: Remove infinite loop from testcase We don't want the infinite loop as it leaks after the test finished. --- lib/kernel/test/os_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 19ab3713a1..5b6e0ab223 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -294,7 +294,7 @@ message_leak(_Config) -> case os:type() of {unix, _} -> - os:cmd("while true; do echo hello; done&"), + os:cmd("for i in $(seq 1 100); do echo hello; done&"), [] = receive_all(); _ -> ok % Cannot background on non-unix -- cgit v1.2.3 From fc69b92df1b6ad6487259ab0e24db9a0c3f3fb77 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 31 Aug 2016 13:42:02 +0200 Subject: Fix xmllint-warnings --- lib/kernel/doc/src/heart.xml | 2 +- lib/kernel/doc/src/kernel_app.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml index 864f8facac..59a046bf4d 100644 --- a/lib/kernel/doc/src/heart.xml +++ b/lib/kernel/doc/src/heart.xml @@ -83,7 +83,7 @@ :

 % erl -heart -env HEART_KILL_SIGNAL SIGABRT ...
-

If heart should not kill the Erlang runtime system, this can be indicated +

If heart should not kill the Erlang runtime system, this can be indicated using the environment variable . This can be useful if the command executed by heart takes care of this, for example as part of a specific cleanup sequence. diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index dc0291babe..fb6421e1c5 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -215,16 +215,16 @@

Defines the First..Last port range for the listener socket of a distributed Erlang node.

- {inet_dist_listen_options, Opts} +

Defines a list of extra socket options to be used when opening the listening socket for a distributed Erlang node. See gen_tcp:listen/2.

- {inet_dist_connect_options, Opts} +

Defines a list of extra socket options to be used when connecting to other distributed Erlang nodes. See gen_tcp:connect/4.

-- cgit v1.2.3 From 6da22ec1d08090c038340e4acf4d96390cd74e9d Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Wed, 31 Aug 2016 19:35:12 +0200 Subject: Print on_load error in a more useful style When printing the error term from on_load, insert a newline because the term is never short and will produce hard to read/copy output that is just hanging off to the right. --- lib/kernel/src/code_server.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 48541ec500..3f220f4a6c 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1414,7 +1414,7 @@ finish_on_load_report(Mod, Term) -> %% from the code_server process. spawn(fun() -> F = "The on_load function for module " - "~s returned ~P\n", + "~s returned:~n~P\n", %% Express the call as an apply to simplify %% the ext_mod_dep/1 test case. -- cgit v1.2.3 From ad6e765bcd4f35a282ef00e38ed9129f3a5c1d83 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 1 Sep 2016 14:32:27 +0200 Subject: doc: Correct errors introduced by Editorial changes Fix some older errors as well. --- lib/kernel/doc/src/app.xml | 6 +++--- lib/kernel/doc/src/application.xml | 6 +++--- lib/kernel/doc/src/auth.xml | 4 ++-- lib/kernel/doc/src/code.xml | 12 ++++++------ lib/kernel/doc/src/erl_boot_server.xml | 4 ++-- lib/kernel/doc/src/erl_ddll.xml | 6 +++--- lib/kernel/doc/src/error_logger.xml | 30 +++++++++++++++--------------- lib/kernel/doc/src/file.xml | 28 ++++++++++++++-------------- lib/kernel/doc/src/gen_tcp.xml | 6 +++--- lib/kernel/doc/src/inet.xml | 22 +++++++++++----------- lib/kernel/doc/src/init_stub.xml | 2 +- lib/kernel/doc/src/kernel_app.xml | 20 ++++++++++---------- lib/kernel/doc/src/net_kernel.xml | 12 ++++++------ lib/kernel/doc/src/notes.xml | 2 +- lib/kernel/doc/src/rpc.xml | 4 ++-- lib/kernel/doc/src/zlib_stub.xml | 2 +- 16 files changed, 83 insertions(+), 83 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/app.xml b/lib/kernel/doc/src/app.xml index 5e0da409a3..d2e9390d7e 100644 --- a/lib/kernel/doc/src/app.xml +++ b/lib/kernel/doc/src/app.xml @@ -151,7 +151,7 @@ ApplicationVersion = string() application is allowed to be started. systools uses this list to generate correct start scripts. Defaults to the empty list, but notice that all applications have - dependencies to (at least) Kernel and STDLIB.

+ dependencies to (at least) Kernel and STDLIB.

env @@ -171,7 +171,7 @@ ApplicationVersion = string() implemented as a supervision tree, otherwise the application controller does not know how to start it. mod can be omitted for applications without processes, typically - code libraries, for example, STDLIB.

+ code libraries, for example, STDLIB.

start_phases @@ -236,7 +236,7 @@ ApplicationVersion = string()
See Also

application(3), - sasl:systools(3)

+ systools(3)

diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml index 8d33aa86e7..886286b76d 100644 --- a/lib/kernel/doc/src/application.xml +++ b/lib/kernel/doc/src/application.xml @@ -200,7 +200,7 @@ app(4).

If Distributed == {Application,[Time,]Nodes}, the application becomes distributed. The argument overrides - the value for the application in the Kernel configuration + the value for the application in the Kernel configuration parameter distributed. Application must be the application name (same as in the first argument). If a node crashes and Time is specified, @@ -221,7 +221,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}] the application is to be started at cp2@cave or cp3@cave.

If Distributed == default, the value for - the application in the Kernel configuration parameter + the application in the Kernel configuration parameter distributed is used.

@@ -267,7 +267,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}] started, Application is started as well.

By default, all applications are loaded with permission true on all nodes. The permission can be configured - using the Kernel configuration parameter permissions.

+ using the Kernel configuration parameter permissions.

diff --git a/lib/kernel/doc/src/auth.xml b/lib/kernel/doc/src/auth.xml index 03f983b96d..5901446960 100644 --- a/lib/kernel/doc/src/auth.xml +++ b/lib/kernel/doc/src/auth.xml @@ -47,7 +47,7 @@

Use erlang:get_cookie() - in ERTS instead.

+ in ERTS instead.

@@ -59,7 +59,7 @@

Use erlang:set_cookie(node(), Cookie) - in ERTS instead.

+ in ERTS instead.

diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 21f8a2d54a..4db377bcde 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -86,11 +86,11 @@ an ebin directory are ignored.

All application directories found in the additional directories appears before the standard OTP applications, except for the - Kernel and STDLIB applications, which are placed before + Kernel and STDLIB applications, which are placed before any additional applications. In other words, modules found in any of the additional library directories override modules with - the same name in OTP, except for modules in Kernel and - STDLIB.

+ the same name in OTP, except for modules in Kernel and + STDLIB.

Environment variable ERL_LIBS (if defined) is to contain a colon-separated (for Unix-like systems) or semicolon-separated (for Windows) list of additional libraries.

@@ -151,7 +151,7 @@ zip:create("mnesia-4.4.7.ez", $OTPROOT/lib/mnesia.ez/mnesia/ebin or $OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin.

-

The code server uses module erl_prim_loader in ERTS +

The code server uses module erl_prim_loader in ERTS (possibly through erl_boot_server) to read code files from archives. However, the functions in erl_prim_loader can also be used by other applications to read files from archives. For @@ -688,9 +688,9 @@ ok = code:finish_loading(Prepared),

Normally, Loaded is the absolute filename Filename from which the code is obtained. If the module is preloaded (see - sasl:script(4)), + script(4)), Loaded==preloaded. If the module is Cover-compiled (see - tools:cover(3)), + cover(3)), Loaded==cover_compiled.

diff --git a/lib/kernel/doc/src/erl_boot_server.xml b/lib/kernel/doc/src/erl_boot_server.xml index 897365f9b9..4109251387 100644 --- a/lib/kernel/doc/src/erl_boot_server.xml +++ b/lib/kernel/doc/src/erl_boot_server.xml @@ -38,13 +38,13 @@ command-line flag -loader inet. All hosts specified with command-line flag -hosts Host must have one instance of this server running.

-

This server can be started with the Kernel configuration +

This server can be started with the Kernel configuration parameter start_boot_server.

The erl_boot_server can read regular files and files in archives. See code(3) and erl_prim_loader(3) - in ERTS.

+ in ERTS.

The support for loading code from archive files is experimental. It is released before it is ready to obtain early feedback. The file format, semantics, diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml index a5ce58ef3e..75114e015c 100644 --- a/lib/kernel/doc/src/erl_ddll.xml +++ b/lib/kernel/doc/src/erl_ddll.xml @@ -201,7 +201,7 @@

Removes a driver monitor in much the same way as erlang:demonitor/1 - in ERTS + in ERTS does with process monitors. For details about how to create driver monitors, see monitor/2, @@ -431,7 +431,7 @@

Creates a driver monitor and works in many ways as erlang:monitor/2 - in ERTS, + in ERTS, does for processes. When a driver changes state, the monitor results in a monitor message that is sent to the calling process. MonitorRef returned by this function is @@ -745,7 +745,7 @@

This parameter is the name of the driver to be used in subsequent calls to function erlang:open_port - in ERTS. + in ERTS. The name can be specified as an iolist() or an atom(). The name specified when loading is used to find the object file (with the help of Path diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index a8273e59e2..814e8eac46 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -33,7 +33,7 @@

The Erlang error logger is an event manager (see OTP Design Principles and - stdlib:gen_event(3)), + gen_event(3)), registered as error_logger. Errors, warnings, and info events are sent to the error logger from the Erlang runtime system and the different Erlang/OTP applications. The events are, by default, @@ -44,12 +44,12 @@ executing.

Initially, error_logger has only a primitive event handler, which buffers and prints the raw event messages. During - system startup, the Kernel application replaces this with a + system startup, the Kernel application replaces this with a standard event handler, by default one that writes - nicely formatted output to the terminal. Kernel can also be + nicely formatted output to the terminal. Kernel can also be configured so that events are logged to a file instead, or not logged at all, see kernel(6).

-

Also the SASL application, if started, adds its own event +

Also the SASL application, if started, adds its own event handler, which by default writes supervisor, crash, and progress reports to the terminal. See sasl(6).

@@ -58,9 +58,9 @@ User-defined event handlers can be added to handle application-specific events, see add_report_handler/1,2. - Also, a useful event handler is provided in STDLIB for multi-file + Also, a useful event handler is provided in STDLIB for multi-file logging of events, see - stdlib:log_mf_h(3).

+ log_mf_h(3).

Warning events were introduced in Erlang/OTP R9C and are enabled by default as from Erlang/OTP 18.0. To retain backwards compatibility with existing user-defined event handlers, the warning events can be @@ -82,7 +82,7 @@

Adds a new event handler to the error logger. The event handler must be implemented as a gen_event callback module, see - stdlib:gen_event(3).

+ gen_event(3).

Handler is typically the name of the callback module and Args is an optional term (defaults to []) passed to the initialization callback function Handler:init/1. @@ -97,7 +97,7 @@

Deletes an event handler from the error logger by calling gen_event:delete_handler(error_logger, Handler, []), - see stdlib:gen_event(3).

+ see gen_event(3).

@@ -110,7 +110,7 @@ The Format and Data arguments are the same as the arguments of io:format/2 - in STDLIB. + in STDLIB. The event is handled by the standard event handler.

Example:

@@ -171,7 +171,7 @@ ok
The Format and Data arguments are the same as the arguments of io:format/2 - in STDLIB. The event is handled by the standard event handler.

+ in STDLIB. The event is handled by the standard event handler.

Example:

 1> error_logger:info_msg("Something happened in ~p~n", [a_module]).
@@ -235,7 +235,7 @@ ok

Enables or disables printout of standard events to a file.

This is done by adding or deleting the standard event handler for output to file. Thus, calling this function overrides - the value of the Kernel error_logger configuration + the value of the Kernel error_logger configuration parameter.

Enabling file logging can be used together with calling tty(false), to have a silent system where @@ -274,7 +274,7 @@ ok to the terminal.

This is done by adding or deleting the standard event handler for output to the terminal. Thus, calling this function overrides - the value of the Kernel error_logger configuration parameter.

+ the value of the Kernel error_logger configuration parameter.

@@ -323,7 +323,7 @@ ok The Format and Data arguments are the same as the arguments of io:format/2 - in STDLIB. + in STDLIB. The event is handled by the standard event handler. It is tagged as an error, warning, or info, see warning_map/0.

@@ -416,8 +416,8 @@ ok
See Also -

stdlib:gen_event(3), - stdlib:log_mf_h(3) +

gen_event(3), + log_mf_h(3) kernel(6) sasl(6)

diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 7d86c3ebcb..d734ee25b8 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -79,7 +79,7 @@ list_dir_all/1 and read_link_all/1.

-

See also section Notes About Raw Filenames in the STDLIB User´s Giude.

+

See also section Notes About Raw Filenames in the STDLIB User´s Giude.

@@ -277,7 +277,7 @@ f.txt: {person, "kalle", 25}. {ok,[{person,"kalle",25},{person,"pelle",30}]}

The encoding of Filename can be set by a comment, as described in - stdlib:epp(3).

+ epp(3).

@@ -445,7 +445,7 @@ f.txt: {person, "kalle", 25}.

The encoding of Filename can be set by a comment, as described in - stdlib:epp(3).

+ epp(3).

@@ -455,7 +455,7 @@ f.txt: {person, "kalle", 25}.

The same as eval/1, but the variable bindings Bindings are used in the evaluation. For information about the variable bindings, see - stdlib:erl_eval(3).

+ erl_eval(3).

@@ -830,7 +830,7 @@ f.txt: {person, "kalle", 25}. this module (file) for reading and writing data as the interfaces provided here work with byte-oriented data. Using other (Unicode) encodings makes the - stdlib:io(3) functions + io(3) functions get_chars, get_line, and put_chars more suitable, as they can work with the full Unicode range.

If data is sent to an io_device() in a format that cannot be @@ -847,7 +847,7 @@ f.txt: {person, "kalle", 25}. that is, read/2 are returned "as is". If module - stdlib:io(3) is used for + io(3) is used for writing, the file can only cope with Unicode characters up to code point 255 (the ISO Latin-1 range).

@@ -861,7 +861,7 @@ f.txt: {person, "kalle", 25}. the file lies beyond the ISO Latin-1 range (0..255), but failure occurs if the data contains Unicode code points beyond that range. The file is best read with the functions in the Unicode aware module - stdlib:io(3).

+ io(3).

Bytes written to the file by any means are translated to UTF-8 encoding before being stored on the disk file.

@@ -891,7 +891,7 @@ f.txt: {person, "kalle", 25}. So a file can be analyzed in latin1 encoding for, for example, a BOM, positioned beyond the BOM and then be set for the right encoding before further reading. For functions identifying BOMs, see module - stdlib:unicode(3).

+ unicode(3).

This option is not allowed on raw files.

ram @@ -932,7 +932,7 @@ f.txt: {person, "kalle", 25}. closed and the process itself is terminated. An IoDevice returned from this call can be used as an argument to the I/O functions (see - stdlib:io(3)).

+ io(3)).

In previous versions of file, modes were specified as one of the atoms read, write, or @@ -1055,7 +1055,7 @@ f.txt: {person, "kalle", 25}.

The encoding of Filename can be set by a comment as described in - stdlib:epp(3).

+ epp(3).

@@ -1128,7 +1128,7 @@ f.txt: {person, "kalle", 25}.

The encoding of Filename can be set by a comment as described in - stdlib:epp(3).

+ epp(3).

@@ -1389,7 +1389,7 @@ f.txt: {person, "kalle", 25}. {ok, FileInfo} if successful, otherwise {error, Reason}. FileInfo is a record - file_info, defined in the Kernel include file + file_info, defined in the Kernel include file file.hrl. Include the following directive in the module from which the function is called:

@@ -1552,7 +1552,7 @@ f.txt: {person, "kalle", 25}. raw line-oriented reading.

If encoding is set to something else than latin1, the read_line/1 call fails if the data contains characters larger than 255, - why module stdlib:io(3) is to be + why module io(3) is to be preferred when reading such a file.

The function returns:

@@ -1970,7 +1970,7 @@ f.txt: {person, "kalle", 25}.

Changes file information. Returns ok if successful, otherwise {error, Reason}. FileInfo is a record - file_info, defined in the Kernel include file + file_info, defined in the Kernel include file file.hrl. Include the following directive in the module from which the function is called:

diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index 83242c2df8..08454b9832 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -216,7 +216,7 @@ do_recv(Sock, Bs) -> time-out in milliseconds. Defaults to infinity.

The default values for options specified to connect can - be affected by the Kernel configuration parameter + be affected by the Kernel configuration parameter inet_default_connect_options. For details, see inet(3).

@@ -293,7 +293,7 @@ do_recv(Sock, Bs) -> accept/1,2.

The default values for options specified to listen can - be affected by the Kernel configuration parameter + be affected by the Kernel configuration parameter inet_default_listen_options. For details, see inet(3).

@@ -307,7 +307,7 @@ do_recv(Sock, Bs) -> See the description of HttpPacket in erlang:decode_packet/3 - in ERTS. + in ERTS.

Receives a packet from a socket in passive diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index 8cc21bf3e2..3f4e3684f4 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -36,7 +36,7 @@ ERTS User's Guide: Inet Configuration for more information about how to configure an Erlang runtime system for IP communication.

-

The following two Kernel configuration parameters affect the +

The following two Kernel configuration parameters affect the behavior of all sockets opened on an Erlang node:

inet_default_connect_options can contain a list of @@ -48,7 +48,7 @@

When accept is issued, the values of the listening socket options are inherited. No such application variable is therefore needed for accept.

-

Using the Kernel configuration parameters above, one +

Using the Kernel configuration parameters above, one can set default options for all TCP sockets on a node, but use this with care. Options such as {delay_send,true} can be specified in this way. The following is an example of starting an Erlang @@ -95,7 +95,7 @@ fe80::204:acff:fe17:bf38 -

The record is defined in the Kernel include file +

The record is defined in the Kernel include file "inet.hrl".

Add the following directive to the module:

@@ -391,7 +391,7 @@ get_tcpi_sacked(Sock) -> <<_:28/binary,TcpiSacked:32/native,_/binary>> = Info, TcpiSacked.]]>

Preferably, you would check the machine type, the operating system, - and the Kernel version before executing anything similar to + and the Kernel version before executing anything similar to this code.

@@ -661,7 +661,7 @@ get_tcpi_sacked(Sock) ->

The size of the user-level software buffer used by the driver. Not to be confused with options sndbuf and recbuf, which correspond to the - Kernel socket buffers. It is recommended + Kernel socket buffers. It is recommended to have val(buffer) >= max(val(sndbuf),val(recbuf)) to avoid performance issues because of unnecessary copying. val(buffer) is automatically set to the above @@ -720,7 +720,7 @@ get_tcpi_sacked(Sock) ->

The socket message queue is set to a busy state when the amount of data on the message queue reaches this limit. Notice that this limit only - concerns data that has not yet reached the ERTS internal + concerns data that has not yet reached the ERTS internal socket implementation. Defaults to 8 kB.

Senders of data to the socket are suspended if either the socket message queue is busy or the socket @@ -736,7 +736,7 @@ get_tcpi_sacked(Sock) -> {high_watermark, Size} (TCP/IP sockets)

The socket is set to a busy state when the amount - of data queued internally by the ERTS socket implementation + of data queued internally by the ERTS socket implementation reaches this limit. Defaults to 8 kB.

Senders of data to the socket are suspended if either the socket message queue is busy or the socket @@ -816,7 +816,7 @@ get_tcpi_sacked(Sock) -> socket message queue is set in a not busy state when the amount of data queued in the message queue falls below this limit. Notice that this limit only concerns data - that has not yet reached the ERTS internal socket + that has not yet reached the ERTS internal socket implementation. Defaults to 4 kB.

Senders that are suspended because of either a busy message queue or a busy socket are resumed @@ -834,7 +834,7 @@ get_tcpi_sacked(Sock) ->

If the socket is in a busy state, the socket is set in a not busy state when the amount of data - queued internally by the ERTS socket implementation + queued internally by the ERTS socket implementation falls below this limit. Defaults to 4 kB.

Senders that are suspended because of a busy message queue or a busy socket are resumed @@ -954,7 +954,7 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp are returned with the format according to HttpPacket described in - erlang:decode_packet/3 in ERTS. + erlang:decode_packet/3 in ERTS. A socket in passive mode returns {ok, HttpPacket} from gen_tcp:recv while an active socket sends messages like @@ -1130,7 +1130,7 @@ inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}]),]]> can respond differently to this kind of option manipulation. Use with care.

Notice that the default options for TCP/IP sockets can be - changed with the Kernel configuration parameters mentioned in + changed with the Kernel configuration parameters mentioned in the beginning of this manual page.

diff --git a/lib/kernel/doc/src/init_stub.xml b/lib/kernel/doc/src/init_stub.xml index df89b174ca..1297c8264d 100644 --- a/lib/kernel/doc/src/init_stub.xml +++ b/lib/kernel/doc/src/init_stub.xml @@ -34,6 +34,6 @@ Coordination of system startup.

This module is moved to the - ERTS application.

+ ERTS application.

diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index fb6421e1c5..df681a505f 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -31,12 +31,12 @@ kernel The Kernel application. -

The Kernel application has all the code necessary to run +

The Kernel application has all the code necessary to run the Erlang runtime system: file servers, code servers, and so on.

-

The Kernel application is the first application started. It is +

The Kernel application is the first application started. It is mandatory in the sense that the minimal system based on - Erlang/OTP consists of Kernel and STDLIB. Kernel + Erlang/OTP consists of Kernel and STDLIB. Kernel contains the following functional areas:

Start, stop, supervision, configuration, and distribution of applications @@ -53,13 +53,13 @@
Error Logger Event Handlers

Two standard error logger event handlers are defined in - the Kernel application. These are described in + the Kernel application. These are described in error_logger(3).

Configuration -

The following configuration parameters are defined for the Kernel +

The following configuration parameters are defined for the Kernel application. For more information about configuration parameters, see file app(4).

@@ -162,8 +162,8 @@ depth to which terms are printed by the error logger event handlers included in OTP. This configuration parameter is used by the two event handlers - defined by the Kernel application and the two event - handlers in the SASL application. + defined by the Kernel application and the two event + handlers in the SASL application. (If you have implemented your own error handlers, this configuration parameter has no effect on them.)

@@ -173,7 +173,7 @@ ~P and ~W, respectively, and Depth is used as the depth parameter. For details, see io:format/2 - in STDLIB.

+ in STDLIB.

A reasonable starting value for Depth is 30. We recommend to test crashing various processes in your @@ -241,7 +241,7 @@

The name (string) of an Inet user configuration file. For details, see section Inet Configuration - in the ERTS User's Guide.

+ in the ERTS User's Guide.

net_setuptime = SetupTime @@ -360,7 +360,7 @@ MaxT = TickTime + TickTime / 4 start_timer = true | false

Starts the timer_server if the parameter is - true (see stdlib:timer(3)). + true (see timer(3)). This parameter is to be set to true in an embedded system using this service.

Defaults to false.

diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml index 3c1b3d5190..4e2b0c69db 100644 --- a/lib/kernel/doc/src/net_kernel.xml +++ b/lib/kernel/doc/src/net_kernel.xml @@ -55,7 +55,7 @@ $ erl -sname foobar erl.

Normally, connections are established automatically when another node is referenced. This functionality can be disabled - by setting Kernel configuration parameter + by setting Kernel configuration parameter dist_auto_connect to false, see kernel(6). In this case, connections must be established explicitly by calling @@ -146,7 +146,7 @@ $ erl -sname foobar are stopped. Two option lists are considered the same if they contain the same set of options.

-

As from Kernel version 2.11.4, and ERTS version +

As from Kernel version 2.11.4, and ERTS version 5.5.4, the following is guaranteed:

nodeup messages are delivered before delivery @@ -156,13 +156,13 @@ $ erl -sname foobar messages from the remote node that have been passed through the connection have been delivered.

-

Notice that this is not guaranteed for Kernel +

Notice that this is not guaranteed for Kernel versions before 2.11.4.

-

As from Kernel version 2.11.4, subscriptions can also be +

As from Kernel version 2.11.4, subscriptions can also be made before the net_kernel server is started, that is, net_kernel:monitor_nodes/[1,2] does not return ignored.

-

As from Kernel version 2.13, and ERTS version +

As from Kernel version 2.13, and ERTS version 5.7, the following is guaranteed:

nodeup messages are delivered after the @@ -172,7 +172,7 @@ $ erl -sname foobar corresponding node has disappeared in results from erlang:nodes/X.

-

Notice that this is not guaranteed for Kernel +

Notice that this is not guaranteed for Kernel versions before 2.13.

The format of the node status change messages depends on Options. If Options is diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 3d35f6f57f..9e9be3f661 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -3482,7 +3482,7 @@ types (for instance, ensure_loaded/1 now only accepts an atom as documented; it used to accept a string too).

-

Dialyzer will generally emit warnings for any +

Dialyzer will generally emit warnings for any calls that use undocumented argument types. Even if the call happens to still work in R12B, you should correct your code. A future release will adhere to the diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml index 8cad9fe4fc..5944e9321a 100644 --- a/lib/kernel/doc/src/rpc.xml +++ b/lib/kernel/doc/src/rpc.xml @@ -320,7 +320,7 @@ Information about a process.

Location transparent version of the BIF - erlang:process_info/1 in ERTS.

+ erlang:process_info/1 in ERTS.

@@ -330,7 +330,7 @@ Information about a process.

Location transparent version of the BIF - erlang:process_info/2 in ERTS.

+ erlang:process_info/2 in ERTS.

diff --git a/lib/kernel/doc/src/zlib_stub.xml b/lib/kernel/doc/src/zlib_stub.xml index b111581b10..9ab9c4eb62 100644 --- a/lib/kernel/doc/src/zlib_stub.xml +++ b/lib/kernel/doc/src/zlib_stub.xml @@ -34,6 +34,6 @@ Zlib compression interface.

This module is moved to the - ERTS application.

+ ERTS application.

-- cgit v1.2.3 From c0ed19c1261ee281d3c8f36ec3f28fa7328f0f39 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 2 Sep 2016 14:29:26 +0200 Subject: kernel: Close stdin of commands run in os:cmd This is needed when running programs that only exit when stdin has been closed, e.g. 'more'. --- lib/kernel/src/os.erl | 14 +++++++++++++- lib/kernel/test/os_SUITE.erl | 17 ++++++++++++++--- lib/kernel/test/os_SUITE_data/Makefile.src | 8 +++++++- lib/kernel/test/os_SUITE_data/my_fds.c | 9 +++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 lib/kernel/test/os_SUITE_data/my_fds.c (limited to 'lib/kernel') diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 05bbf1069e..f8519d3a5e 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -254,7 +254,19 @@ mk_cmd(_,Cmd) -> {"/bin/sh -s unix:cmd", [out], %% We insert a new line after the command, in case the command %% contains a comment character. - ["(", unicode:characters_to_binary(Cmd), "\n); echo \"\^D\"\n"], + %% + %% The >}. validate(Atom) when is_atom(Atom) -> diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 19ab3713a1..ef252b732d 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -25,7 +25,7 @@ -export([space_in_cwd/1, quoting/1, cmd_unicode/1, space_in_name/1, bad_command/1, find_executable/1, unix_comment_in_command/1, deep_list_command/1, large_output_command/1, background_command/0, background_command/1, - message_leak/1, perf_counter_api/1]). + message_leak/1, close_stdin/0, close_stdin/1, perf_counter_api/1]). -include_lib("common_test/include/ct.hrl"). @@ -37,7 +37,7 @@ all() -> [space_in_cwd, quoting, cmd_unicode, space_in_name, bad_command, find_executable, unix_comment_in_command, deep_list_command, large_output_command, background_command, message_leak, - perf_counter_api]. + close_stdin, perf_counter_api]. groups() -> []. @@ -54,7 +54,8 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. -init_per_testcase(background_command, Config) -> +init_per_testcase(TC, Config) + when TC =:= background_command; TC =:= close_stdin -> case os:type() of {win32, _} -> {skip,"Should not work on windows"}; @@ -302,6 +303,16 @@ message_leak(_Config) -> process_flag(trap_exit, false). +%% Test that os:cmd closes stdin of the program that is executed +close_stdin() -> + [{timetrap, {seconds, 5}}]. +close_stdin(Config) -> + DataDir = proplists:get_value(data_dir, Config), + Fds = filename:join(DataDir, "my_fds"), + + "-1" = os:cmd(Fds). + + %% Test that the os:perf_counter api works as expected perf_counter_api(_Config) -> diff --git a/lib/kernel/test/os_SUITE_data/Makefile.src b/lib/kernel/test/os_SUITE_data/Makefile.src index 912d0cbcb1..f83f781411 100644 --- a/lib/kernel/test/os_SUITE_data/Makefile.src +++ b/lib/kernel/test/os_SUITE_data/Makefile.src @@ -3,7 +3,7 @@ LD = @LD@ CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@ CROSSLDFLAGS = @CROSSLDFLAGS@ -PROGS = my_echo@exe@ +PROGS = my_echo@exe@ my_fds@exe@ all: $(PROGS) @@ -12,3 +12,9 @@ my_echo@exe@: my_echo@obj@ my_echo@obj@: my_echo.c $(CC) -c -o my_echo@obj@ $(CFLAGS) my_echo.c + +my_fds@exe@: my_fds@obj@ + $(LD) $(CROSSLDFLAGS) -o my_fds my_fds@obj@ @LIBS@ + +my_fds@obj@: my_fds.c + $(CC) -c -o my_fds@obj@ $(CFLAGS) my_fds.c diff --git a/lib/kernel/test/os_SUITE_data/my_fds.c b/lib/kernel/test/os_SUITE_data/my_fds.c new file mode 100644 index 0000000000..704a4d1e1d --- /dev/null +++ b/lib/kernel/test/os_SUITE_data/my_fds.c @@ -0,0 +1,9 @@ +#include + +int +main(int argc, char** argv) +{ + char buff[1]; + int res = read(stdin, buff, 1); + printf("%d", res); +} -- cgit v1.2.3 From 5b07e582ce6175d169e3e0d4c824e77ea336be6a Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 6 Sep 2016 09:42:38 +0200 Subject: kernel: Correct file(3) --- lib/kernel/doc/src/file.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index d734ee25b8..09497482cf 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -79,7 +79,7 @@ list_dir_all/1 and read_link_all/1.

-

See also section Notes About Raw Filenames in the STDLIB User´s Giude.

+

See also section Notes About Raw Filenames in the STDLIB User's Guide.

-- cgit v1.2.3 From c376e2a0fd5cc77ce6be99279a601e680b86a1b4 Mon Sep 17 00:00:00 2001 From: Peter Andersson Date: Wed, 20 Jul 2016 17:31:06 +0200 Subject: Fix incorrect priv_dir when adding app's ebin directory to path --- lib/kernel/src/code_server.erl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 48541ec500..29307bc696 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -811,7 +811,13 @@ clear_namedb([], _) -> %% Dir must be a complete pathname (not only a name). insert_dir(Dir, Db) -> Splitted = filename:split(Dir), - Name = get_name_from_splitted(Splitted), + case get_name_from_splitted(Splitted) of + Name when Name /= "ebin", Name /= "." -> + Name; + _ -> + SplittedAbsName = filename:split(absname(Dir)), + Name = get_name_from_splitted(SplittedAbsName) + end, AppDir = filename:join(del_ebin_1(Splitted)), do_insert_name(Name, AppDir, Db). @@ -952,6 +958,10 @@ del_ebin_1([Parent,App,"ebin"]) -> [Archive] end end; +del_ebin_1(Path = [_App,"ebin"]) -> + del_ebin_1(filename:split(absname(filename:join(Path)))); +del_ebin_1(["ebin"]) -> + del_ebin_1(filename:split(absname("ebin"))); del_ebin_1([H|T]) -> [H|del_ebin_1(T)]; del_ebin_1([]) -> -- cgit v1.2.3 From 82d673f8c9dd39cc78cb7567fe59ebda2b88bf2d Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Mon, 12 Sep 2016 10:14:50 +0200 Subject: Implement IPV6_TCLASS --- lib/kernel/doc/src/inet.xml | 9 +++++++++ lib/kernel/src/inet.erl | 10 +++++----- lib/kernel/src/inet_int.hrl | 1 + lib/kernel/test/gen_tcp_api_SUITE.erl | 21 ++++++++++++++++++++- 4 files changed, 35 insertions(+), 6 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index 3f4e3684f4..d907cef7d3 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -1092,6 +1092,15 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp The option is ignored on platforms where it is not implemented. Use with caution.

+ {tclass, Integer} + +

+ Sets IPV6_TCLASS IP level options on platforms + where this is implemented. The behavior and allowed range + varies between different systems. + The option is ignored on platforms where it is not + implemented. Use with caution.

+

In addition to these options, raw option specifications can be used. The raw options are diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 75dd800c6b..f5c13ecdd7 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -677,7 +677,7 @@ parse_strict_address(Addr) -> %% Return a list of available options options() -> [ - tos, priority, reuseaddr, keepalive, dontroute, linger, + tos, tclass, priority, reuseaddr, keepalive, dontroute, linger, broadcast, sndbuf, recbuf, nodelay, ipv6_v6only, buffer, header, active, packet, deliver, mode, multicast_if, multicast_ttl, multicast_loop, @@ -698,7 +698,7 @@ stats() -> %% Available options for tcp:connect %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% connect_options() -> - [tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, + [tos, tclass, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, header, active, packet, packet_size, buffer, mode, deliver, line_delimiter, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw, @@ -766,7 +766,7 @@ con_add(Name, Val, #connect_opts{} = R, Opts, AllOpts) -> %% Available options for tcp:listen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% listen_options() -> - [tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, + [tos, tclass, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, @@ -846,7 +846,7 @@ tcp_module_1(Opts, Address) -> %% Available options for udp:open %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% udp_options() -> - [tos, priority, reuseaddr, sndbuf, recbuf, header, active, buffer, mode, + [tos, tclass, priority, reuseaddr, sndbuf, recbuf, header, active, buffer, mode, deliver, ipv6_v6only, broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop, add_membership, drop_membership, read_packets,raw, @@ -917,7 +917,7 @@ udp_module(Opts) -> % (*) passing of open FDs ("fdopen") is not supported. sctp_options() -> [ % The following are generic inet options supported for SCTP sockets: - mode, active, buffer, tos, priority, dontroute, reuseaddr, linger, sndbuf, + mode, active, buffer, tos, tclass, priority, dontroute, reuseaddr, linger, sndbuf, recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark, % Other options are SCTP-specific (though they may be similar to their diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl index c8a8962e78..4e8f59a3b9 100644 --- a/lib/kernel/src/inet_int.hrl +++ b/lib/kernel/src/inet_int.hrl @@ -153,6 +153,7 @@ -define(INET_LOPT_NETNS, 38). -define(INET_LOPT_TCP_SHOW_ECONNRESET, 39). -define(INET_LOPT_LINE_DELIM, 40). +-define(INET_OPT_TCLASS, 41). % Specific SCTP options: separate range: -define(SCTP_OPT_RTOINFO, 100). -define(SCTP_OPT_ASSOCINFO, 101). diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index 77ec89b4f4..d630032480 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -38,7 +38,7 @@ t_local_basic/1, t_local_unbound/1, t_local_fdopen/1, t_local_fdopen_listen/1, t_local_fdopen_listen_unbound/1, t_local_fdopen_connect/1, t_local_fdopen_connect_unbound/1, - t_local_abstract/1]). + t_local_abstract/1, t_accept_inet6_tclass/1]). -export([getsockfd/0,closesockfd/1]). @@ -50,6 +50,7 @@ all() -> [{group, t_accept}, {group, t_connect}, {group, t_recv}, t_shutdown_write, t_shutdown_both, t_shutdown_error, t_shutdown_async, t_fdopen, t_fdconnect, t_implicit_inet6, + t_accept_inet6_tclass, {group, t_local}]. groups() -> @@ -521,6 +522,24 @@ local_handshake(S, SAddr, C, CAddr) -> SData = ok(gen_tcp:recv(C, length(SData))), ok. +t_accept_inet6_tclass(Config) when is_list(Config) -> + TClassOpt = {tclass,8#56 bsl 2}, % Expedited forwarding + case gen_tcp:listen(0, [inet6,TClassOpt]) of + {ok,L} -> + LPort = ok(inet:port(L)), + Loopback = {0,0,0,0,0,0,0,1}, + Sa = ok(gen_tcp:connect(Loopback, LPort, [])), + Sb = ok(gen_tcp:accept(L)), + [TClassOpt] = ok(inet:getopts(Sb, [tclass])), + ok = gen_tcp:close(Sb), + ok = gen_tcp:close(Sa), + ok = gen_tcp:close(L), + ok; + {error,_} -> + {skip,"IPv6 not supported"} + end. + + %%% Utilities %% Calls M:F/length(A), which should return a timeout error, and complete -- cgit v1.2.3 From 8d5a41b9eeae54d1135c570878fecc2ad3ad1d8e Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 13 Sep 2016 09:40:01 +0200 Subject: Tune 'tclass' semantics --- lib/kernel/test/gen_tcp_api_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index d630032480..92a74465b7 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -536,7 +536,7 @@ t_accept_inet6_tclass(Config) when is_list(Config) -> ok = gen_tcp:close(L), ok; {error,_} -> - {skip,"IPv6 not supported"} + {skip,"IPv6 TCLASS not supported"} end. -- cgit v1.2.3 From c70ca686fe269db6079a2ca1c7e09cdfc0cfa903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 5 Sep 2016 16:16:23 +0200 Subject: Don't leak old code when loading a modules with an on_load function Normally, calling code:delete/1 before re-loading the code for a module is unnecessary but causes no problem. But there will be be problems if the new code has an on_load function. Code with an on_load function will always be loaded as old code to allowed it to be easily purged if the on_load function would fail. If the on_load function succeeds, the old and current code will be swapped. So in the scenario where code:delete/1 has been called explicitly, there is old code but no current code. Loading code with an on_load function will cause the reference to the old code to be overwritten. That will at best cause a memory leak, and at worst an emulator crash (especially if NIFs are involved). To avoid that situation, we will put the code with the on_load function in a special, third slot in Module. ERL-240 --- lib/kernel/src/code_server.erl | 3 +- lib/kernel/test/code_SUITE.erl | 94 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 48541ec500..38c1169308 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1382,11 +1382,10 @@ finish_on_load(PidRef, OnLoadRes, #state{on_load=OnLoad0}=St0) -> finish_on_load_1(Mod, OnLoadRes, Waiting, St) -> Keep = OnLoadRes =:= ok, - erlang:finish_after_on_load(Mod, Keep), + erts_code_purger:finish_after_on_load(Mod, Keep), Res = case Keep of false -> _ = finish_on_load_report(Mod, OnLoadRes), - _ = erts_code_purger:purge(Mod), {error,on_load_failure}; true -> {module,Mod} diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 8da67c89f8..c5167efa56 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -36,6 +36,7 @@ code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, on_load_embedded/1, on_load_errors/1, on_load_update/1, on_load_purge/1, on_load_self_call/1, on_load_pending/1, + on_load_deleted/1, big_boot_embedded/1, native_early_modules/1, get_mode/1, normalized_paths/1]). @@ -66,6 +67,7 @@ all() -> bad_erl_libs, code_archive, code_archive2, on_load, on_load_binary, on_load_embedded, on_load_errors, on_load_update, on_load_purge, on_load_self_call, on_load_pending, + on_load_deleted, big_boot_embedded, native_early_modules, get_mode, normalized_paths]. groups() -> @@ -1602,6 +1604,98 @@ on_load_pending(_Config) -> ok = Mod:t(), ok. +on_load_deleted(_Config) -> + Mod = ?FUNCTION_NAME, + + R0 = fun() -> + Tree = ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() -> ok.\n"]), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree), + {module,Mod} = code:load_binary(Mod, "", Code) + end, + delete_before_reload(Mod, R0), + delete_before_reload(Mod, R0), + + R1 = fun() -> + Tree = ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() -> fail.\n"]), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree), + {error,on_load_failure} = code:load_binary(Mod, "", Code) + end, + delete_before_reload(Mod, R1), + delete_before_reload(Mod, R1), + + OtherMod = list_to_atom(lists:concat([Mod,"_42"])), + OtherTree = ?Q(["-module('@OtherMod@').\n"]), + merl:print(OtherTree), + {ok,OtherMod,OtherCode} = merl:compile(OtherTree), + + R2 = fun() -> + RegName = 'on_load__registered_name', + Tree = ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() ->\n", + " register('@RegName@', self()),\n", + " receive _ -> ok end.\n"]), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree), + spawn(fun() -> + {module,Mod} = code:load_binary(Mod, "", Code) + end), + receive after 1 -> ok end, + {module,OtherMod} = code:load_binary(OtherMod, "", + OtherCode), + RegName ! stop + end, + delete_before_reload(Mod, R2), + + ok. + +delete_before_reload(Mod, Reload) -> + false = check_old_code(Mod), + + Tree1 = ?Q(["-module('@Mod@').\n", + "-export([f/1]).\n", + "f(Parent) ->\n", + " register('@Mod@', self()),\n", + " Parent ! started,\n", + " receive _ -> ok end.\n"]), + merl:print(Tree1), + {ok,Mod,Code1} = merl:compile(Tree1), + + Self = self(), + spawn(fun() -> + {module,Mod} = code:load_binary(Mod, "", Code1), + Mod:f(Self) + end), + receive started -> ok end, + + true = code:delete(Mod), + true = check_old_code(Mod), + + Reload(), + + %% When loading the the module with the -on_load() function, + %% the reference to the old code would be lost. Make sure that + %% the old code is remembered and is still preventing the + %% purge. + false = code:soft_purge(Mod), + + %% Get rid of the old code. + Mod ! stop, + receive after 1 -> ok end, + true = code:soft_purge(Mod), + + %% Unload the version of the module with the -on_load() function. + true = code:delete(Mod), + true = code:soft_purge(Mod), + + ok. + %% Test that the native code of early loaded modules is loaded. native_early_modules(Config) when is_list(Config) -> -- cgit v1.2.3 From db12deff975c013a0ac02cfb49a339f8e6af5938 Mon Sep 17 00:00:00 2001 From: Luis Rascao Date: Sat, 10 Sep 2016 21:02:47 +0200 Subject: Allow for easier enabling of distribution debug Also update already deprecated calls. --- lib/kernel/include/dist_util.hrl | 2 +- lib/kernel/src/global.erl | 16 ++++++++++------ lib/kernel/src/net_kernel.erl | 4 +--- 3 files changed, 12 insertions(+), 10 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/include/dist_util.hrl b/lib/kernel/include/dist_util.hrl index 320e916c04..e3d2fe0eb6 100644 --- a/lib/kernel/include/dist_util.hrl +++ b/lib/kernel/include/dist_util.hrl @@ -29,7 +29,7 @@ -endif. -ifdef(dist_trace). --define(trace(Fmt,Args), io:format("~p ~p:~s",[erlang:now(),node(),lists:flatten(io_lib:format(Fmt, Args))])). +-define(trace(Fmt,Args), io:format("~p ~p:~s",[erlang:timestamp(),node(),lists:flatten(io_lib:format(Fmt, Args))])). % Use the one below for config-file (early boot) connection tracing %-define(trace(Fmt,Args), erlang:display([erlang:now(),node(),lists:flatten(io_lib:format(Fmt, Args))])). -define(trace_factor,8). diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index 0c73ead7c5..5e8bc2ba5d 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -58,14 +58,18 @@ %%% In certain places in the server, calling io:format hangs everything, %%% so we'd better use erlang:display/1. %%% my_tracer is used in testsuites --define(trace(_), ok). +%% uncomment this if tracing is wanted +%%-define(DEBUG, true). +-ifdef(DEBUG). +-define(trace(T), erlang:display({format, node(), cs(), T})). + cs() -> + {_Big, Small, Tiny} = erlang:timestamp(), + (Small rem 100) * 100 + (Tiny div 10000). %-define(trace(T), (catch my_tracer ! {node(), {line,?LINE}, T})). - -%-define(trace(T), erlang:display({format, node(), cs(), T})). -%cs() -> -% {_Big, Small, Tiny} = now(), -% (Small rem 100) * 100 + (Tiny div 10000). +-else. +-define(trace(_), ok). +-endif. %% These are the protocol versions: %% Vsn 1 is the original protocol. diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl index 0c679e7349..0a9f9316b0 100644 --- a/lib/kernel/src/net_kernel.erl +++ b/lib/kernel/src/net_kernel.erl @@ -26,15 +26,13 @@ %%-define(dist_debug, true). -%-define(DBG,erlang:display([?MODULE,?LINE])). - -ifdef(dist_debug). -define(debug(Term), erlang:display(Term)). -else. -define(debug(Term), ok). -endif. --ifdef(DEBUG). +-ifdef(dist_debug). -define(connect_failure(Node,Term), io:format("Net Kernel 2: Failed connection to node ~p, reason ~p~n", [Node,Term])). -- cgit v1.2.3 From 3489b9b689073f428a23f7fc7a67774b7dda07be Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 18 Sep 2016 12:33:08 +0200 Subject: Use more correct delimiters for erl_nif.h include Anywhere but the beam sources we shouldn't #include "erl_nif.h", because what "erl_nif.h" does is: (1) fail to find it outside of -I dirs, (2) then treat it as if it was written like . Using skips (1). More information can be found in 6.10.2 of the C standard. Because the examples use "erl_nif.h", NIF projects in the Erlang ecosystem copy this verbatim and make the same mistake. --- lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c index 2990ddda41..b91dca61d4 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c +++ b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c @@ -17,7 +17,7 @@ * * %CopyrightEnd% */ -#include "erl_nif.h" +#include #include #include -- cgit v1.2.3 From 37e14c395a0d3621d65552b3954856d1cbeaed9a Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 20 Sep 2016 09:36:54 +0200 Subject: Prepare release --- lib/kernel/doc/src/notes.xml | 68 ++++++++++++++++++++++++++++++++++++++++++++ lib/kernel/vsn.mk | 2 +- 2 files changed, 69 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 9e9be3f661..5bcc0b7c09 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,74 @@

This document describes the changes made to the Kernel application.

+
Kernel 5.1 + +
Fixed Bugs and Malfunctions + + +

+ Fix a memory leak when calling + seq_trace:get_system_tracer().

+

+ Own Id: OTP-13742

+
+ +

+ Fix for the problem that when adding the ebin directory + of an application to the code path, the + code:priv_dir/1 function returns an incorrect path + to the priv directory of the same application.

+

+ Own Id: OTP-13758 Aux Id: ERL-195

+
+ +

+ Fix code_server crash when adding code paths of two + levels.

+

+ Own Id: OTP-13765 Aux Id: ERL-194

+
+ +

+ Respect -proto_dist switch while connection to EPMD

+

+ Own Id: OTP-13770 Aux Id: PR-1129

+
+ +

+ Fixed a bug where init:stop could deadlock if a process + with infinite shutdown timeout (e.g. a supervisor) + attempted to load code while terminating.

+

+ Own Id: OTP-13802

+
+ +

+ Close stdin of commands run in os:cmd. This is a + backwards compatiblity fix that restores the behaviour of + pre 19.0 os:cmd.

+

+ Own Id: OTP-13867 Aux Id: seq13178

+
+
+
+ + +
Improvements and New Features + + +

+ Add net_kernel:setopts/2 and + net_kernel:getopts/2 to control options for + distribution sockets in runtime.

+

+ Own Id: OTP-13564

+
+
+
+ +
+
Kernel 5.0.2
Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index cdd200a234..d3b2d18ae5 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.0.2 +KERNEL_VSN = 5.1 -- cgit v1.2.3 From 3f3f25b23379b1afb15cc97462cf5d385690f5a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 22 Sep 2016 12:19:40 +0200 Subject: file_SUITE: Test file:write_file/3 Extend file_SUITE:read_write_file/1 to test file:write_file/3 which was not tested at all. While we are it, remove the superfluous roundtrips tests of term_to_binary/1 and binary_to_term/1. Those BIFs are tested in detail in other test suites (for example, binary_SUITE in emulator_test). --- lib/kernel/test/file_SUITE.erl | 54 ++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 23 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 5f049c6f99..c37d114a58 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -493,22 +493,13 @@ read_write_file(Config) when is_list(Config) -> %% Try writing and reading back some term SomeTerm = {"This term",{will,be},[written,$t,$o],1,file,[]}, - ok = ?FILE_MODULE:write_file(Name,term_to_binary(SomeTerm)), - {ok,Bin1} = ?FILE_MODULE:read_file(Name), - SomeTerm = binary_to_term(Bin1), + Bin1 = term_to_binary(SomeTerm), + ok = do_read_write_file(Name, Bin1), %% Try a "null" term NullTerm = [], - ok = ?FILE_MODULE:write_file(Name,term_to_binary(NullTerm)), - {ok,Bin2} = ?FILE_MODULE:read_file(Name), - NullTerm = binary_to_term(Bin2), - - %% Try some "complicated" types - BigNum = 123456789012345678901234567890, - ComplTerm = {self(),make_ref(),BigNum,3.14159}, - ok = ?FILE_MODULE:write_file(Name,term_to_binary(ComplTerm)), - {ok,Bin3} = ?FILE_MODULE:read_file(Name), - ComplTerm = binary_to_term(Bin3), + Bin2 = term_to_binary(NullTerm), + ok = do_read_write_file(Name, Bin2), %% Try reading a nonexistent file Name2 = filename:join(RootDir, @@ -519,25 +510,42 @@ read_write_file(Config) when is_list(Config) -> {error, enoent} = ?FILE_MODULE:read_file(''), %% Try writing to a bad filename - {error, enoent} = - ?FILE_MODULE:write_file("",term_to_binary(NullTerm)), + {error, enoent} = do_read_write_file("", Bin2), %% Try writing something else than a binary - {error, badarg} = ?FILE_MODULE:write_file(Name,{1,2,3}), - {error, badarg} = ?FILE_MODULE:write_file(Name,self()), + {error, badarg} = do_read_write_file(Name, {1,2,3}), + {error, badarg} = do_read_write_file(Name, self()), %% Some non-term binaries - ok = ?FILE_MODULE:write_file(Name,[]), - {ok,Bin4} = ?FILE_MODULE:read_file(Name), - 0 = byte_size(Bin4), + ok = do_read_write_file(Name, []), - ok = ?FILE_MODULE:write_file(Name,[Bin1,[],[[Bin2]]]), - {ok,Bin5} = ?FILE_MODULE:read_file(Name), - {Bin1,Bin2} = split_binary(Bin5,byte_size(Bin1)), + %% Write some iolists + ok = do_read_write_file(Name, [Bin1,[],[[Bin2]]]), + ok = do_read_write_file(Name, ["string",<<"binary">>]), + ok = do_read_write_file(Name, "pure string"), [] = flush(), ok. +do_read_write_file(Name, Data) -> + case ?FILE_MODULE:write_file(Name, Data) of + ok -> + BinData = iolist_to_binary(Data), + {ok,BinData} = ?FILE_MODULE:read_file(Name), + + ok = ?FILE_MODULE:write_file(Name, Data, []), + {ok,BinData} = ?FILE_MODULE:read_file(Name), + + ok = ?FILE_MODULE:write_file(Name, Data, [raw]), + {ok,BinData} = ?FILE_MODULE:read_file(Name), + + ok; + {error,_}=Res -> + Res = ?FILE_MODULE:write_file(Name, Data, []), + Res = ?FILE_MODULE:write_file(Name, Data, [raw]), + Res + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3 From 07b0f4315b079cce7aeef7babdba1bbb686de611 Mon Sep 17 00:00:00 2001 From: Nathan Long Date: Tue, 13 Sep 2016 08:36:42 -0400 Subject: Let file:write_file/3 use writev Previously, this function would turn any input into a single binary before writing. This meant it could not take advantage of the `writev` system call if it was given a list of binaries and told to write with `raw` mode. To see this, start an erlang shell on the parent commit, and also start this dtrace script: https://github.com/evanmiller/tracewrite like this: sudo dtrace -s tracewrite.d -p $(pgrep beam) In the erlang shell, run the following: file:write_file("/tmp/tmp.txt", [<<97,98>>, <<98,97>>], [raw]). In the dtrace output, you will see that the system call used is `write`. Now repeat with this commit, and you will see that `writev` is used. --- lib/kernel/src/file.erl | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 58b601e456..1971df9038 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -397,25 +397,36 @@ write_file(Name, Bin) -> Modes :: [mode()], Reason :: posix() | badarg | terminated | system_limit. -write_file(Name, Bin, ModeList) when is_list(ModeList) -> - case make_binary(Bin) of - B when is_binary(B) -> - case open(Name, [binary, write | - lists:delete(binary, - lists:delete(write, ModeList))]) of - {ok, Handle} -> - case write(Handle, B) of - ok -> - close(Handle); - E1 -> - _ = close(Handle), - E1 - end; - E2 -> - E2 - end; - E3 -> - E3 +write_file(Name, IOData, ModeList) when is_list(ModeList) -> + case lists:member(raw, ModeList) of + true -> + %% For backwards compatibility of error messages + try iolist_size(IOData) of + _Size -> do_write_file(Name, IOData, ModeList) + catch + error:Error -> {error, Error} + end; + false -> + case make_binary(IOData) of + Bin when is_binary(Bin) -> + do_write_file(Name, Bin, ModeList); + Error -> + Error + end + end. + +do_write_file(Name, IOData, ModeList) -> + case open(Name, [binary, write | ModeList]) of + {ok, Handle} -> + case write(Handle, IOData) of + ok -> + close(Handle); + E1 -> + _ = close(Handle), + E1 + end; + E2 -> + E2 end. %% Obsolete, undocumented, local node only, don't use!. -- cgit v1.2.3 From 2e232b0449ca9aa0fd1854672cb87f902323ccdf Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 26 Sep 2016 16:58:03 +0200 Subject: Update appups in kernel and stdlib for OTP versions > 19.1 --- lib/kernel/src/kernel.appup.src | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index d16e200cb3..82cf73cbda 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"5\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.* %% Down to - max one major revision back - [{<<"5\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.* }. -- cgit v1.2.3 From 024092849b5feab979018c05cfdab640c3f2cecf Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 27 Sep 2016 11:13:41 +0200 Subject: Update appups in kernel, stdlib and sasl for OTP-20 --- lib/kernel/src/kernel.appup.src | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 82cf73cbda..b505524471 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,9 +18,7 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* - {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.* + [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.* %% Down to - max one major revision back - [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* - {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.* + [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.* }. -- cgit v1.2.3 From 714570912d678c10f4aa4b6a6692d958e0fc7fe7 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Wed, 28 Sep 2016 16:40:19 +0200 Subject: Document the order of directories added with code:add_pathsa/1 code:add_pathsa/1 reverts the list of directories when adding it at the beginning of the code path. The command line option '-pa' behaves in the same way. This is now documented. --- lib/kernel/doc/src/code.xml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 4db377bcde..3143cdc825 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -382,9 +382,14 @@ zip:create("mnesia-4.4.7.ez", Add directories to the beginning of the code path. -

Adds the directories in Dirs to the beginning of - the code path. If a Dir exists, it is removed - from the old position in the code path.

+

Traverses Dirs and adds + each Dir to the beginning of the code + path. This means that the order of Dirs + is reversed in the resulting code path. For example, if you + add [Dir1,Dir2], the resulting path will + be [Dir2,Dir1|OldCodePath].

+

If a Dir already exists in the code + path, it is removed from the old position.

Always returns ok, regardless of the validity of each individual Dir.

-- cgit v1.2.3 From 16d295c98f46e468ab1f7f4b3e6bfeb8f0f5749e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 15 Sep 2016 21:18:28 +0200 Subject: hipe_unified_loader: Refactor rename all Addresses to FunDefs as they are lists of #fundef records --- lib/kernel/src/hipe_unified_loader.erl | 120 ++++++++++++++++----------------- 1 file changed, 60 insertions(+), 60 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 087cceb5d8..7b1e6c2591 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -229,15 +229,15 @@ load_common(Mod, Bin, Beam, OldReferencesToPatch, Architecture) -> %% Patch references to code labels in data seg. ok = patch_consts(LabelMap, ConstAddr, CodeAddress, WriteWord), %% Find out which functions are being loaded (and where). - %% Note: Addresses are sorted descending. - {MFAs,Addresses} = exports(ExportMap, CodeAddress), + %% Note: FunDefs are sorted descending. + {MFAs,FunDefs} = exports(ExportMap, CodeAddress), %% Remove references to old versions of the module. ReferencesToPatch = get_refs_from(MFAs, []), %% io:format("References to patch: ~w~n", [ReferencesToPatch]), ok = remove_refs_from(MFAs), %% Patch all dynamic references in the code. %% Function calls, Atoms, Constants, System calls - ok = patch(Refs, CodeAddress, ConstMap2, Addresses, TrampolineMap), + ok = patch(Refs, CodeAddress, ConstMap2, FunDefs, TrampolineMap), %% Tell the system where the loaded funs are. %% (patches the BEAM code to redirect to native.) @@ -250,23 +250,23 @@ load_common(Mod, Bin, Beam, OldReferencesToPatch, Architecture) -> lists:foreach(fun({FE, DestAddress}) -> hipe_bifs:set_native_address_in_fe(FE, DestAddress) end, erase(closures_to_patch)), - export_funs(Addresses), + export_funs(FunDefs), ok; BeamBinary when is_binary(BeamBinary) -> %% Find all closures in the code. [] = erase(closures_to_patch), %Clean up, assertion. ClosurePatches = find_closure_patches(Refs), AddressesOfClosuresToPatch = - calculate_addresses(ClosurePatches, CodeAddress, Addresses), - export_funs(Addresses), + calculate_addresses(ClosurePatches, CodeAddress, FunDefs), + export_funs(FunDefs), export_funs(Mod, MD5, BeamBinary, - Addresses, AddressesOfClosuresToPatch) + FunDefs, AddressesOfClosuresToPatch) end, %% Redirect references to the old module to the new module's BEAM stub. patch_to_emu_step2(OldReferencesToPatch), %% Patch referring functions to call the new function %% The call to export_funs/1 above updated the native addresses - %% for the targets, so passing 'Addresses' is not needed. + %% for the targets, so passing 'FunDefs' is not needed. redirect(ReferencesToPatch), %% Final clean up. _ = erase(hipe_patch_closures), @@ -373,29 +373,29 @@ trampoline_map_lookup(Primop, Map) -> exports(ExportMap, BaseAddress) -> exports(ExportMap, BaseAddress, [], []). -exports([Offset,M,F,A,IsClosure,IsExported|Rest], BaseAddress, MFAs, Addresses) -> +exports([Offset,M,F,A,IsClosure,IsExported|Rest], BaseAddress, MFAs, FunDefs) -> case IsExported andalso erlang:is_builtin(M, F, A) of true -> - exports(Rest, BaseAddress, MFAs, Addresses); + exports(Rest, BaseAddress, MFAs, FunDefs); _false -> MFA = {M,F,A}, Address = BaseAddress + Offset, FunDef = #fundef{address=Address, mfa=MFA, is_closure=IsClosure, is_exported=IsExported}, - exports(Rest, BaseAddress, [MFA|MFAs], [FunDef|Addresses]) + exports(Rest, BaseAddress, [MFA|MFAs], [FunDef|FunDefs]) end; -exports([], _, MFAs, Addresses) -> - {MFAs, Addresses}. +exports([], _, MFAs, FunDefs) -> + {MFAs, FunDefs}. mod({M,_F,_A}) -> M. %%------------------------------------------------------------------------ -calculate_addresses(PatchOffsets, Base, Addresses) -> +calculate_addresses(PatchOffsets, Base, FunDefs) -> RemoteOrLocal = local, % closure code refs are local [{Data, offsets_to_addresses(Offsets, Base), - get_native_address(DestMFA, Addresses, RemoteOrLocal)} || + get_native_address(DestMFA, FunDefs, RemoteOrLocal)} || {{DestMFA,_,_}=Data,Offsets} <- PatchOffsets]. offsets_to_addresses(Os, Base) -> @@ -424,7 +424,7 @@ find_closure_refs([], Refs) -> %%------------------------------------------------------------------------ -export_funs([FunDef | Addresses]) -> +export_funs([FunDef | FunDefs]) -> #fundef{address=Address, mfa=MFA, is_closure=IsClosure, is_exported=IsExported} = FunDef, ?IF_DEBUG({M,F,A} = MFA, no_debug), @@ -439,19 +439,19 @@ export_funs([FunDef | Addresses]) -> end, no_debug), hipe_bifs:set_funinfo_native_address(MFA, Address, IsExported), hipe_bifs:set_native_address(MFA, Address, IsClosure), - export_funs(Addresses); + export_funs(FunDefs); export_funs([]) -> ok. -export_funs(Mod, MD5, Beam, Addresses, ClosuresToPatch) -> - Fs = [{F,A,Address} || #fundef{address=Address, mfa={_M,F,A}} <- Addresses], +export_funs(Mod, MD5, Beam, FunDefs, ClosuresToPatch) -> + Fs = [{F,A,Address} || #fundef{address=Address, mfa={_M,F,A}} <- FunDefs], Mod = code:make_stub_module(Mod, Beam, {Fs,ClosuresToPatch,MD5}), ok. %%======================================================================== %% Patching %% @spec patch(refs(), BaseAddress::integer(), ConstAndZone::term(), -%% Addresses::term(), TrampolineMap::term()) -> 'ok'. +%% FunDefs::term(), TrampolineMap::term()) -> 'ok'. %% @type refs()=[{RefType::integer(), Reflist::reflist()} | refs()] %% %% @type reflist()= [{Data::term(), Offsets::offests()}|reflist()] @@ -463,39 +463,39 @@ export_funs(Mod, MD5, Beam, Addresses, ClosuresToPatch) -> %% (we use this to look up the address of a referred function only once). %% -patch([{Type,SortedRefs}|Rest], CodeAddress, ConstMap2, Addresses, TrampolineMap) -> +patch([{Type,SortedRefs}|Rest], CodeAddress, ConstMap2, FunDefs, TrampolineMap) -> ?debug_msg("Patching ~w at [~w+offset] with ~w\n", [Type,CodeAddress,SortedRefs]), case ?EXT2PATCH_TYPE(Type) of call_local -> - patch_call(SortedRefs, CodeAddress, Addresses, 'local', TrampolineMap); + patch_call(SortedRefs, CodeAddress, FunDefs, 'local', TrampolineMap); call_remote -> - patch_call(SortedRefs, CodeAddress, Addresses, 'remote', TrampolineMap); + patch_call(SortedRefs, CodeAddress, FunDefs, 'remote', TrampolineMap); Other -> - patch_all(Other, SortedRefs, CodeAddress, {ConstMap2,CodeAddress}, Addresses) + patch_all(Other, SortedRefs, CodeAddress, {ConstMap2,CodeAddress}, FunDefs) end, - patch(Rest, CodeAddress, ConstMap2, Addresses, TrampolineMap); + patch(Rest, CodeAddress, ConstMap2, FunDefs, TrampolineMap); patch([], _, _, _, _) -> ok. %%---------------------------------------------------------------- %% Handle a 'call_local' or 'call_remote' patch. %% -patch_call([{DestMFA,Offsets}|SortedRefs], BaseAddress, Addresses, RemoteOrLocal, TrampolineMap) -> +patch_call([{DestMFA,Offsets}|SortedRefs], BaseAddress, FunDefs, RemoteOrLocal, TrampolineMap) -> case bif_address(DestMFA) of false -> - %% Previous code used mfa_to_address(DestMFA, Addresses) + %% Previous code used mfa_to_address(DestMFA, FunDefs) %% here for local calls. That is wrong because even local - %% destinations may not be present in Addresses: they may + %% destinations may not be present in FunDefs: they may %% not have been compiled yet, or they may be BEAM-only %% functions (e.g. module_info). - DestAddress = get_native_address(DestMFA, Addresses, RemoteOrLocal), + DestAddress = get_native_address(DestMFA, FunDefs, RemoteOrLocal), Trampoline = trampoline_map_get(DestMFA, TrampolineMap), - patch_mfa_call_list(Offsets, BaseAddress, DestMFA, DestAddress, Addresses, RemoteOrLocal, Trampoline); + patch_mfa_call_list(Offsets, BaseAddress, DestMFA, DestAddress, FunDefs, RemoteOrLocal, Trampoline); BifAddress when is_integer(BifAddress) -> Trampoline = trampoline_map_lookup(DestMFA, TrampolineMap), patch_bif_call_list(Offsets, BaseAddress, BifAddress, Trampoline) end, - patch_call(SortedRefs, BaseAddress, Addresses, RemoteOrLocal, TrampolineMap); + patch_call(SortedRefs, BaseAddress, FunDefs, RemoteOrLocal, TrampolineMap); patch_call([], _, _, _, _) -> ok. @@ -506,12 +506,12 @@ patch_bif_call_list([Offset|Offsets], BaseAddress, BifAddress, Trampoline) -> patch_bif_call_list(Offsets, BaseAddress, BifAddress, Trampoline); patch_bif_call_list([], _, _, _) -> ok. -patch_mfa_call_list([Offset|Offsets], BaseAddress, DestMFA, DestAddress, Addresses, RemoteOrLocal, Trampoline) -> +patch_mfa_call_list([Offset|Offsets], BaseAddress, DestMFA, DestAddress, FunDefs, RemoteOrLocal, Trampoline) -> CallAddress = BaseAddress+Offset, - add_ref(DestMFA, CallAddress, Addresses, 'call', Trampoline, RemoteOrLocal), + add_ref(DestMFA, CallAddress, FunDefs, 'call', Trampoline, RemoteOrLocal), ?ASSERT(assert_local_patch(CallAddress)), patch_call_insn(CallAddress, DestAddress, Trampoline), - patch_mfa_call_list(Offsets, BaseAddress, DestMFA, DestAddress, Addresses, RemoteOrLocal, Trampoline); + patch_mfa_call_list(Offsets, BaseAddress, DestMFA, DestAddress, FunDefs, RemoteOrLocal, Trampoline); patch_mfa_call_list([], _, _, _, _, _, _) -> ok. patch_call_insn(CallAddress, DestAddress, Trampoline) -> @@ -522,33 +522,33 @@ patch_call_insn(CallAddress, DestAddress, Trampoline) -> %% ____________________________________________________________________ %% -patch_all(Type, [{Dest,Offsets}|Rest], BaseAddress, ConstAndZone, Addresses)-> - patch_all_offsets(Type, Dest, Offsets, BaseAddress, ConstAndZone, Addresses), - patch_all(Type, Rest, BaseAddress, ConstAndZone, Addresses); +patch_all(Type, [{Dest,Offsets}|Rest], BaseAddress, ConstAndZone, FunDefs)-> + patch_all_offsets(Type, Dest, Offsets, BaseAddress, ConstAndZone, FunDefs), + patch_all(Type, Rest, BaseAddress, ConstAndZone, FunDefs); patch_all(_, [], _, _, _) -> ok. patch_all_offsets(Type, Data, [Offset|Offsets], BaseAddress, - ConstAndZone, Addresses) -> + ConstAndZone, FunDefs) -> ?debug_msg("Patching ~w at [~w+~w] with ~w\n", [Type,BaseAddress,Offset, Data]), Address = BaseAddress + Offset, - patch_offset(Type, Data, Address, ConstAndZone, Addresses), + patch_offset(Type, Data, Address, ConstAndZone, FunDefs), ?debug_msg("Patching done\n",[]), - patch_all_offsets(Type, Data, Offsets, BaseAddress, ConstAndZone, Addresses); + patch_all_offsets(Type, Data, Offsets, BaseAddress, ConstAndZone, FunDefs); patch_all_offsets(_, _, [], _, _, _) -> ok. %%---------------------------------------------------------------- %% Handle any patch type except 'call_local' or 'call_remote'. %% -patch_offset(Type, Data, Address, ConstAndZone, Addresses) -> +patch_offset(Type, Data, Address, ConstAndZone, FunDefs) -> case Type of load_address -> - patch_load_address(Data, Address, ConstAndZone, Addresses); + patch_load_address(Data, Address, ConstAndZone, FunDefs); load_atom -> Atom = Data, patch_atom(Address, Atom); sdesc -> - patch_sdesc(Data, Address, ConstAndZone, Addresses); + patch_sdesc(Data, Address, ConstAndZone, FunDefs); x86_abs_pcrel -> patch_instr(Address, Data, x86_abs_pcrel) %% _ -> @@ -561,37 +561,37 @@ patch_atom(Address, Atom) -> patch_instr(Address, hipe_bifs:atom_to_word(Atom), atom). patch_sdesc(?STACK_DESC(SymExnRA, FSize, Arity, Live), - Address, {_ConstMap2,CodeAddress}, _Addresses) -> + Address, {_ConstMap2,CodeAddress}, _FunDefs) -> ExnRA = case SymExnRA of [] -> 0; % No catch LabelOffset -> CodeAddress + LabelOffset end, ?ASSERT(assert_local_patch(Address)), - DBG_MFA = ?IF_DEBUG(address_to_mfa_lth(Address, _Addresses), {undefined,undefined,0}), + DBG_MFA = ?IF_DEBUG(address_to_mfa_lth(Address, _FunDefs), {undefined,undefined,0}), hipe_bifs:enter_sdesc({Address, ExnRA, FSize, Arity, Live, DBG_MFA}). %%---------------------------------------------------------------- %% Handle a 'load_address'-type patch. %% -patch_load_address(Data, Address, ConstAndZone, Addresses) -> +patch_load_address(Data, Address, ConstAndZone, FunDefs) -> case Data of {local_function,DestMFA} -> - patch_load_mfa(Address, DestMFA, Addresses, 'local'); + patch_load_mfa(Address, DestMFA, FunDefs, 'local'); {remote_function,DestMFA} -> - patch_load_mfa(Address, DestMFA, Addresses, 'remote'); + patch_load_mfa(Address, DestMFA, FunDefs, 'remote'); {constant,Name} -> {ConstMap2,_CodeAddress} = ConstAndZone, ConstAddress = find_const(Name, ConstMap2), patch_instr(Address, ConstAddress, constant); {closure,{DestMFA,Uniq,Index}} -> - patch_closure(DestMFA, Uniq, Index, Address, Addresses); + patch_closure(DestMFA, Uniq, Index, Address, FunDefs); {c_const,CConst} -> patch_instr(Address, bif_address(CConst), c_const) end. -patch_closure(DestMFA, Uniq, Index, Address, Addresses) -> +patch_closure(DestMFA, Uniq, Index, Address, FunDefs) -> case get(hipe_patch_closures) of false -> []; % This is taken care of when registering the module. @@ -602,7 +602,7 @@ patch_closure(DestMFA, Uniq, Index, Address, Addresses) -> %% address into the fun entry to ensure that the native code cannot %% be called until it has been completely fixed up. RemoteOrLocal = local, % closure code refs are local - DestAddress = get_native_address(DestMFA, Addresses, RemoteOrLocal), + DestAddress = get_native_address(DestMFA, FunDefs, RemoteOrLocal), BEAMAddress = hipe_bifs:fun_to_address(DestMFA), FE = hipe_bifs:get_fe(mod(DestMFA), {Uniq, Index, BEAMAddress}), put(closures_to_patch, [{FE,DestAddress}|get(closures_to_patch)]), @@ -616,12 +616,12 @@ patch_closure(DestMFA, Uniq, Index, Address, Addresses) -> %% Patch an instruction loading the address of an MFA. %% RemoteOrLocal ::= 'remote' | 'local' %% -patch_load_mfa(CodeAddress, DestMFA, Addresses, RemoteOrLocal) -> +patch_load_mfa(CodeAddress, DestMFA, FunDefs, RemoteOrLocal) -> DestAddress = case bif_address(DestMFA) of false -> - NativeAddress = get_native_address(DestMFA, Addresses, RemoteOrLocal), - add_ref(DestMFA, CodeAddress, Addresses, 'load_mfa', [], RemoteOrLocal), + NativeAddress = get_native_address(DestMFA, FunDefs, RemoteOrLocal), + add_ref(DestMFA, CodeAddress, FunDefs, 'load_mfa', [], RemoteOrLocal), NativeAddress; BifAddress when is_integer(BifAddress) -> BifAddress @@ -772,7 +772,7 @@ find_const(ConstNo, []) -> %%---------------------------------------------------------------- %% Record that the code at address 'Address' has a reference %% of type 'RefType' ('call' or 'load_mfa') to 'CalleeMFA'. -%% 'Addresses' must be an address-descending list from exports/2. +%% 'FunDefs' must be an address-descending list from exports/2. %% %% If 'RefType' is 'call', then 'Trampoline' may be the address %% of a stub branching to 'CalleeMFA', where the stub is reachable @@ -785,8 +785,8 @@ find_const(ConstNo, []) -> %% -record(ref, {caller_mfa, address, ref_type, trampoline, remote_or_local}). %% -add_ref(CalleeMFA, Address, Addresses, RefType, Trampoline, RemoteOrLocal) -> - CallerMFA = address_to_mfa_lth(Address, Addresses), +add_ref(CalleeMFA, Address, FunDefs, RefType, Trampoline, RemoteOrLocal) -> + CallerMFA = address_to_mfa_lth(Address, FunDefs), %% just a sanity assertion below true = case RemoteOrLocal of local -> @@ -904,13 +904,13 @@ remove_refs_from(MFAs) -> %%-------------------------------------------------------------------- %% To find the native code of an MFA we need to look in 3 places: -%% 1. If it is compiled now look in the Addresses data structure. +%% 1. If it is compiled now look in the FunDefs data structure. %% 2. Then look in native_addresses from module info. %% 3. Then (the function might have been singled compiled) look in %% hipe_funinfo %% If all else fails create a native stub for the MFA -get_native_address(MFA, Addresses, RemoteOrLocal) -> - case mfa_to_address(MFA, Addresses, RemoteOrLocal) of +get_native_address(MFA, FunDefs, RemoteOrLocal) -> + case mfa_to_address(MFA, FunDefs, RemoteOrLocal) of Adr when is_integer(Adr) -> Adr; false -> IsRemote = -- cgit v1.2.3 From 099c60de4033d7b397d4b3fb47f183b52fcba855 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 15 Sep 2016 21:21:10 +0200 Subject: erts: Improve hipe load/upgrade/purge machinery A step toward better integration of hipe load and purge Highlights: * code_server no longer needs to call hipe_unified_loader:post_beam_load/1 Instead new internal function hipe_redirect_to_module() is called by loading BIFs to patch native call sites if needed. * hipe_purge_module() is called by erts_internal:purge_module/2 to purge any native code. * struct hipe_mfa_info redesigned and only used for exported functions that are called from or implemented by native code. A list of native call sites (struct hipe_ref) are kept for each hipe_mfa_info. * struct hipe_sdesc used by hipe_find_mfa_from_ra() to build native stack traces. --- lib/kernel/src/code_server.erl | 24 +-- lib/kernel/src/hipe_unified_loader.erl | 233 ++++++--------------- lib/kernel/test/code_SUITE.erl | 30 +-- lib/kernel/test/code_SUITE_data/upgrade_client.erl | 88 +++++++- lib/kernel/test/code_SUITE_data/upgradee.erl | 12 ++ 5 files changed, 187 insertions(+), 200 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 835b7eb588..90ecb22074 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1130,7 +1130,7 @@ try_load_module_2(File, Mod, Bin, From, Architecture, #state{moddb=Db}=St) -> case catch hipe_unified_loader:load_native_code(Mod, Bin, Architecture) of {module,Mod} = Module -> - ets:insert(Db, [{{native,Mod},true},{Mod,File}]), + ets:insert(Db, {Mod,File}), {reply,Module,St}; no_native -> try_load_module_3(File, Mod, Bin, From, Architecture, St); @@ -1139,10 +1139,9 @@ try_load_module_2(File, Mod, Bin, From, Architecture, {reply,ok,St} end. -try_load_module_3(File, Mod, Bin, From, Architecture, St0) -> +try_load_module_3(File, Mod, Bin, From, _Architecture, St0) -> Action = fun({module,_}=Module, #state{moddb=Db}=S) -> ets:insert(Db, {Mod,File}), - post_beam_load([Mod], Architecture, S), {reply,Module,S}; ({error,on_load_failure}=Error, S) -> {reply,Error,S}; @@ -1153,24 +1152,14 @@ try_load_module_3(File, Mod, Bin, From, Architecture, St0) -> Res = erlang:load_module(Mod, Bin), handle_on_load(Res, Action, Mod, From, St0). -hipe_result_to_status(Result, #state{moddb=Db}) -> +hipe_result_to_status(Result, #state{}) -> case Result of - {module,Mod} -> - ets:insert(Db, [{{native,Mod},true}]), + {module,_} -> Result; _ -> {error,Result} end. -post_beam_load(_, undefined, _) -> - %% HiPE is disabled. - ok; -post_beam_load(Mods0, _Architecture, #state{moddb=Db}) -> - %% post_beam_load/2 can potentially be very expensive because it - %% blocks multi-scheduling. Therefore, we only want to call - %% it with modules that are known to have native code loaded. - Mods = [M || M <- Mods0, ets:member(Db, {native,M})], - hipe_unified_loader:post_beam_load(Mods). int_list([H|T]) when is_integer(H) -> int_list(T); int_list([_|_]) -> false; @@ -1313,15 +1302,12 @@ abort_if_sticky(L, Db) -> [_|_] -> {error,Sticky} end. -do_finish_loading(Prepared, #state{moddb=Db}=St) -> +do_finish_loading(Prepared, #state{moddb=Db}) -> MagicBins = [B || {_,{B,_}} <- Prepared], case erlang:finish_loading(MagicBins) of ok -> MFs = [{M,F} || {M,{_,F}} <- Prepared], true = ets:insert(Db, MFs), - Ms = [M || {M,_} <- MFs], - Architecture = erlang:system_info(hipe_architecture), - post_beam_load(Ms, Architecture, St), ok; {Reason,Ms} -> {error,[{M,Reason} || M <- Ms]} diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 7b1e6c2591..75a5995695 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -41,10 +41,11 @@ % I think the real solution would be to let BIF erlang:load_module/2 redirect all % hipe calls to the module and thereby remove post_beam_load. +% SVERK: Can we remove -compile(no_native) now when post_beam_load is gone? + -export([chunk_name/1, %% Only the code and code_server modules may call the entries below! load_native_code/3, - post_beam_load/1, load_module/4, load/3]). @@ -101,15 +102,13 @@ word_size(Architecture) -> load_native_code(_Mod, _Bin, undefined) -> no_native; load_native_code(Mod, Bin, Architecture) when is_atom(Mod), is_binary(Bin) -> - %% patch_to_emu(Mod), case code:get_chunk(Bin, chunk_name(Architecture)) of undefined -> no_native; NativeCode when is_binary(NativeCode) -> erlang:system_flag(multi_scheduling, block_normal), try - OldReferencesToPatch = patch_to_emu_step1(Mod), - case load_module(Mod, NativeCode, Bin, OldReferencesToPatch, - Architecture) of + put(hipe_patch_closures, false), + case load_common(Mod, NativeCode, Bin, Architecture) of bad_crc -> no_native; Result -> Result end @@ -120,22 +119,6 @@ load_native_code(Mod, Bin, Architecture) when is_atom(Mod), is_binary(Bin) -> %%======================================================================== --spec post_beam_load([module()]) -> 'ok'. - -post_beam_load([])-> - ok; -post_beam_load([_|_]=Mods) -> - erlang:system_flag(multi_scheduling, block_normal), - try - _ = [patch_to_emu(Mod) || Mod <- Mods], - ok - after - erlang:system_flag(multi_scheduling, unblock_normal) - end, - ok. - -%%======================================================================== - version_check(Version, Mod) when is_atom(Mod) -> Ver = ?VERSION_STRING(), case Version < Ver of @@ -153,19 +136,12 @@ version_check(Version, Mod) when is_atom(Mod) -> load_module(Mod, Bin, Beam, Architecture) -> erlang:system_flag(multi_scheduling, block_normal), try - load_module_nosmp(Mod, Bin, Beam, Architecture) + put(hipe_patch_closures, false), + load_common(Mod, Bin, Beam, Architecture) after erlang:system_flag(multi_scheduling, unblock_normal) end. -load_module_nosmp(Mod, Bin, Beam, Architecture) -> - load_module(Mod, Bin, Beam, [], Architecture). - -load_module(Mod, Bin, Beam, OldReferencesToPatch, Architecture) -> - ?debug_msg("************ Loading Module ~w ************\n",[Mod]), - %% Loading a whole module, let the BEAM loader patch closures. - put(hipe_patch_closures, false), - load_common(Mod, Bin, Beam, OldReferencesToPatch, Architecture). %%======================================================================== @@ -175,20 +151,17 @@ load_module(Mod, Bin, Beam, OldReferencesToPatch, Architecture) -> load(Mod, Bin, Architecture) -> erlang:system_flag(multi_scheduling, block_normal), try - load_nosmp(Mod, Bin, Architecture) + ?debug_msg("********* Loading funs in module ~w *********\n",[Mod]), + %% Loading just some functions in a module; patch closures separately. + put(hipe_patch_closures, true), + load_common(Mod, Bin, [], Architecture) after erlang:system_flag(multi_scheduling, unblock_normal) end. -load_nosmp(Mod, Bin, Architecture) -> - ?debug_msg("********* Loading funs in module ~w *********\n",[Mod]), - %% Loading just some functions in a module; patch closures separately. - put(hipe_patch_closures, true), - load_common(Mod, Bin, [], [], Architecture). - %%------------------------------------------------------------------------ -load_common(Mod, Bin, Beam, OldReferencesToPatch, Architecture) -> +load_common(Mod, Bin, Beam, Architecture) -> %% Unpack the binary. [{Version, CheckSum}, ConstAlign, ConstSize, ConstMap, LabelMap, ExportMap, @@ -228,15 +201,14 @@ load_common(Mod, Bin, Beam, OldReferencesToPatch, Architecture) -> Architecture), %% Patch references to code labels in data seg. ok = patch_consts(LabelMap, ConstAddr, CodeAddress, WriteWord), + %% Find out which functions are being loaded (and where). - %% Note: FunDefs are sorted descending. - {MFAs,FunDefs} = exports(ExportMap, CodeAddress), - %% Remove references to old versions of the module. - ReferencesToPatch = get_refs_from(MFAs, []), - %% io:format("References to patch: ~w~n", [ReferencesToPatch]), - ok = remove_refs_from(MFAs), + %% Note: FunDefs are sorted descending address order. + FunDefs = exports(ExportMap, CodeAddress), + %% Patch all dynamic references in the code. %% Function calls, Atoms, Constants, System calls + ok = patch(Refs, CodeAddress, ConstMap2, FunDefs, TrampolineMap), %% Tell the system where the loaded funs are. @@ -250,7 +222,7 @@ load_common(Mod, Bin, Beam, OldReferencesToPatch, Architecture) -> lists:foreach(fun({FE, DestAddress}) -> hipe_bifs:set_native_address_in_fe(FE, DestAddress) end, erase(closures_to_patch)), - export_funs(FunDefs), + set_beam_call_traps(FunDefs), ok; BeamBinary when is_binary(BeamBinary) -> %% Find all closures in the code. @@ -259,15 +231,10 @@ load_common(Mod, Bin, Beam, OldReferencesToPatch, Architecture) -> AddressesOfClosuresToPatch = calculate_addresses(ClosurePatches, CodeAddress, FunDefs), export_funs(FunDefs), - export_funs(Mod, MD5, BeamBinary, - FunDefs, AddressesOfClosuresToPatch) + make_beam_stub(Mod, MD5, BeamBinary, FunDefs, AddressesOfClosuresToPatch, + CodeAddress, byte_size(CodeBinary)) end, - %% Redirect references to the old module to the new module's BEAM stub. - patch_to_emu_step2(OldReferencesToPatch), - %% Patch referring functions to call the new function - %% The call to export_funs/1 above updated the native addresses - %% for the targets, so passing 'FunDefs' is not needed. - redirect(ReferencesToPatch), + %% Final clean up. _ = erase(hipe_patch_closures), _ = erase(hipe_assert_code_area), @@ -371,21 +338,21 @@ trampoline_map_lookup(Primop, Map) -> is_exported :: boolean()}). exports(ExportMap, BaseAddress) -> - exports(ExportMap, BaseAddress, [], []). + exports(ExportMap, BaseAddress, []). -exports([Offset,M,F,A,IsClosure,IsExported|Rest], BaseAddress, MFAs, FunDefs) -> +exports([Offset,M,F,A,IsClosure,IsExported|Rest], BaseAddress, FunDefs) -> case IsExported andalso erlang:is_builtin(M, F, A) of true -> - exports(Rest, BaseAddress, MFAs, FunDefs); + exports(Rest, BaseAddress, FunDefs); _false -> MFA = {M,F,A}, Address = BaseAddress + Offset, FunDef = #fundef{address=Address, mfa=MFA, is_closure=IsClosure, is_exported=IsExported}, - exports(Rest, BaseAddress, [MFA|MFAs], [FunDef|FunDefs]) + exports(Rest, BaseAddress, [FunDef|FunDefs]) end; -exports([], _, MFAs, FunDefs) -> - {MFAs, FunDefs}. +exports([], _, FunDefs) -> + FunDefs. mod({M,_F,_A}) -> M. @@ -424,9 +391,9 @@ find_closure_refs([], Refs) -> %%------------------------------------------------------------------------ -export_funs([FunDef | FunDefs]) -> +set_beam_call_traps([FunDef | FunDefs]) -> #fundef{address=Address, mfa=MFA, is_closure=IsClosure, - is_exported=IsExported} = FunDef, + is_exported=_IsExported} = FunDef, ?IF_DEBUG({M,F,A} = MFA, no_debug), ?IF_DEBUG( case IsClosure of @@ -437,15 +404,32 @@ export_funs([FunDef | FunDefs]) -> ?debug_msg("LINKING: ~w:~w/~w to closure (0x~.16b)\n", [M,F,A, Address]) end, no_debug), - hipe_bifs:set_funinfo_native_address(MFA, Address, IsExported), hipe_bifs:set_native_address(MFA, Address, IsClosure), + set_beam_call_traps(FunDefs); +set_beam_call_traps([]) -> + ok. + +export_funs([FunDef | FunDefs]) -> + #fundef{address=Address, mfa=MFA, is_closure=_IsClosure, + is_exported=IsExported} = FunDef, + ?IF_DEBUG({M,F,A} = MFA, no_debug), + ?IF_DEBUG( + case _IsClosure of + false -> + ?debug_msg("LINKING: ~w:~w/~w to (0x~.16b)\n", + [M,F,A, Address]); + true -> + ?debug_msg("LINKING: ~w:~w/~w to closure (0x~.16b)\n", + [M,F,A, Address]) + end, no_debug), + hipe_bifs:set_funinfo_native_address(MFA, Address, IsExported), export_funs(FunDefs); export_funs([]) -> ok. -export_funs(Mod, MD5, Beam, FunDefs, ClosuresToPatch) -> +make_beam_stub(Mod, MD5, Beam, FunDefs, ClosuresToPatch, CodeAddress, CodeSize) -> Fs = [{F,A,Address} || #fundef{address=Address, mfa={_M,F,A}} <- FunDefs], - Mod = code:make_stub_module(Mod, Beam, {Fs,ClosuresToPatch,MD5}), + Mod = code:make_stub_module(Mod, Beam, {Fs,ClosuresToPatch,MD5,CodeAddress,CodeSize}), ok. %%======================================================================== @@ -515,8 +499,7 @@ patch_mfa_call_list([Offset|Offsets], BaseAddress, DestMFA, DestAddress, FunDefs patch_mfa_call_list([], _, _, _, _, _, _) -> ok. patch_call_insn(CallAddress, DestAddress, Trampoline) -> - %% This assertion is false when we're called from redirect/2. - %% ?ASSERT(assert_local_patch(CallAddress)), + ?ASSERT(assert_local_patch(CallAddress)), hipe_bifs:patch_call(CallAddress, DestAddress, Trampoline). %% ____________________________________________________________________ @@ -561,15 +544,15 @@ patch_atom(Address, Atom) -> patch_instr(Address, hipe_bifs:atom_to_word(Atom), atom). patch_sdesc(?STACK_DESC(SymExnRA, FSize, Arity, Live), - Address, {_ConstMap2,CodeAddress}, _FunDefs) -> + Address, {_ConstMap2,CodeAddress}, FunDefs) -> ExnRA = case SymExnRA of [] -> 0; % No catch LabelOffset -> CodeAddress + LabelOffset end, ?ASSERT(assert_local_patch(Address)), - DBG_MFA = ?IF_DEBUG(address_to_mfa_lth(Address, _FunDefs), {undefined,undefined,0}), - hipe_bifs:enter_sdesc({Address, ExnRA, FSize, Arity, Live, DBG_MFA}). + MFA = address_to_mfa_lth(Address, FunDefs), + hipe_bifs:enter_sdesc({Address, ExnRA, FSize, Arity, Live, MFA, get(hipe_patch_closures)}). %%---------------------------------------------------------------- @@ -617,6 +600,7 @@ patch_closure(DestMFA, Uniq, Index, Address, FunDefs) -> %% RemoteOrLocal ::= 'remote' | 'local' %% patch_load_mfa(CodeAddress, DestMFA, FunDefs, RemoteOrLocal) -> + ?ASSERT(assert_local_patch(CodeAddress)), DestAddress = case bif_address(DestMFA) of false -> @@ -626,7 +610,6 @@ patch_load_mfa(CodeAddress, DestMFA, FunDefs, RemoteOrLocal) -> BifAddress when is_integer(BifAddress) -> BifAddress end, - ?ASSERT(assert_local_patch(CodeAddress)), patch_instr(CodeAddress, DestAddress, 'load_mfa'). %%---------------------------------------------------------------- @@ -781,23 +764,17 @@ find_const(ConstNo, []) -> %% RemoteOrLocal ::= 'remote' | 'local'. %% -%% -%% -record(ref, {caller_mfa, address, ref_type, trampoline, remote_or_local}). -%% - add_ref(CalleeMFA, Address, FunDefs, RefType, Trampoline, RemoteOrLocal) -> CallerMFA = address_to_mfa_lth(Address, FunDefs), - %% just a sanity assertion below - true = case RemoteOrLocal of - local -> - {M1,_,_} = CalleeMFA, - {M2,_,_} = CallerMFA, - M1 =:= M2; - remote -> - true - end, - %% io:format("Adding ref ~w\n",[{CallerMFA, CalleeMFA, Address, RefType}]), - hipe_bifs:add_ref(CalleeMFA, {CallerMFA,Address,RefType,Trampoline,RemoteOrLocal}). + case RemoteOrLocal of + local -> + %% just a sanity assertion + {M,_,_} = CalleeMFA, + {M,_,_} = CallerMFA; + remote -> + hipe_bifs:add_ref(CalleeMFA, {CallerMFA,Address,RefType,Trampoline,get(hipe_patch_closures)}) + end, + ok. % For FunDefs sorted from low to high addresses address_to_mfa_lth(Address, FunDefs) -> @@ -825,81 +802,6 @@ address_to_mfa_lth(_Address, [], Prev) -> %% ?error_msg("Local adddress not found ~w\n",[Address]), %% exit({?MODULE, local_address_not_found}). -%%---------------------------------------------------------------- -%% Change callers of the given module to instead trap to BEAM. -%% load_native_code/3 calls this just before loading native code. -%% -patch_to_emu(Mod) -> - patch_to_emu_step2(patch_to_emu_step1(Mod)). - -%% Step 1 must occur before the loading of native code updates -%% references information or creates a new BEAM stub module. -patch_to_emu_step1(Mod) -> - case is_loaded(Mod) of - true -> - %% Get exported functions - MFAs = [{Mod,Fun,Arity} || {Fun,Arity} <- Mod:module_info(exports)], - %% get_refs_from/2 only finds references from compiled static - %% call sites to the module, but some native address entries - %% 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. - 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. - ReferencesToPatch = get_refs_from(MFAs, []), - ok = remove_refs_from(MFAs), - ReferencesToPatch; - false -> - %% The first time we load the module, no redirection needs to be done. - [] - end. - -%% Step 2 must occur after the new BEAM stub module is created. -patch_to_emu_step2(ReferencesToPatch) -> - redirect(ReferencesToPatch). - --spec is_loaded(Module::atom()) -> boolean(). -%% @doc Checks whether a module is loaded or not. -is_loaded(M) when is_atom(M) -> - try hipe_bifs:fun_to_address({M,module_info,0}) of - I when is_integer(I) -> true - catch _:_ -> false - end. - -%%-------------------------------------------------------------------- -%% Given a list of MFAs, tag them with their referred_from references. -%% The resulting {MFA,Refs} list is later passed to redirect/1, once -%% the MFAs have been bound to (possibly new) native-code addresses. -%% -get_refs_from(MFAs, []) -> - mark_referred_from(MFAs), - MFAs. - -mark_referred_from(MFAs) -> - lists:foreach(fun(MFA) -> hipe_bifs:mark_referred_from(MFA) end, MFAs). - -%%-------------------------------------------------------------------- -%% Given a list of MFAs with referred_from references, update their -%% callers to refer to their new native-code addresses. -%% -%% The {MFA,Refs} list must come from get_refs_from/2. -%% -redirect(MFAs) -> - lists:foreach(fun(MFA) -> hipe_bifs:redirect_referred_from(MFA) end, MFAs). - -%%-------------------------------------------------------------------- -%% Given a list of MFAs, remove all referred_from references having -%% any of them as CallerMFA. -%% -%% This is the only place using refers_to. Whenever a reference is -%% added from CallerMFA to CalleeMFA, CallerMFA is added to CalleeMFA's -%% referred_from list, and CalleeMFA is added to CallerMFA's refers_to -%% list. The refers_to list is used here to find the CalleeMFAs whose -%% referred_from lists should be updated. -%% -remove_refs_from(MFAs) -> - lists:foreach(fun(MFA) -> hipe_bifs:remove_refs_from(MFA) end, MFAs). %%-------------------------------------------------------------------- @@ -913,12 +815,13 @@ get_native_address(MFA, FunDefs, RemoteOrLocal) -> case mfa_to_address(MFA, FunDefs, RemoteOrLocal) of Adr when is_integer(Adr) -> Adr; false -> - IsRemote = case RemoteOrLocal of - remote -> true; - local -> false - end, - hipe_bifs:find_na_or_make_stub(MFA, IsRemote) + remote -> + hipe_bifs:find_na_or_make_stub(MFA); + local -> + ?error_msg("Local function ~p not found\n",[MFA]), + exit({function_not_found,MFA}) + end end. mfa_to_address(MFA, [#fundef{address=Adr, mfa=MFA, diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index c5167efa56..1be4c364d5 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -483,23 +483,25 @@ load_binary(Config) when is_list(Config) -> code:delete(code_b_test), ok. + upgrade(Config) -> DataDir = proplists:get_value(data_dir, Config), - %%T = [beam, hipe], - T = [beam], - - [upgrade_do(DataDir, Client, U1, U2, O1, O2) - || Client<-T, U1<-T, U2<-T, O1<-T, O2<-T], + T = [beam, hipe], + %%T = [beam], + %%T = [hipe], + [upgrade_do(DataDir, Client, T) || Client <- T], ok. -upgrade_do(DataDir, Client, U1, U2, O1, O2) -> +upgrade_do(DataDir, Client, T) -> compile_load(upgrade_client, DataDir, undefined, Client), - upgrade_client:run(DataDir, U1, U2, O1, O2), + [upgrade_client:run(DataDir, U1, U2, O1, O2) + || U1<-T, U2<-T, O1<-T, O2<-T], ok. compile_load(Mod, Dir, Ver, CodeType) -> + erlang:display({"{{{{{{{{{{{{{{{{Loading",Mod,Ver,CodeType}), Version = case Ver of undefined -> io:format("Compiling '~p' as ~p\n", [Mod, CodeType]), @@ -516,9 +518,15 @@ compile_load(Mod, Dir, Ver, CodeType) -> CompOpts = [binary, report] ++ Target ++ Version, Src = filename:join(Dir, atom_to_list(Mod) ++ ".erl"), + T1 = erlang:now(), {ok,Mod,Code} = compile:file(Src, CompOpts), + T2 = erlang:now(), ObjFile = filename:basename(Src,".erl") ++ ".beam", {module,Mod} = code:load_binary(Mod, ObjFile, Code), + T3 = erlang:now(), + io:format("Compile time ~p ms, Load time ~p ms\n", + [timer:now_diff(T2,T1) div 1000, timer:now_diff(T3,T2) div 1000]), + erlang:display({"}}}}}}}}}}}}}}}Loaded",Mod,Ver,CodeType}), ok. dir_req(Config) when is_list(Config) -> @@ -810,8 +818,6 @@ check_funs({'$M_EXPR','$F_EXPR',_}, {code_server,start_link,1}]) -> 0; check_funs({'$M_EXPR','$F_EXPR',_}, [{erlang,spawn_link,1},{code_server,start_link,1}]) -> 0; -check_funs({'$M_EXPR',module_info,1}, - [{hipe_unified_loader,patch_to_emu_step1,1} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',2}, [{hipe_unified_loader,write_words,3} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',2}, @@ -823,11 +829,7 @@ check_funs({'$M_EXPR','$F_EXPR',2}, {hipe_unified_loader,sort_and_write,5} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',1}, [{lists,foreach,2}, - {hipe_unified_loader,patch_consts,3} | _]) -> 0; -check_funs({'$M_EXPR','$F_EXPR',1}, - [{lists,foreach,2}, - {hipe_unified_loader,mark_referred_from,1}, - {hipe_unified_loader,get_refs_from,2}| _]) -> 0; + {hipe_unified_loader,patch_consts,4} | _]) -> 0; check_funs({'$M_EXPR',warning_msg,2}, [{code_server,finish_on_load_report,2} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',1}, diff --git a/lib/kernel/test/code_SUITE_data/upgrade_client.erl b/lib/kernel/test/code_SUITE_data/upgrade_client.erl index bb655e01d3..7ca0df7f5c 100644 --- a/lib/kernel/test/code_SUITE_data/upgrade_client.erl +++ b/lib/kernel/test/code_SUITE_data/upgrade_client.erl @@ -9,6 +9,8 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> %% Load version 1 of upgradee code_SUITE:compile_load(upgradee, Dir, 1, Upgradee1), + Tracer = start_tracing(), + ?line 1 = upgradee:exp1(), ?line 1 = upgradee:exp1exp2(), ?line 1 = upgradee:exp1loc2(), @@ -56,6 +58,16 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + Env1 = "Env1", + put(loc1_fun, upgradee:get_local_fun(Env1)), + erlang:display(sverk_break), + ?line {1,Env1} = (get(loc1_fun))(), + + put(exp1exp2_fun, upgradee:get_exp1exp2_fun()), + ?line 1 = (get(exp1exp2_fun))(), + + ?line 13 = check_tracing(Tracer), + %% %% Load version 1 of other %% @@ -78,6 +90,8 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + ?line 5 = check_tracing(Tracer), + %% %% Load version 2 of upgradee %% @@ -130,6 +144,15 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + ?line {1,Env1} = (get(loc1_fun))(), + Env2 = "Env2", + put(loc2_fun, upgradee:get_local_fun(Env2)), + ?line {2,Env2} = (get(loc2_fun))(), + + ?line 2 = (get(exp1exp2_fun))(), + + ?line 10 = check_tracing(Tracer), + %% %% Load version 2 of other %% @@ -182,17 +205,26 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + ?line {1,Env1} = (get(loc1_fun))(), + ?line {2,Env2} = (get(loc2_fun))(), + ?line 2 = (get(exp1exp2_fun))(), + + ?line 10 = check_tracing(Tracer), %% %% Upgrade proxy to version 2 %% P ! upgrade_order, - %% - io:format("Delete version 2 of 'upgradee'\n",[]), + io:format("Purge version 1 of 'upgradee'\n",[]), %% + put(loc1_fun,undefined), code:purge(upgradee), + + %% + io:format("Delete version 2 of 'upgradee'\n",[]), + %% code:delete(upgradee), ?line {'EXIT',{undef,_}} = (catch upgradee:exp2()), @@ -239,17 +271,24 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + + ?line {'EXIT',{undef,_}} = (catch (get(exp1exp2_fun))()), + ?line 14 = check_tracing(Tracer), + unlink(P), exit(P, die_please), io:format("Purge 'upgradee'\n",[]), + put(loc2_fun,undefined), code:purge(upgradee), io:format("Delete and purge 'other'\n",[]), code:purge(other), code:delete(other), code:purge(other), + + stop_tracing(Tracer), ok. proxy_call(Pid, CallType, Func) -> @@ -257,3 +296,48 @@ proxy_call(Pid, CallType, Func) -> receive {Pid, call_result, Func, Ret} -> Ret end. + + +start_tracing() -> + Self = self(), + {Tracer,_} = spawn_opt(fun() -> tracer_loop(Self) end, [link,monitor]), + ?line 1 = erlang:trace_pattern({error_handler,undefined_function,3}, + true, [global]), + ?line 1 = erlang:trace(Self, true, [call,{tracer,Tracer}]), + Tracer. + + +tracer_loop(Receiver) -> + receive + die_please -> + ok; + {do_trace_delivered, Tracee} -> + _ = erlang:trace_delivered(Tracee), + tracer_loop(Receiver); + + Msg -> + Receiver ! Msg, + tracer_loop(Receiver) + end. + +check_tracing(Tracer) -> + Tracer ! {do_trace_delivered, self()}, + check_tracing_loop(0). + +check_tracing_loop(N) -> + Self = self(), + receive + {trace, _Pid, call, {_M, _F, _Args}} = Msg -> + io:format("Trace: ~p\n",[Msg]), + check_tracing_loop(N+1); + {trace_delivered, Self, _} -> + N + end. + + +stop_tracing(Tracer) -> + erlang:trace(self(), false, [call]), + Tracer ! die_please, + receive + {'DOWN', _, process, Tracer, _} -> ok + end. diff --git a/lib/kernel/test/code_SUITE_data/upgradee.erl b/lib/kernel/test/code_SUITE_data/upgradee.erl index 62b1d95e30..8ca660c19c 100644 --- a/lib/kernel/test/code_SUITE_data/upgradee.erl +++ b/lib/kernel/test/code_SUITE_data/upgradee.erl @@ -8,6 +8,9 @@ -export([exp1/0]). % only exported in v1 -export([exp1loc2/0]). % exported in v1, local in v2 -export([exp1exp2/0]). % exported in v1 and v2 +-export([get_local_fun/1]). +-export([get_exp1exp2_fun/0]). +-export([exp1exp2_fun/0]). exp1() -> ?VERSION. loc1() -> ?VERSION. @@ -20,6 +23,9 @@ loc1() -> ?VERSION. -export([exp2/0]). -export([loc1exp2/0]). -export([exp1exp2/0]). +-export([get_local_fun/1]). +-export([get_exp1exp2_fun/0]). +-export([exp1exp2_fun/0]). exp2() -> ?VERSION. loc2() -> ?VERSION. @@ -31,6 +37,12 @@ exp1loc2() -> ?VERSION. loc1exp2() -> ?VERSION. loc1loc2() -> ?VERSION. +get_local_fun(Env) -> fun() -> {?VERSION,Env} end. +get_exp1exp2_fun() -> fun ?MODULE:exp1exp2_fun/0. + +exp1exp2_fun() -> + ?VERSION. + dispatch_loop() -> receive upgrade_order -> -- cgit v1.2.3 From 4d96d297044274c46deda1adfc567297449a9ba9 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 15 Sep 2016 19:23:27 +0200 Subject: erts: Remove unused hipe_bifs:code_size and hipe_bifs:update_code_size --- lib/kernel/src/hipe_unified_loader.erl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 75a5995695..b3acd9ea74 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -195,7 +195,7 @@ load_common(Mod, Bin, Beam, Architecture) -> CalleeMFAs = find_callee_mfas(Refs, Architecture), %% Write the code to memory. {CodeAddress,Trampolines} = - enter_code(CodeSize, CodeBinary, CalleeMFAs, Mod, Beam), + enter_code(CodeSize, CodeBinary, CalleeMFAs), %% Construct CalleeMFA-to-trampoline mapping. TrampolineMap = mk_trampoline_map(CalleeMFAs, Trampolines, Architecture), @@ -863,9 +863,8 @@ assert_local_patch(Address) when is_integer(Address) -> %% Beam: nil() | binary() (used as a flag) -enter_code(CodeSize, CodeBinary, CalleeMFAs, Mod, Beam) -> +enter_code(CodeSize, CodeBinary, CalleeMFAs) -> true = byte_size(CodeBinary) =:= CodeSize, - hipe_bifs:update_code_size(Mod, Beam, CodeSize), {CodeAddress,Trampolines} = hipe_bifs:enter_code(CodeBinary, CalleeMFAs), ?init_assert_patch(CodeAddress, byte_size(CodeBinary)), {CodeAddress,Trampolines}. -- cgit v1.2.3 From 81cf5bc05e502809398116eaa0b78deb9336d68b Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 10 Oct 2016 16:39:31 +0200 Subject: kernel: Add test pdict_SUITE:literals to get some coverage in beam_load.c:hash_internal_genop_arg(). --- lib/kernel/test/pdict_SUITE.erl | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/test/pdict_SUITE.erl b/lib/kernel/test/pdict_SUITE.erl index 638d99176e..d105952df9 100644 --- a/lib/kernel/test/pdict_SUITE.erl +++ b/lib/kernel/test/pdict_SUITE.erl @@ -32,10 +32,13 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, mixed/1, + literals/1, simple/1, complicated/1, heavy/1, simple_all_keys/1, info/1]). -export([init_per_testcase/2, end_per_testcase/2]). -export([other_process/2]). +-export([put_do/2, get_do/1, erase_do/1]). + init_per_testcase(_Case, Config) -> Config. @@ -48,6 +51,7 @@ suite() -> all() -> [simple, complicated, heavy, simple_all_keys, info, + literals, mixed]. groups() -> @@ -418,3 +422,59 @@ do_mixed([GoalN | _]=Goals, CurrN, Array0, C, Rand0) -> Array2 = array:resize(CurrN-1, Array1), do_mixed(Goals, CurrN-1, Array2, C+1, Rand2) end. + +%% Test hash precalculation of literal keys +literals(_Config) -> + %% Put literal -> get variable + put(1742, "1742"), + "1742" = ?MODULE:get_do(1742), + "1742" = ?MODULE:erase_do(1742), + + put(-1742, "-1742"), + "-1742" = ?MODULE:get_do(-1742), + "-1742" = ?MODULE:erase_do(-1742), + + put([], "NIL"), + "NIL" = ?MODULE:get_do([]), + "NIL" = ?MODULE:erase_do([]), + + put(<<"binary">>, "binary"), + "binary" = ?MODULE:get_do(<<"binary">>), + "binary" = ?MODULE:erase_do(<<"binary">>), + + BigBin = <<"A large binary with a lot of bytes to make it go off heap as shared and reference counted">>, + put(BigBin, "bigbin"), + "bigbin" = ?MODULE:get_do(BigBin), + "bigbin" = ?MODULE:erase_do(BigBin), + + %% Put variable -> get literal + ?MODULE:put_do(4217, "4217"), + "4217" = get(4217), + "4217" = erase(4217), + + ?MODULE:put_do(-4217, "-4217"), + "-4217" = get(-4217), + "-4217" = erase(-4217), + + ?MODULE:put_do([], "NIL"), + "NIL" = get([]), + "NIL" = erase([]), + + ?MODULE:put_do(<<"bytes">>, "bytes"), + "bytes" = get(<<"bytes">>), + "bytes" = erase(<<"bytes">>), + + ?MODULE:put_do(BigBin, "BigBin"), + "BigBin" = get(BigBin), + "BigBin" = erase(BigBin), + + ok. + +put_do(K, V) -> + put(K, V). + +get_do(K) -> + get(K). + +erase_do(K) -> + erase(K). -- cgit v1.2.3 From 39072836944d00c288beebfd98b14593f9609006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Thu, 19 May 2016 17:38:54 +0200 Subject: Add a loader state for HiPE code loading Just like the BEAM loader state (as returned by erlang:prepare_loading/2), the HiPE loader state is contained in a magic binary. Eventually, we will separate HiPE loading into a prepare and a finalise phase, like the BEAM loader, where the prepare phase will be implemented by hipe_unified_loader and the finalise phase be implemented in C by hipe_load.c and beam_load.c, making prepare side-effect free and finalise atomic. The finalise phase will be exposed through the erlang:finish_loading/1 API, just like the BEAM loader, as this will allow HiPE and BEAM modules to be mixed in the same atomic "commit". The usage of a loader state makes it easier to keep track of all resources allocated during loading, and will not only make it easy to prevent leaks when hipe_unified_loader crashes, but also paves the way for proper, leak-free, unloading of HiPE modules. --- lib/kernel/src/hipe_unified_loader.erl | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index b3acd9ea74..6245646263 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -188,14 +188,16 @@ load_common(Mod, Bin, Beam, Architecture) -> put(closures_to_patch, []), WordSize = word_size(Architecture), WriteWord = write_word_fun(WordSize), + LoaderState = hipe_bifs:alloc_loader_state(Mod), %% Create data segment {ConstAddr,ConstMap2} = - create_data_segment(ConstAlign, ConstSize, ConstMap, WriteWord), + create_data_segment(ConstAlign, ConstSize, ConstMap, WriteWord, + LoaderState), %% Find callees for which we may need trampolines. CalleeMFAs = find_callee_mfas(Refs, Architecture), %% Write the code to memory. {CodeAddress,Trampolines} = - enter_code(CodeSize, CodeBinary, CalleeMFAs), + enter_code(CodeSize, CodeBinary, CalleeMFAs, LoaderState), %% Construct CalleeMFA-to-trampoline mapping. TrampolineMap = mk_trampoline_map(CalleeMFAs, Trampolines, Architecture), @@ -231,8 +233,8 @@ load_common(Mod, Bin, Beam, Architecture) -> AddressesOfClosuresToPatch = calculate_addresses(ClosurePatches, CodeAddress, FunDefs), export_funs(FunDefs), - make_beam_stub(Mod, MD5, BeamBinary, FunDefs, AddressesOfClosuresToPatch, - CodeAddress, byte_size(CodeBinary)) + make_beam_stub(Mod, LoaderState, MD5, BeamBinary, FunDefs, + AddressesOfClosuresToPatch) end, %% Final clean up. @@ -427,9 +429,9 @@ export_funs([FunDef | FunDefs]) -> export_funs([]) -> ok. -make_beam_stub(Mod, MD5, Beam, FunDefs, ClosuresToPatch, CodeAddress, CodeSize) -> +make_beam_stub(Mod, LoaderState, MD5, Beam, FunDefs, ClosuresToPatch) -> Fs = [{F,A,Address} || #fundef{address=Address, mfa={_M,F,A}} <- FunDefs], - Mod = code:make_stub_module(Mod, Beam, {Fs,ClosuresToPatch,MD5,CodeAddress,CodeSize}), + Mod = code:make_stub_module(LoaderState, Beam, {Fs,ClosuresToPatch,MD5}), ok. %%======================================================================== @@ -685,9 +687,9 @@ bif_address(Name) when is_atom(Name) -> %% memory, and produces a ConstMap2 mapping each constant's ConstNo to %% its runtime address, tagged if the constant is a term. %% -create_data_segment(DataAlign, DataSize, DataList, WriteWord) -> +create_data_segment(DataAlign, DataSize, DataList, WriteWord, LoaderState) -> %%io:format("create_data_segment: \nDataAlign: ~p\nDataSize: ~p\nDataList: ~p\n",[DataAlign,DataSize,DataList]), - DataAddress = hipe_bifs:alloc_data(DataAlign, DataSize), + DataAddress = hipe_bifs:alloc_data(DataAlign, DataSize, LoaderState), enter_data(DataList, [], DataAddress, DataSize, WriteWord). enter_data(List, ConstMap2, DataAddress, DataSize, WriteWord) -> @@ -863,9 +865,10 @@ assert_local_patch(Address) when is_integer(Address) -> %% Beam: nil() | binary() (used as a flag) -enter_code(CodeSize, CodeBinary, CalleeMFAs) -> +enter_code(CodeSize, CodeBinary, CalleeMFAs, LoaderState) -> true = byte_size(CodeBinary) =:= CodeSize, - {CodeAddress,Trampolines} = hipe_bifs:enter_code(CodeBinary, CalleeMFAs), + {CodeAddress,Trampolines} = hipe_bifs:enter_code(CodeBinary, CalleeMFAs, + LoaderState), ?init_assert_patch(CodeAddress, byte_size(CodeBinary)), {CodeAddress,Trampolines}. -- cgit v1.2.3 From 966098ceb9dd9d18e9bcd37cd06b96045903e320 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 20 Sep 2016 16:16:50 +0200 Subject: erts: Move new hipe ref and sdesc lists to loader state --- lib/kernel/src/hipe_unified_loader.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 6245646263..cde2eb059a 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -189,6 +189,7 @@ load_common(Mod, Bin, Beam, Architecture) -> WordSize = word_size(Architecture), WriteWord = write_word_fun(WordSize), LoaderState = hipe_bifs:alloc_loader_state(Mod), + put(hipe_loader_state, LoaderState), %% Create data segment {ConstAddr,ConstMap2} = create_data_segment(ConstAlign, ConstSize, ConstMap, WriteWord, @@ -238,6 +239,7 @@ load_common(Mod, Bin, Beam, Architecture) -> end, %% Final clean up. + _ = erase(hipe_loader_state), _ = erase(hipe_patch_closures), _ = erase(hipe_assert_code_area), ?debug_msg("****************Loader Finished****************\n", []), @@ -554,7 +556,8 @@ patch_sdesc(?STACK_DESC(SymExnRA, FSize, Arity, Live), end, ?ASSERT(assert_local_patch(Address)), MFA = address_to_mfa_lth(Address, FunDefs), - hipe_bifs:enter_sdesc({Address, ExnRA, FSize, Arity, Live, MFA, get(hipe_patch_closures)}). + hipe_bifs:enter_sdesc({Address, ExnRA, FSize, Arity, Live, MFA, get(hipe_patch_closures)}, + get(hipe_loader_state)). %%---------------------------------------------------------------- @@ -774,7 +777,9 @@ add_ref(CalleeMFA, Address, FunDefs, RefType, Trampoline, RemoteOrLocal) -> {M,_,_} = CalleeMFA, {M,_,_} = CallerMFA; remote -> - hipe_bifs:add_ref(CalleeMFA, {CallerMFA,Address,RefType,Trampoline,get(hipe_patch_closures)}) + hipe_bifs:add_ref(CalleeMFA, {CallerMFA,Address,RefType,Trampoline, + get(hipe_patch_closures), + get(hipe_loader_state)}) end, ok. -- cgit v1.2.3 From e77d7a8417368617c4c228af9556a7f6a8f3e84c Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 28 Sep 2016 20:55:40 +0200 Subject: erts: Fix early hipe patch loading by introducing hipe_bifs:commit_patch_load/1 that creates the HipeModule. --- lib/kernel/src/hipe_unified_loader.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index cde2eb059a..03116758de 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -225,6 +225,7 @@ load_common(Mod, Bin, Beam, Architecture) -> lists:foreach(fun({FE, DestAddress}) -> hipe_bifs:set_native_address_in_fe(FE, DestAddress) end, erase(closures_to_patch)), + ok = hipe_bifs:commit_patch_load(LoaderState), set_beam_call_traps(FunDefs), ok; BeamBinary when is_binary(BeamBinary) -> @@ -556,7 +557,7 @@ patch_sdesc(?STACK_DESC(SymExnRA, FSize, Arity, Live), end, ?ASSERT(assert_local_patch(Address)), MFA = address_to_mfa_lth(Address, FunDefs), - hipe_bifs:enter_sdesc({Address, ExnRA, FSize, Arity, Live, MFA, get(hipe_patch_closures)}, + hipe_bifs:enter_sdesc({Address, ExnRA, FSize, Arity, Live, MFA}, get(hipe_loader_state)). @@ -778,7 +779,6 @@ add_ref(CalleeMFA, Address, FunDefs, RefType, Trampoline, RemoteOrLocal) -> {M,_,_} = CallerMFA; remote -> hipe_bifs:add_ref(CalleeMFA, {CallerMFA,Address,RefType,Trampoline, - get(hipe_patch_closures), get(hipe_loader_state)}) end, ok. -- cgit v1.2.3 From cb987678ff56142029758e0e84fa97fa90003b4a Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 30 Sep 2016 18:05:25 +0200 Subject: kernel: Fix strange 'ok' return value from code_server when failing to load native code. --- lib/kernel/src/code_server.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 90ecb22074..418b0c50e1 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1136,7 +1136,7 @@ try_load_module_2(File, Mod, Bin, From, Architecture, try_load_module_3(File, Mod, Bin, From, Architecture, St); Error -> error_msg("Native loading of ~ts failed: ~p\n", [File,Error]), - {reply,ok,St} + {reply,{error,Error},St} end. try_load_module_3(File, Mod, Bin, From, _Architecture, St0) -> -- cgit v1.2.3 From ee0531308b0cc57f0312e1d0676635969d8a8029 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 7 Oct 2016 16:55:08 +0200 Subject: kernel: Fix code_SUITE:upgrade for non-hipe --- lib/kernel/test/code_SUITE.erl | 7 ++++--- lib/kernel/test/code_SUITE_data/upgrade_client.erl | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 1be4c364d5..96f8ff2c5f 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -487,9 +487,10 @@ load_binary(Config) when is_list(Config) -> upgrade(Config) -> DataDir = proplists:get_value(data_dir, Config), - T = [beam, hipe], - %%T = [beam], - %%T = [hipe], + T = case erlang:system_info(hipe_architecture) of + undefined -> [beam]; + _ -> [beam,hipe] + end, [upgrade_do(DataDir, Client, T) || Client <- T], ok. diff --git a/lib/kernel/test/code_SUITE_data/upgrade_client.erl b/lib/kernel/test/code_SUITE_data/upgrade_client.erl index 7ca0df7f5c..98d36f6014 100644 --- a/lib/kernel/test/code_SUITE_data/upgrade_client.erl +++ b/lib/kernel/test/code_SUITE_data/upgrade_client.erl @@ -60,7 +60,6 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> Env1 = "Env1", put(loc1_fun, upgradee:get_local_fun(Env1)), - erlang:display(sverk_break), ?line {1,Env1} = (get(loc1_fun))(), put(exp1exp2_fun, upgradee:get_exp1exp2_fun()), -- cgit v1.2.3 From 2b2de6173d4ba5506ae9b1692a19e01cf0d299c8 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 17 Oct 2016 11:32:38 +0200 Subject: kernel,hipe: Fix dialyzer warnings --- lib/kernel/src/code.erl | 4 ++-- lib/kernel/src/hipe_unified_loader.erl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 8d0a2fbf66..622b27080c 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -116,8 +116,8 @@ get_chunk(_, _) -> is_module_native(_) -> erlang:nif_error(undef). --spec make_stub_module(Module, Beam, Info) -> Module when - Module :: module(), +-spec make_stub_module(LoaderState, Beam, Info) -> module() when + LoaderState :: binary(), Beam :: binary(), Info :: {list(), list(), binary()}. diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 03116758de..a7e30a048f 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -772,7 +772,7 @@ find_const(ConstNo, []) -> add_ref(CalleeMFA, Address, FunDefs, RefType, Trampoline, RemoteOrLocal) -> CallerMFA = address_to_mfa_lth(Address, FunDefs), - case RemoteOrLocal of + _ = case RemoteOrLocal of local -> %% just a sanity assertion {M,_,_} = CalleeMFA, -- cgit v1.2.3 From 8fcdf80aba9115bc6f3b345b83e53be1bbf69778 Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Mon, 17 Oct 2016 11:05:43 +0100 Subject: Clarify permission bits in file.xml In commit 3d70cee4034e, this text was changed to suggest that a list of Unix-specific permission bits would follow, but no such list was added. Let's revert back to the previous wording, so people won't look for a list that isn't there. --- lib/kernel/doc/src/file.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 09497482cf..b674b3ca93 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -1477,8 +1477,8 @@ f.txt: {person, "kalle", 25}. 16#400

set group id on execution

-

On Unix platforms, the following bits - can also be set:

+

On Unix platforms, other bits than those listed above + may be set.

links = integer() >= 0 @@ -2042,8 +2042,8 @@ f.txt: {person, "kalle", 25}. 16#400

Set group id on execution

-

On Unix platforms, the following bits - can also be set.

+

On Unix platforms, other bits than those listed above + may be set.

uid = integer() >= 0 -- cgit v1.2.3 From 0c7e4330ddced978934dd63520795554b29244a2 Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Tue, 18 Oct 2016 13:08:38 +0200 Subject: Code cleanup to remove confusing assertion The code of add_ref/6 contained an assertion that somehow appeared twice. Also, a recent commit (2b2de61) suppressed an unmatched return warning in a non-optimal way. By changing the return type of hipe_bifs:add_ref/2 to be 'ok' instead of [] the code can be cleaned up and simplified. While at it, fixed the wrong indentation of some nearby code. --- lib/kernel/src/hipe_unified_loader.erl | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index a7e30a048f..ce7408a3cc 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -772,27 +772,26 @@ find_const(ConstNo, []) -> add_ref(CalleeMFA, Address, FunDefs, RefType, Trampoline, RemoteOrLocal) -> CallerMFA = address_to_mfa_lth(Address, FunDefs), - _ = case RemoteOrLocal of + case RemoteOrLocal of local -> %% just a sanity assertion - {M,_,_} = CalleeMFA, - {M,_,_} = CallerMFA; + {_M,_,_} = CalleeMFA, + ok; remote -> hipe_bifs:add_ref(CalleeMFA, {CallerMFA,Address,RefType,Trampoline, get(hipe_loader_state)}) - end, - ok. + end. -% For FunDefs sorted from low to high addresses +%% For FunDefs sorted from low to high addresses address_to_mfa_lth(Address, FunDefs) -> - case address_to_mfa_lth(Address, FunDefs, false) of - false -> - ?error_msg("Local adddress not found ~w\n",[Address]), - exit({?MODULE, local_address_not_found}); - MFA -> - MFA - end. - + case address_to_mfa_lth(Address, FunDefs, false) of + false -> + ?error_msg("Local adddress not found ~w\n",[Address]), + exit({?MODULE, local_address_not_found}); + MFA -> + MFA + end. + address_to_mfa_lth(Address, [#fundef{address=Adr, mfa=MFA}|Rest], Prev) -> if Address < Adr -> Prev; @@ -802,7 +801,7 @@ address_to_mfa_lth(Address, [#fundef{address=Adr, mfa=MFA}|Rest], Prev) -> address_to_mfa_lth(_Address, [], Prev) -> Prev. -% For FunDefs sorted from high to low addresses +%% For FunDefs sorted from high to low addresses %% address_to_mfa_htl(Address, [#fundef{address=Adr, mfa=MFA}|_Rest]) when Address >= Adr -> MFA; %% address_to_mfa_htl(Address, [_ | Rest]) -> address_to_mfa_htl(Address, Rest); %% address_to_mfa_htl(Address, []) -> @@ -868,8 +867,6 @@ assert_local_patch(Address) when is_integer(Address) -> %% ____________________________________________________________________ %% -%% Beam: nil() | binary() (used as a flag) - enter_code(CodeSize, CodeBinary, CalleeMFAs, LoaderState) -> true = byte_size(CodeBinary) =:= CodeSize, {CodeAddress,Trampolines} = hipe_bifs:enter_code(CodeBinary, CalleeMFAs, -- cgit v1.2.3 From a79e2569f5a6d6a622bd78b04326a6ad976c0a4c Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Tue, 18 Oct 2016 14:03:41 +0200 Subject: Restore the erroneously taken out assertion --- lib/kernel/src/hipe_unified_loader.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index ce7408a3cc..04ec1479cb 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -774,8 +774,9 @@ add_ref(CalleeMFA, Address, FunDefs, RefType, Trampoline, RemoteOrLocal) -> CallerMFA = address_to_mfa_lth(Address, FunDefs), case RemoteOrLocal of local -> - %% just a sanity assertion - {_M,_,_} = CalleeMFA, + %% assert that the callee and caller are from the same module + {M,_,_} = CalleeMFA, + {M,_,_} = CallerMFA, ok; remote -> hipe_bifs:add_ref(CalleeMFA, {CallerMFA,Address,RefType,Trampoline, -- cgit v1.2.3 From c8f3ec52716064e0835e2e84329b2257be22acb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Tue, 18 Oct 2016 15:54:40 +0200 Subject: hipe_llvm: Use different symbols for remote calls --- lib/kernel/test/code_SUITE.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 96f8ff2c5f..237f1c46b6 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -489,7 +489,11 @@ upgrade(Config) -> T = case erlang:system_info(hipe_architecture) of undefined -> [beam]; - _ -> [beam,hipe] + _ -> + case hipe:llvm_support_available() of + false -> [beam,hipe]; + true -> [beam,hipe,hipe_llvm] + end end, [upgrade_do(DataDir, Client, T) || Client <- T], @@ -514,7 +518,8 @@ compile_load(Mod, Dir, Ver, CodeType) -> end, Target = case CodeType of beam -> []; - hipe -> [native] + hipe -> [native]; + hipe_llvm -> [native,{hipe,to_llvm}] end, CompOpts = [binary, report] ++ Target ++ Version, -- cgit v1.2.3 From 72026389d89a2e9530d3594df742588bace7079a Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 18 Oct 2016 17:59:06 +0200 Subject: kernel: Reduce test logging from code_SUITE:upgrade --- lib/kernel/test/code_SUITE.erl | 4 ++-- lib/kernel/test/code_SUITE_data/upgrade_client.erl | 28 +++++++++++++--------- 2 files changed, 19 insertions(+), 13 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 237f1c46b6..8d517d144e 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -506,7 +506,7 @@ upgrade_do(DataDir, Client, T) -> ok. compile_load(Mod, Dir, Ver, CodeType) -> - erlang:display({"{{{{{{{{{{{{{{{{Loading",Mod,Ver,CodeType}), + %%erlang:display({"{{{{{{{{{{{{{{{{Loading",Mod,Ver,CodeType}), Version = case Ver of undefined -> io:format("Compiling '~p' as ~p\n", [Mod, CodeType]), @@ -532,7 +532,7 @@ compile_load(Mod, Dir, Ver, CodeType) -> T3 = erlang:now(), io:format("Compile time ~p ms, Load time ~p ms\n", [timer:now_diff(T2,T1) div 1000, timer:now_diff(T3,T2) div 1000]), - erlang:display({"}}}}}}}}}}}}}}}Loaded",Mod,Ver,CodeType}), + %%erlang:display({"}}}}}}}}}}}}}}}Loaded",Mod,Ver,CodeType}), ok. dir_req(Config) when is_list(Config) -> diff --git a/lib/kernel/test/code_SUITE_data/upgrade_client.erl b/lib/kernel/test/code_SUITE_data/upgrade_client.erl index 98d36f6014..faa18e1410 100644 --- a/lib/kernel/test/code_SUITE_data/upgrade_client.erl +++ b/lib/kernel/test/code_SUITE_data/upgrade_client.erl @@ -65,7 +65,7 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> put(exp1exp2_fun, upgradee:get_exp1exp2_fun()), ?line 1 = (get(exp1exp2_fun))(), - ?line 13 = check_tracing(Tracer), + ok = check_tracing(Tracer, 13), %% %% Load version 1 of other @@ -89,7 +89,7 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), - ?line 5 = check_tracing(Tracer), + ok = check_tracing(Tracer, 5), %% %% Load version 2 of upgradee @@ -150,7 +150,7 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line 2 = (get(exp1exp2_fun))(), - ?line 10 = check_tracing(Tracer), + ok = check_tracing(Tracer, 10), %% %% Load version 2 of other @@ -208,7 +208,7 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {2,Env2} = (get(loc2_fun))(), ?line 2 = (get(exp1exp2_fun))(), - ?line 10 = check_tracing(Tracer), + ok = check_tracing(Tracer, 10), %% %% Upgrade proxy to version 2 @@ -273,7 +273,7 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = (catch (get(exp1exp2_fun))()), - ?line 14 = check_tracing(Tracer), + ok = check_tracing(Tracer, 14), unlink(P), exit(P, die_please), @@ -319,18 +319,24 @@ tracer_loop(Receiver) -> tracer_loop(Receiver) end. -check_tracing(Tracer) -> +check_tracing(Tracer, Expected) -> Tracer ! {do_trace_delivered, self()}, - check_tracing_loop(0). + case check_tracing_loop(0,[]) of + {Expected,_} -> + ok; + {Got, MsgList} -> + io:format("Expected ~p trace msg, got ~p:\n~p\n", + [Expected, Got, lists:reverse(MsgList)]), + "Trace msg mismatch" + end. -check_tracing_loop(N) -> +check_tracing_loop(N, MsgList) -> Self = self(), receive {trace, _Pid, call, {_M, _F, _Args}} = Msg -> - io:format("Trace: ~p\n",[Msg]), - check_tracing_loop(N+1); + check_tracing_loop(N+1, [Msg | MsgList]); {trace_delivered, Self, _} -> - N + {N, MsgList} end. -- cgit v1.2.3 From 7a48251e07d662261de68798de6a91ab8ad5ffe7 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 20 Oct 2016 15:16:47 +0200 Subject: kernel: Test hipe and hipe_llvm separate in code_SUITE:upgrade. Combining both takes time. --- lib/kernel/test/code_SUITE.erl | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 8d517d144e..342f9ad5c3 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -487,16 +487,21 @@ load_binary(Config) when is_list(Config) -> upgrade(Config) -> DataDir = proplists:get_value(data_dir, Config), - T = case erlang:system_info(hipe_architecture) of - undefined -> [beam]; - _ -> - case hipe:llvm_support_available() of - false -> [beam,hipe]; - true -> [beam,hipe,hipe_llvm] - end - end, - - [upgrade_do(DataDir, Client, T) || Client <- T], + case erlang:system_info(hipe_architecture) of + undefined -> + upgrade_do(DataDir, beam, [beam]); + + _ -> + T = [beam, hipe], + [upgrade_do(DataDir, Client, T) || Client <- T], + + case hipe:llvm_support_available() of + false -> ok; + true -> + T2 = [beam, hipe_llvm], + [upgrade_do(DataDir, Client, T2) || Client <- T2] + end + end, ok. upgrade_do(DataDir, Client, T) -> -- cgit v1.2.3 From f96c3f2e8c02ec3e50708fed6e58227bd234318e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 20 Oct 2016 15:17:37 +0200 Subject: kernel: Fix hipe compiler option to_llvm --- lib/kernel/test/code_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 342f9ad5c3..29b3f7caaf 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -524,7 +524,7 @@ compile_load(Mod, Dir, Ver, CodeType) -> Target = case CodeType of beam -> []; hipe -> [native]; - hipe_llvm -> [native,{hipe,to_llvm}] + hipe_llvm -> [native,{hipe,[to_llvm]}] end, CompOpts = [binary, report] ++ Target ++ Version, -- cgit v1.2.3 From 70526ab4e8b5a0d84c5cfd27557a481707420ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20G=C3=B6m=C3=B6ri?= Date: Thu, 20 Oct 2016 01:05:45 +0200 Subject: controlling_process can return {error, badarg} For gen_tcp, gen_udp and gen_sctp controlling_process/2 can return badarg if erlang:port_connect/2 fails with badarg. This can easily happen if the new owner is not alive but in some race condition also when the socket is closed right before port_connect/2 (and after the previous socket function) This commit documents this behaviour. --- lib/kernel/doc/src/gen_tcp.xml | 6 +++++- lib/kernel/doc/src/gen_udp.xml | 6 +++++- lib/kernel/src/gen_sctp.erl | 2 +- lib/kernel/src/gen_tcp.erl | 2 +- lib/kernel/src/gen_udp.erl | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index 08454b9832..e97db20062 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -231,7 +231,11 @@ do_recv(Sock, Bs) -> Socket. The controlling process is the process that receives messages from the socket. If called by any other process than the current controlling process, - {error, not_owner} is returned.

+ {error, not_owner} is returned. If the process identified + by Pid is not an existing local pid, + {error, badarg} is returned. {error, badarg} may also + be returned in some cases when Socket is closed + during the execution of this function.

If the socket is set in active mode, this function will transfer any messages in the mailbox of the caller to the new controlling process. diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml index 3f88a0272d..f79566ef71 100644 --- a/lib/kernel/doc/src/gen_udp.xml +++ b/lib/kernel/doc/src/gen_udp.xml @@ -68,7 +68,11 @@ Socket. The controlling process is the process that receives messages from the socket. If called by any other process than the current controlling process, - {error, not_owner} is returned.

+ {error, not_owner} is returned. If the process identified + by Pid is not an existing local pid, + {error, badarg} is returned. {error, badarg} may also + be returned in some cases when Socket is closed + during the execution of this function.

diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl index b133e6fed4..a6aa0edd15 100644 --- a/lib/kernel/src/gen_sctp.erl +++ b/lib/kernel/src/gen_sctp.erl @@ -439,7 +439,7 @@ error_string(X) -> -spec controlling_process(Socket, Pid) -> ok | {error, Reason} when Socket :: sctp_socket(), Pid :: pid(), - Reason :: closed | not_owner | inet:posix(). + Reason :: closed | not_owner | badarg | inet:posix(). controlling_process(S, Pid) when is_port(S), is_pid(Pid) -> inet:udp_controlling_process(S, Pid); diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl index 1a21541b7c..ac61dbc792 100644 --- a/lib/kernel/src/gen_tcp.erl +++ b/lib/kernel/src/gen_tcp.erl @@ -320,7 +320,7 @@ unrecv(S, Data) when is_port(S) -> -spec controlling_process(Socket, Pid) -> ok | {error, Reason} when Socket :: socket(), Pid :: pid(), - Reason :: closed | not_owner | inet:posix(). + Reason :: closed | not_owner | badarg | inet:posix(). controlling_process(S, NewOwner) -> case inet_db:lookup_socket(S) of diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl index 98d2f0bcfb..3121544719 100644 --- a/lib/kernel/src/gen_udp.erl +++ b/lib/kernel/src/gen_udp.erl @@ -195,7 +195,7 @@ connect(S, Address, Port) when is_port(S) -> -spec controlling_process(Socket, Pid) -> ok | {error, Reason} when Socket :: socket(), Pid :: pid(), - Reason :: closed | not_owner | inet:posix(). + Reason :: closed | not_owner | badarg | inet:posix(). controlling_process(S, NewOwner) -> inet:udp_controlling_process(S, NewOwner). -- cgit v1.2.3 From 1c3dc406736e13a38d6a70fc82027d3f3f846b13 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 31 Oct 2016 17:20:54 +0100 Subject: kernel: Add lost dependency to erts-8.1 In OTP-19.1 (c70ca686fe269db6079a2ca1c7e09cdfc0cfa903) erts_code_purger:finish_after_on_load/2 was added and called by code_server.erl. --- lib/kernel/src/kernel.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 56d1699656..d184223524 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -118,6 +118,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-8.0", "stdlib-3.0", "sasl-3.0"]} + {runtime_dependencies, ["erts-8.1", "stdlib-3.0", "sasl-3.0"]} ] }. -- cgit v1.2.3 From 3097a53cc6bc3728f72c3873713f42d9c591ba0c Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 15 Nov 2016 10:40:30 +0100 Subject: Minor documentation cleanup --- lib/kernel/doc/src/disk_log.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index 0b6ee1e6a5..3c9bc7f6e8 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -43,7 +43,7 @@ halt logs

Appends items to a single file, which size can - be limited by the disk log module.

+ be limited by the disk_log module.

wrap logs

Uses a sequence of wrap log files of limited size. As a wrap log file is filled up, further items are logged on to the next @@ -62,8 +62,8 @@ An item logged to an internally formatted log must not occupy more than 4 GB of disk space (the size must fit in 4 bytes).

external format -

Leaves it up to the user to read the logged deep byte lists. - The disk log module cannot repair externally formatted logs.

+

Leaves it up to the user to read and interpret the logged data. + The disk_log module cannot repair externally formatted logs.

For each open disk log, one process handles requests -- cgit v1.2.3 From a59be645027272e96acdddf5cf9710aeda1e11de Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 15 Nov 2016 11:53:07 +0100 Subject: Rename internal function for clarity --- lib/kernel/src/disk_log.erl | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 9b44021872..515caf98a7 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -133,7 +133,7 @@ log(Log, Term) -> Log :: log(), Bytes :: bytes(). blog(Log, Bytes) -> - req(Log, {blog, check_bytes(Bytes)}). + req(Log, {blog, ensure_binary(Bytes)}). -spec log_terms(Log, TermList) -> ok | {error, Resaon :: log_error_rsn()} when Log :: log(), @@ -147,7 +147,7 @@ log_terms(Log, Terms) -> Log :: log(), BytesList :: [bytes()]. blog_terms(Log, Bytess) -> - Bs = check_bytes_list(Bytess, Bytess), + Bs = ensure_binary_list(Bytess), req(Log, {blog, Bs}). -type notify_ret() :: 'ok' | {'error', 'no_such_log'}. @@ -169,13 +169,13 @@ alog_terms(Log, Terms) -> Log :: log(), Bytes :: bytes(). balog(Log, Bytes) -> - notify(Log, {balog, check_bytes(Bytes)}). + notify(Log, {balog, ensure_binary(Bytes)}). -spec balog_terms(Log, ByteList) -> notify_ret() when Log :: log(), ByteList :: [bytes()]. balog_terms(Log, Bytess) -> - Bs = check_bytes_list(Bytess, Bytess), + Bs = ensure_binary_list(Bytess), notify(Log, {balog, Bs}). -type close_error_rsn() ::'no_such_log' | 'nonode' @@ -221,7 +221,7 @@ truncate(Log, Head) -> Log :: log(), BHead :: bytes(). btruncate(Log, Head) -> - req(Log, {truncate, {ok, check_bytes(Head)}, btruncate, 2}). + req(Log, {truncate, {ok, ensure_binary(Head)}, btruncate, 2}). -type reopen_error_rsn() :: no_such_log | nonode @@ -250,7 +250,7 @@ reopen(Log, NewFile, NewHead) -> File :: file:filename(), BHead :: bytes(). breopen(Log, NewFile, NewHead) -> - req(Log, {reopen, NewFile, {ok, check_bytes(NewHead)}, breopen, 3}). + req(Log, {reopen, NewFile, {ok, ensure_binary(NewHead)}, breopen, 3}). -type inc_wrap_error_rsn() :: 'no_such_log' | 'nonode' | {'read_only_mode', log()} @@ -1326,7 +1326,7 @@ do_open(A) -> end. mk_head({head, Term}, internal) -> {ok, term_to_binary(Term)}; -mk_head({head, Bytes}, external) -> {ok, check_bytes(Bytes)}; +mk_head({head, Bytes}, external) -> {ok, ensure_binary(Bytes)}; mk_head(H, _) -> H. terms2bins([T | Ts]) -> @@ -1334,23 +1334,24 @@ terms2bins([T | Ts]) -> terms2bins([]) -> []. -check_bytes_list([B | Bs], Bs0) when is_binary(B) -> - check_bytes_list(Bs, Bs0); -check_bytes_list([], Bs0) -> +ensure_binary_list(Bs) -> + ensure_binary_list(Bs, Bs). + +ensure_binary_list([B | Bs], Bs0) when is_binary(B) -> + ensure_binary_list(Bs, Bs0); +ensure_binary_list([], Bs0) -> Bs0; -check_bytes_list(_, Bs0) -> - check_bytes_list(Bs0). - -check_bytes_list([B | Bs]) when is_binary(B) -> - [B | check_bytes_list(Bs)]; -check_bytes_list([B | Bs]) -> - [list_to_binary(B) | check_bytes_list(Bs)]; -check_bytes_list([]) -> +ensure_binary_list(_, Bs0) -> + make_binary_list(Bs0). + +make_binary_list([B | Bs]) -> + [ensure_binary(B) | make_binary_list(Bs)]; +make_binary_list([]) -> []. -check_bytes(Binary) when is_binary(Binary) -> +ensure_binary(Binary) when is_binary(Binary) -> Binary; -check_bytes(Bytes) -> +ensure_binary(Bytes) -> list_to_binary(Bytes). %%----------------------------------------------------------------- @@ -1388,7 +1389,7 @@ check_head({head_func, {M, F, A}}, _Format) when is_atom(M), is_list(A) -> {ok, {M, F, A}}; check_head({head, Head}, external) -> - case catch check_bytes(Head) of + case catch ensure_binary(Head) of {'EXIT', _} -> {error, {badarg, head}}; _ -> -- cgit v1.2.3 From a46e95598f6c587277671980115a4c61ff08c9cd Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 15 Nov 2016 14:21:29 +0100 Subject: Eliminate some code duplication --- lib/kernel/src/disk_log.erl | 63 +++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 33 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 515caf98a7..312d07515b 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -686,7 +686,7 @@ handle({From, write_cache}, S) when From =:= self() -> Error -> loop(S#state{cache_error = Error}) end; -handle({From, {log, B}}, S) -> +handle({From, {log, B}}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); @@ -699,9 +699,9 @@ handle({From, {log, B}}, S) -> L when L#log.blocked_by =:= From -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, {log, B}} | S#state.queue]}) - end; -handle({From, {blog, B}}, S) -> + enqueue(Message, S) + end; +handle({From, {blog, B}}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); @@ -712,9 +712,9 @@ handle({From, {blog, B}}, S) -> L when L#log.blocked_by =:= From -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, {blog, B}} | S#state.queue]}) + enqueue(Message, S) end; -handle({alog, B}, S) -> +handle({alog, B}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> notify_owners({read_only,B}), @@ -728,9 +728,9 @@ handle({alog, B}, S) -> notify_owners({blocked_log, B}), loop(S); _ -> - loop(S#state{queue = [{alog, B} | S#state.queue]}) + enqueue(Message, S) end; -handle({balog, B}, S) -> +handle({balog, B}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> notify_owners({read_only,B}), @@ -741,9 +741,9 @@ handle({balog, B}, S) -> notify_owners({blocked_log, B}), loop(S); _ -> - loop(S#state{queue = [{balog, B} | S#state.queue]}) + enqueue(Message, S) end; -handle({From, {block, QueueLogRecs}}, S) -> +handle({From, {block, QueueLogRecs}}=Message, S) -> case get(log) of L when L#log.status =:= ok -> do_block(From, QueueLogRecs, L), @@ -753,8 +753,7 @@ handle({From, {block, QueueLogRecs}}, S) -> L when L#log.blocked_by =:= From -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, {block, QueueLogRecs}} | - S#state.queue]}) + enqueue(Message, S) end; handle({From, unblock}, S) -> case get(log) of @@ -766,7 +765,7 @@ handle({From, unblock}, S) -> L -> reply(From, {error, {not_blocked_by_pid, L#log.name}}, S) end; -handle({From, sync}, S) -> +handle({From, sync}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); @@ -777,9 +776,9 @@ handle({From, sync}, S) -> L when L#log.blocked_by =:= From -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, sync} | S#state.queue]}) + enqueue(Message, S) end; -handle({From, {truncate, Head, F, A}}, S) -> +handle({From, {truncate, Head, F, A}}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); @@ -801,10 +800,9 @@ handle({From, {truncate, Head, F, A}}, S) -> L when L#log.blocked_by =:= From -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, {truncate, Head, F, A}} - | S#state.queue]}) + enqueue(Message, S) end; -handle({From, {chunk, Pos, B, N}}, S) -> +handle({From, {chunk, Pos, B, N}}=Message, S) -> case get(log) of L when L#log.status =:= ok, S#state.cache_error =/= ok -> loop(cache_error(S, [From])); @@ -817,9 +815,9 @@ handle({From, {chunk, Pos, B, N}}, S) -> L when L#log.status =:= {blocked, false} -> reply(From, {error, {blocked_log, L#log.name}}, S); _L -> - loop(S#state{queue = [{From, {chunk, Pos, B, N}} | S#state.queue]}) + enqueue(Message, S) end; -handle({From, {chunk_step, Pos, N}}, S) -> +handle({From, {chunk_step, Pos, N}}=Message, S) -> case get(log) of L when L#log.status =:= ok, S#state.cache_error =/= ok -> loop(cache_error(S, [From])); @@ -832,10 +830,9 @@ handle({From, {chunk_step, Pos, N}}, S) -> L when L#log.status =:= {blocked, false} -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, {chunk_step, Pos, N}} - | S#state.queue]}) + enqueue(Message, S) end; -handle({From, {change_notify, Pid, NewNotify}}, S) -> +handle({From, {change_notify, Pid, NewNotify}}=Message, S) -> case get(log) of L when L#log.status =:= ok -> case do_change_notify(L, Pid, NewNotify) of @@ -850,10 +847,9 @@ handle({From, {change_notify, Pid, NewNotify}}, S) -> L when L#log.blocked_by =:= From -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, {change_notify, Pid, NewNotify}} - | S#state.queue]}) + enqueue(Message, S) end; -handle({From, {change_header, NewHead}}, S) -> +handle({From, {change_header, NewHead}}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); @@ -870,10 +866,9 @@ handle({From, {change_header, NewHead}}, S) -> L when L#log.blocked_by =:= From -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, {change_header, NewHead}} - | S#state.queue]}) + enqueue(Message, S) end; -handle({From, {change_size, NewSize}}, S) -> +handle({From, {change_size, NewSize}}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); @@ -899,10 +894,9 @@ handle({From, {change_size, NewSize}}, S) -> L when L#log.blocked_by =:= From -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, {change_size, NewSize}} - | S#state.queue]}) + enqueue(Message, S) end; -handle({From, inc_wrap_file}, S) -> +handle({From, inc_wrap_file}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); @@ -925,7 +919,7 @@ handle({From, inc_wrap_file}, S) -> L when L#log.blocked_by =:= From -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> - loop(S#state{queue = [{From, inc_wrap_file} | S#state.queue]}) + enqueue(Message, S) end; handle({From, {reopen, NewFile, Head, F, A}}, S) -> case get(log) of @@ -1034,6 +1028,9 @@ handle({system, From, Req}, S) -> handle(_, S) -> loop(S). +enqueue(Message, S) -> + loop(S#state{queue = [Message | S#state.queue]}). + sync_loop(From, S) -> log_loop(S, [], [], From, 0). -- cgit v1.2.3 From b653dc18fa91e68021b28bef37e942f7fa7f3809 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 15 Nov 2016 15:56:24 +0100 Subject: Only read log format once in collect loop --- lib/kernel/src/disk_log.erl | 54 +++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 312d07515b..d06429d629 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -67,7 +67,7 @@ %%-define(PROFILE(C), C). -define(PROFILE(C), void). --compile({inline,[{log_loop,5},{log_end_sync,2},{replies,2},{rflat,1}]}). +-compile({inline,[{log_loop,6},{log_end_sync,2},{replies,2},{rflat,1}]}). %%%---------------------------------------------------------------------- %%% Contract type specifications @@ -691,7 +691,7 @@ handle({From, {log, B}}=Message, S) -> L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); L when L#log.status =:= ok, L#log.format =:= internal -> - log_loop(S, From, [B], [], iolist_size(B)); + log_loop(S, From, [B], []); L when L#log.status =:= ok, L#log.format =:= external -> reply(From, {error, {format_external, L#log.name}}, S); L when L#log.status =:= {blocked, false} -> @@ -706,7 +706,7 @@ handle({From, {blog, B}}=Message, S) -> L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); L when L#log.status =:= ok -> - log_loop(S, From, [B], [], iolist_size(B)); + log_loop(S, From, [B], []); L when L#log.status =:= {blocked, false} -> reply(From, {error, {blocked_log, L#log.name}}, S); L when L#log.blocked_by =:= From -> @@ -720,7 +720,7 @@ handle({alog, B}=Message, S) -> notify_owners({read_only,B}), loop(S); L when L#log.status =:= ok, L#log.format =:= internal -> - log_loop(S, [], [B], [], iolist_size(B)); + log_loop(S, [], [B], []); L when L#log.status =:= ok -> notify_owners({format_external, B}), loop(S); @@ -736,7 +736,7 @@ handle({balog, B}=Message, S) -> notify_owners({read_only,B}), loop(S); L when L#log.status =:= ok -> - log_loop(S, [], [B], [], iolist_size(B)); + log_loop(S, [], [B], []); L when L#log.status =:= {blocked, false} -> notify_owners({blocked_log, B}), loop(S); @@ -770,7 +770,7 @@ handle({From, sync}=Message, S) -> L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); L when L#log.status =:= ok -> - sync_loop([From], S); + log_loop(S, [], [], [From]); L when L#log.status =:= {blocked, false} -> reply(From, {error, {blocked_log, L#log.name}}, S); L when L#log.blocked_by =:= From -> @@ -1031,41 +1031,43 @@ handle(_, S) -> enqueue(Message, S) -> loop(S#state{queue = [Message | S#state.queue]}). -sync_loop(From, S) -> - log_loop(S, [], [], From, 0). +%% Collect further log and sync requests already in the mailbox or queued -define(MAX_LOOK_AHEAD, 64*1024). +log_loop(S, Pids, Bins, Sync) -> + log_loop(S, Pids, Bins, Sync, iolist_size(Bins), (get(log))#log.format). + %% Inlined. -log_loop(#state{cache_error = CE}=S, Pids, _Bins, _Sync, _Sz) when CE =/= ok -> +log_loop(#state{cache_error = CE}=S, Pids, _Bins, _Sync, _Sz, _F) when CE =/= ok -> loop(cache_error(S, Pids)); -log_loop(#state{}=S, Pids, Bins, Sync, Sz) when Sz > ?MAX_LOOK_AHEAD -> +log_loop(#state{}=S, Pids, Bins, Sync, Sz, _F) when Sz > ?MAX_LOOK_AHEAD -> loop(log_end(S, Pids, Bins, Sync)); -log_loop(#state{messages = []}=S, Pids, Bins, Sync, Sz) -> - receive +log_loop(#state{messages = []}=S, Pids, Bins, Sync, Sz, F) -> + receive Message -> - log_loop(Message, Pids, Bins, Sync, Sz, S, get(log)) + log_loop(Message, Pids, Bins, Sync, Sz, F, S) after 0 -> loop(log_end(S, Pids, Bins, Sync)) end; -log_loop(#state{messages = [M | Ms]}=S, Pids, Bins, Sync, Sz) -> +log_loop(#state{messages = [M | Ms]}=S, Pids, Bins, Sync, Sz, F) -> S1 = S#state{messages = Ms}, - log_loop(M, Pids, Bins, Sync, Sz, S1, get(log)). + log_loop(M, Pids, Bins, Sync, Sz, F, S1). %% Items logged after the last sync request found are sync:ed as well. -log_loop({alog,B}, Pids, Bins, Sync, Sz, S, #log{format = internal}) -> +log_loop({alog,B}, Pids, Bins, Sync, Sz, internal=F, S) -> %% {alog, _} allowed for the internal format only. - log_loop(S, Pids, [B | Bins], Sync, Sz+iolist_size(B)); -log_loop({balog, B}, Pids, Bins, Sync, Sz, S, _L) -> - log_loop(S, Pids, [B | Bins], Sync, Sz+iolist_size(B)); -log_loop({From, {log, B}}, Pids, Bins, Sync, Sz, S, #log{format = internal}) -> + log_loop(S, Pids, [B | Bins], Sync, Sz+iolist_size(B), F); +log_loop({balog, B}, Pids, Bins, Sync, Sz, F, S) -> + log_loop(S, Pids, [B | Bins], Sync, Sz+iolist_size(B), F); +log_loop({From, {log, B}}, Pids, Bins, Sync, Sz, internal=F, S) -> %% {log, _} allowed for the internal format only. - log_loop(S, [From | Pids], [B | Bins], Sync, Sz+iolist_size(B)); -log_loop({From, {blog, B}}, Pids, Bins, Sync, Sz, S, _L) -> - log_loop(S, [From | Pids], [B | Bins], Sync, Sz+iolist_size(B)); -log_loop({From, sync}, Pids, Bins, Sync, Sz, S, _L) -> - log_loop(S, Pids, Bins, [From | Sync], Sz); -log_loop(Message, Pids, Bins, Sync, _Sz, S, _L) -> + log_loop(S, [From | Pids], [B | Bins], Sync, Sz+iolist_size(B), F); +log_loop({From, {blog, B}}, Pids, Bins, Sync, Sz, F, S) -> + log_loop(S, [From | Pids], [B | Bins], Sync, Sz+iolist_size(B), F); +log_loop({From, sync}, Pids, Bins, Sync, Sz, F, S) -> + log_loop(S, Pids, Bins, [From | Sync], Sz, F); +log_loop(Message, Pids, Bins, Sync, _Sz, _F, S) -> NS = log_end(S, Pids, Bins, Sync), handle(Message, NS). -- cgit v1.2.3 From 6abc37b32ac6965ab780cd6fda5667585caaa711 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 15 Nov 2016 16:53:38 +0100 Subject: Use iolist_size instead of local function --- lib/kernel/src/disk_log.erl | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index d06429d629..8dd9975b23 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -1695,7 +1695,7 @@ do_unblock(L, S) -> do_log(L, B) when L#log.type =:= halt -> #log{format = Format, extra = Halt} = L, #halt{curB = CurSize, size = Sz} = Halt, - {Bs, BSize} = bsize(B, Format), + {Bs, BSize} = logl(B, Format), case get(is_full) of true -> {error, {error, {full, L#log.name}}, 0}; @@ -1731,17 +1731,14 @@ do_log(L, B) when L#log.format_type =:= wrap_ext -> {error, Error, Logged - Lost} end. -bsize(B, external) -> - {B, xsz(B, 0)}; -bsize(B, internal) -> +logl(B, external) -> + {B, iolist_size(B)}; +logl(B, internal) -> disk_log_1:logl(B). -xsz([B|T], Sz) -> xsz(T, byte_size(B) + Sz); -xsz([], Sz) -> Sz. - halt_write_full(L, [Bin | Bins], Format, N) -> B = [Bin], - {Bs, BSize} = bsize(B, Format), + {Bs, BSize} = logl(B, Format), Halt = L#log.extra, #halt{curB = CurSize, size = Sz} = Halt, if -- cgit v1.2.3 From 08d22e7658542279711753f3363299105bd669bb Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 15 Nov 2016 17:21:49 +0100 Subject: Pass through known size instead of recomputing --- lib/kernel/src/disk_log.erl | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 8dd9975b23..1b28d05691 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -1042,13 +1042,13 @@ log_loop(S, Pids, Bins, Sync) -> log_loop(#state{cache_error = CE}=S, Pids, _Bins, _Sync, _Sz, _F) when CE =/= ok -> loop(cache_error(S, Pids)); log_loop(#state{}=S, Pids, Bins, Sync, Sz, _F) when Sz > ?MAX_LOOK_AHEAD -> - loop(log_end(S, Pids, Bins, Sync)); + loop(log_end(S, Pids, Bins, Sync, Sz)); log_loop(#state{messages = []}=S, Pids, Bins, Sync, Sz, F) -> receive Message -> log_loop(Message, Pids, Bins, Sync, Sz, F, S) after 0 -> - loop(log_end(S, Pids, Bins, Sync)) + loop(log_end(S, Pids, Bins, Sync, Sz)) end; log_loop(#state{messages = [M | Ms]}=S, Pids, Bins, Sync, Sz, F) -> S1 = S#state{messages = Ms}, @@ -1067,14 +1067,14 @@ log_loop({From, {blog, B}}, Pids, Bins, Sync, Sz, F, S) -> log_loop(S, [From | Pids], [B | Bins], Sync, Sz+iolist_size(B), F); log_loop({From, sync}, Pids, Bins, Sync, Sz, F, S) -> log_loop(S, Pids, Bins, [From | Sync], Sz, F); -log_loop(Message, Pids, Bins, Sync, _Sz, _F, S) -> - NS = log_end(S, Pids, Bins, Sync), +log_loop(Message, Pids, Bins, Sync, Sz, _F, S) -> + NS = log_end(S, Pids, Bins, Sync, Sz), handle(Message, NS). -log_end(S, [], [], Sync) -> +log_end(S, [], [], Sync, _Sz) -> log_end_sync(S, Sync); -log_end(S, Pids, Bins, Sync) -> - case do_log(get(log), rflat(Bins)) of +log_end(S, Pids, Bins, Sync, Sz) -> + case do_log(get(log), rflat(Bins), Sz) of N when is_integer(N) -> ok = replies(Pids, ok), S1 = (state_ok(S))#state{cnt = S#state.cnt+N}, @@ -1692,10 +1692,13 @@ do_unblock(L, S) -> -spec do_log(#log{}, [binary()]) -> integer() | {'error', _, integer()}. -do_log(L, B) when L#log.type =:= halt -> +do_log(L, B) -> + do_log(L, B, iolist_size(B)). + +do_log(L, B, BSz) when L#log.type =:= halt -> #log{format = Format, extra = Halt} = L, #halt{curB = CurSize, size = Sz} = Halt, - {Bs, BSize} = logl(B, Format), + {Bs, BSize} = logl(B, Format, BSz), case get(is_full) of true -> {error, {error, {full, L#log.name}}, 0}; @@ -1704,7 +1707,7 @@ do_log(L, B) when L#log.type =:= halt -> undefined -> halt_write_full(L, B, Format, 0) end; -do_log(L, B) when L#log.format_type =:= wrap_int -> +do_log(L, B, _BSz) when L#log.format_type =:= wrap_int -> case disk_log_1:mf_int_log(L#log.extra, B, L#log.head) of {ok, Handle, Logged, Lost, Wraps} -> notify_owners_wrap(Wraps), @@ -1717,7 +1720,7 @@ do_log(L, B) when L#log.format_type =:= wrap_int -> put(log, L#log{extra = Handle}), {error, Error, Logged - Lost} end; -do_log(L, B) when L#log.format_type =:= wrap_ext -> +do_log(L, B, _BSz) when L#log.format_type =:= wrap_ext -> case disk_log_1:mf_ext_log(L#log.extra, B, L#log.head) of {ok, Handle, Logged, Lost, Wraps} -> notify_owners_wrap(Wraps), @@ -1731,14 +1734,16 @@ do_log(L, B) when L#log.format_type =:= wrap_ext -> {error, Error, Logged - Lost} end. -logl(B, external) -> +logl(B, external, undefined) -> {B, iolist_size(B)}; -logl(B, internal) -> +logl(B, external, Sz) -> + {B, Sz}; +logl(B, internal, _Sz) -> disk_log_1:logl(B). halt_write_full(L, [Bin | Bins], Format, N) -> B = [Bin], - {Bs, BSize} = logl(B, Format), + {Bs, BSize} = logl(B, Format, undefined), Halt = L#log.extra, #halt{curB = CurSize, size = Sz} = Halt, if -- cgit v1.2.3 From 0d8670a9359d6a895b003ad1cfd7a523983ba775 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 18 Nov 2016 18:50:24 +0000 Subject: document {yield/nb_yield}() limitation --- lib/kernel/doc/src/rpc.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml index 5944e9321a..adec2d9520 100644 --- a/lib/kernel/doc/src/rpc.xml +++ b/lib/kernel/doc/src/rpc.xml @@ -88,6 +88,12 @@ to retrieve the value of evaluating apply(Module, Function, Args) on node Node.

+ +

yield/1 and + nb_yield/1,2 + must be called by the same process from which this function + was made otherwise they will never yield correctly.

+
@@ -299,6 +305,11 @@ the tuple {value, Val} when the computation is finished, or timeout when Timeout milliseconds has elapsed.

+ +

This function must be called by the same process from which + async_call/4 + was made otherwise it will only return timeout.

+
@@ -407,6 +418,11 @@ If the answer is available, it is returned immediately. Otherwise, the calling process is suspended until the answer arrives from Node.

+ +

This function must be called by the same process from which + async_call/4 + was made otherwise it will never return.

+
-- cgit v1.2.3 From 5b9265ad19d6596a8b599eccc64accb67e3c664e Mon Sep 17 00:00:00 2001 From: Magnus Henoch Date: Mon, 21 Nov 2016 11:48:54 +0000 Subject: Remove vestiges of watchdog support in heart Hardware watchdog support was removed from heart in R13A, but there were still some vestiges in the code and the documentation. - Remove mentions of the HW_WD_DISABLE variable, as it's no longer used. - Remove the HEART_BEAT_BOOT_DELAY variable, as it was only used for the hardware watchdog. --- lib/kernel/doc/src/heart.xml | 17 +++++------------ lib/kernel/src/heart.erl | 15 +++++---------- 2 files changed, 10 insertions(+), 22 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml index 59a046bf4d..5b5b71e521 100644 --- a/lib/kernel/doc/src/heart.xml +++ b/lib/kernel/doc/src/heart.xml @@ -37,10 +37,7 @@ the heart port program is to check that the Erlang runtime system it is supervising is still running. If the port program has not received any heartbeats within HEART_BEAT_TIMEOUT seconds - (defaults to 60 seconds), the system can be rebooted. Also, if - the system is equipped with a hardware watchdog timer and is - running Solaris, the watchdog can be used to supervise the entire - system.

+ (defaults to 60 seconds), the system can be rebooted.

An Erlang runtime system to be monitored by a heart program is to be started with command-line flag -heart (see also erl(1)). @@ -51,17 +48,13 @@ or a terminated Erlang runtime system, environment variable HEART_COMMAND must be set before the system is started. If this variable is not set, a warning text is printed but - the system does not reboot. However, if the hardware watchdog is - used, it still triggers a reboot HEART_BEAT_BOOT_DELAY - seconds later (defaults to 60 seconds).

+ the system does not reboot.

To reboot on Windows, HEART_COMMAND can be set to heart -shutdown (included in the Erlang delivery) or to any other suitable program that can activate a reboot.

-

The hardware watchdog is not started under Solaris if - environment variable HW_WD_DISABLE is set.

-

The environment variables HEART_BEAT_TIMEOUT and - HEART_BEAT_BOOT_DELAY can be used to configure the heart - time-outs; they can be set in the operating system shell before Erlang +

The environment variable HEART_BEAT_TIMEOUT + can be used to configure the heart + time-outs; it can be set in the operating system shell before Erlang is started or be specified at the command line:

 % erl -heart -env HEART_BEAT_TIMEOUT 30 ...
diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl index eea78aabdf..8fa48d56fb 100644 --- a/lib/kernel/src/heart.erl +++ b/lib/kernel/src/heart.erl @@ -198,16 +198,11 @@ start_portprogram() -> end. get_heart_timeouts() -> - HeartOpts = case os:getenv("HEART_BEAT_TIMEOUT") of - false -> ""; - H when is_list(H) -> - "-ht " ++ H - end, - HeartOpts ++ case os:getenv("HEART_BEAT_BOOT_DELAY") of - false -> ""; - W when is_list(W) -> - " -wt " ++ W - end. + case os:getenv("HEART_BEAT_TIMEOUT") of + false -> ""; + H when is_list(H) -> + "-ht " ++ H + end. check_start_heart() -> case init:get_argument(heart) of -- cgit v1.2.3 From 65c4401c1cd1094da5d8f35137532a22054a8517 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Mon, 21 Nov 2016 15:31:16 +0100 Subject: Remove remnants of module package support --- lib/kernel/src/code.erl | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 622b27080c..1b149bbb4e 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -719,37 +719,28 @@ start_get_mode() -> which(Module) when is_atom(Module) -> case is_loaded(Module) of false -> - which2(Module); + File = atom_to_list(Module) ++ objfile_extension(), + which(File, get_path()); {file, File} -> File end. -which2(Module) -> - Base = atom_to_list(Module), - File = filename:basename(Base) ++ objfile_extension(), - Path = get_path(), - which(File, filename:dirname(Base), Path). - --spec which(file:filename(), file:filename(), [file:filename()]) -> +-spec which(file:filename(), [file:filename()]) -> 'non_existing' | file:filename(). -which(_, _, []) -> +which(_, []) -> non_existing; -which(File, Base, [Directory|Tail]) -> - Path = if - Base =:= "." -> Directory; - true -> filename:join(Directory, Base) - end, +which(File, [Path|Tail]) -> case erl_prim_loader:list_dir(Path) of {ok,Files} -> case lists:member(File,Files) of true -> filename:append(Path, File); false -> - which(File, Base, Tail) + which(File, Tail) end; _Error -> - which(File, Base, Tail) + which(File, Tail) end. %% Search the code path for a specific file. Try to locate @@ -760,13 +751,13 @@ which(File, Base, [Directory|Tail]) -> Absname :: file:filename(). where_is_file(File) when is_list(File) -> Path = get_path(), - which(File, ".", Path). + which(File, Path). -spec where_is_file(Path :: file:filename(), Filename :: file:filename()) -> file:filename() | 'non_existing'. where_is_file(Path, File) when is_list(Path), is_list(File) -> - which(File, ".", Path). + which(File, Path). -spec set_primary_archive(ArchiveFile :: file:filename(), ArchiveBin :: binary(), -- cgit v1.2.3 From c7e5cf8e259956120c07206c4e7df235b129cb56 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 22 Nov 2016 15:17:04 +0100 Subject: Restructure code:which() and where_is_file() --- lib/kernel/src/code.erl | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 1b149bbb4e..bb19d6716d 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -719,29 +719,14 @@ start_get_mode() -> which(Module) when is_atom(Module) -> case is_loaded(Module) of false -> - File = atom_to_list(Module) ++ objfile_extension(), - which(File, get_path()); + which(Module, get_path()); {file, File} -> File end. --spec which(file:filename(), [file:filename()]) -> - 'non_existing' | file:filename(). - -which(_, []) -> - non_existing; -which(File, [Path|Tail]) -> - case erl_prim_loader:list_dir(Path) of - {ok,Files} -> - case lists:member(File,Files) of - true -> - filename:append(Path, File); - false -> - which(File, Tail) - end; - _Error -> - which(File, Tail) - end. +which(Module, Path) when is_atom(Module) -> + File = atom_to_list(Module) ++ objfile_extension(), + where_is_file(Path, File). %% Search the code path for a specific file. Try to locate %% it in the code path cache if possible. @@ -751,13 +736,28 @@ which(File, [Path|Tail]) -> Absname :: file:filename(). where_is_file(File) when is_list(File) -> Path = get_path(), - which(File, Path). + where_is_file(Path, File). -spec where_is_file(Path :: file:filename(), Filename :: file:filename()) -> file:filename() | 'non_existing'. -where_is_file(Path, File) when is_list(Path), is_list(File) -> - which(File, Path). +where_is_file([], _) -> + non_existing; +where_is_file([Path|Tail], File) -> + case erl_prim_loader:list_dir(Path) of + {ok,Files} -> + where_is_file(Tail, File, Path, Files); + _Error -> + where_is_file(Tail, File) + end. + +where_is_file(Tail, File, Path, Files) -> + case lists:member(File, Files) of + true -> + filename:append(Path, File); + false -> + where_is_file(Tail, File) + end. -spec set_primary_archive(ArchiveFile :: file:filename(), ArchiveBin :: binary(), -- cgit v1.2.3 From a834d721e5047c5c43a8ede249fdf6711234ff1b Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 22 Nov 2016 15:33:14 +0100 Subject: Handle prefetched paths --- lib/kernel/src/code.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index bb19d6716d..0ad0676f98 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -738,11 +738,16 @@ where_is_file(File) when is_list(File) -> Path = get_path(), where_is_file(Path, File). --spec where_is_file(Path :: file:filename(), Filename :: file:filename()) -> - file:filename() | 'non_existing'. +%% To avoid unnecessary work when looking at many modules, this also +%% accepts pairs of directories and pre-fetched contents in the path +-spec where_is_file(Path :: [Dir|{Dir,Files}], Filename :: file:filename()) -> + 'non_existing' | file:filename() when + Dir :: file:filename(), Files :: [file:filename()]. where_is_file([], _) -> non_existing; +where_is_file([{Path, Files}|Tail], File) -> + where_is_file(Tail, File, Path, Files); where_is_file([Path|Tail], File) -> case erl_prim_loader:list_dir(Path) of {ok,Files} -> -- cgit v1.2.3 From fa73cc8e23d62c6112bd67f5d311c6043ee2ae94 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Thu, 9 Jul 2015 22:39:49 +0200 Subject: Add license headers to hipe files in kernel --- lib/kernel/src/hipe_ext_format.hrl | 12 ++++++++++++ lib/kernel/src/hipe_unified_loader.erl | 11 +++++++++++ 2 files changed, 23 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/src/hipe_ext_format.hrl b/lib/kernel/src/hipe_ext_format.hrl index 102cb49a2b..05c678fdec 100644 --- a/lib/kernel/src/hipe_ext_format.hrl +++ b/lib/kernel/src/hipe_ext_format.hrl @@ -1,3 +1,15 @@ +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + %% hipe_x86_ext_format.hrl %% Definitions for unified external object format %% Currently: sparc, x86, amd64 diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 04ec1479cb..f4c7c277ed 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -1,4 +1,15 @@ %% -*- erlang-indent-level: 2 -*- +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% ======================================================================= %% Filename : hipe_unified_loader.erl %% Module : hipe_unified_loader -- cgit v1.2.3 From d1301e814920bde89dec4acfab58d0f2600e2b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Thu, 24 Nov 2016 21:26:20 +0100 Subject: Remove duplicate docs for the priority inet option --- lib/kernel/doc/src/inet.xml | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index d907cef7d3..4c4a5c39cb 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -987,11 +987,6 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp

Sets the line delimiting character for line-oriented protocols (line). Defaults to $\n.

- {priority, Priority} - -

Sets the protocol-defined priority for all packets to be sent - on this socket.

-
{raw, Protocol, OptionNum, ValueBin}

See below.

-- cgit v1.2.3 From 86fa667f9731c790d6575f31efa156c02cb7984b Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Thu, 19 May 2016 20:29:45 +0200 Subject: Add code:module_status/1 and modified_modules/0 These functions use the MD5 beam/native checksum to determine whether the code for a module has changed on disk and is a candidate for loading. --- lib/kernel/doc/src/code.xml | 42 ++++++++++ lib/kernel/src/code.erl | 98 +++++++++++++++++++++- lib/kernel/test/code_SUITE.erl | 180 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 319 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 3143cdc825..f881fd76fd 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -898,6 +898,48 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]), identical names and writes a report to stdout.

+ + + Return the status of the module in relation to object file on disk. + +

Returns:

+ + not_loaded +

If Module is not currently loaded.

+ loaded +

If Module is loaded and the object file + exists and contains the same code.

+ removed +

If Module is loaded but no + corresponding object file can be found in the code path.

+ modified +

If Module is loaded but the object file + contains code with a different MD5 checksum.

+
+

Preloaded modules are always reported as loaded, without + inspecting the contents on disk. Cover compiled modules will always + be reported as modified if an object file exists, or as + removed otherwise. Modules whose load path is an empty string + (which is the convention for auto-generated code) will only be + reported as loaded or not_loaded.

+

For modules that have native code loaded (see + is_module_native/1), + the MD5 sum of the native code in the object file is used for the + comparison, if it exists; the Beam code in the file is ignored. + Reversely, for modules that do not currently have native code + loaded, any native code in the file will be ignored.

+

See also modified_modules/0.

+
+
+ + + Return a list of all modules modified on disk. + +

Returns the list of all currently loaded modules for which + module_status/1 + returns modified. See also all_loaded/0.

+
+
Test if a module has native code. diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 0ad0676f98..5a7ca493cc 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -70,7 +70,9 @@ where_is_file/2, set_primary_archive/4, clash/0, - get_mode/0]). + module_status/1, + modified_modules/0, + get_mode/0]). -deprecated({rehash,0,next_major_release}). @@ -895,3 +897,97 @@ load_all_native_1([{Mod,BeamFilename}|T], ChunkTag) -> load_all_native_1(T, ChunkTag); load_all_native_1([], _) -> ok. + +%% Returns the status of the module in relation to object file on disk. +-spec module_status(Module :: module()) -> not_loaded | loaded | modified | removed. +module_status(Module) -> + module_status(Module, code:get_path()). + +%% Note that we don't want to go via which/1, since it doesn't look at the +%% disk contents at all if the module is already loaded. +module_status(Module, PathFiles) -> + case code:is_loaded(Module) of + false -> not_loaded; + {file, preloaded} -> loaded; + {file, cover_compiled} -> + %% cover compilation loads directly to memory and does not + %% create a beam file, so report 'modified' if a file exists + case which(Module, PathFiles) of + non_existing -> removed; + _File -> modified + end; + {file, []} -> loaded; % no beam file - generated code + {file, OldFile} when is_list(OldFile) -> + %% we don't care whether or not the file is in the same location + %% as when last loaded, as long as it can be found in the path + case which(Module, PathFiles) of + non_existing -> removed; + Path -> + case module_changed_on_disk(Module, Path) of + true -> modified; + false -> loaded + end + end + end. + +%% Detects actual code changes only, e.g. to decide whether a module should +%% be reloaded; does not care about file timestamps or compilation time +module_changed_on_disk(Module, Path) -> + MD5 = erlang:get_module_info(Module, md5), + case erlang:system_info(hipe_architecture) of + undefined -> + %% straightforward, since native is not supported + MD5 =/= beam_file_md5(Path); + Architecture -> + case code:is_module_native(Module) of + true -> + %% MD5 is for native code, so we check only the native + %% code on disk, ignoring the beam code + MD5 =/= beam_file_native_md5(Path, Architecture); + _ -> + %% MD5 is for beam code, so check only the beam code on + %% disk, even if the file contains native code as well + MD5 =/= beam_file_md5(Path) + end + end. + +beam_file_md5(Path) -> + case beam_lib:md5(Path) of + {ok,{_Mod,MD5}} -> MD5; + _ -> undefined + end. + +beam_file_native_md5(Path, Architecture) -> + try + get_beam_chunk(Path, hipe_unified_loader:chunk_name(Architecture)) + of + NativeCode when is_binary(NativeCode) -> + erlang:md5(NativeCode) + catch + _:_ -> undefined + end. + +get_beam_chunk(Path, Chunk) -> + {ok, {_, [{_, Bin}]}} = beam_lib:chunks(Path, [Chunk]), + Bin. + +%% Returns a list of all modules modified on disk. +-spec modified_modules() -> [module()]. +modified_modules() -> + PathFiles = path_files(), + [M || {M, _} <- code:all_loaded(), + module_status(M, PathFiles) =:= modified]. + +%% prefetch the directory contents of code path directories +path_files() -> + path_files(code:get_path()). + +path_files([]) -> + []; +path_files([Path|Tail]) -> + case erl_prim_loader:list_dir(Path) of + {ok, Files} -> + [{Path,Files} | path_files(Tail)]; + _Error -> + path_files(Tail) + end. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 29b3f7caaf..4914ce9e4c 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -38,6 +38,7 @@ on_load_purge/1, on_load_self_call/1, on_load_pending/1, on_load_deleted/1, big_boot_embedded/1, + module_status/1, native_early_modules/1, get_mode/1, normalized_paths/1]). @@ -68,6 +69,7 @@ all() -> on_load_binary, on_load_embedded, on_load_errors, on_load_update, on_load_purge, on_load_self_call, on_load_pending, on_load_deleted, + module_status, big_boot_embedded, native_early_modules, get_mode, normalized_paths]. groups() -> @@ -93,6 +95,11 @@ init_per_suite(Config) -> end_per_suite(Config) -> Config. +-define(TESTMOD, test_dummy). +-define(TESTMODSTR, "test_dummy"). +-define(TESTMODSRC, ?TESTMODSTR ".erl"). +-define(TESTMODOBJ, ?TESTMODSTR ".beam"). + init_per_testcase(big_boot_embedded, Config) -> case catch crypto:start() of ok -> @@ -104,6 +111,13 @@ init_per_testcase(_Func, Config) -> P = code:get_path(), [{code_path, P}|Config]. +end_per_testcase(module_status, Config) -> + code:purge(?TESTMOD), + code:delete(?TESTMOD), + code:purge(?TESTMOD), + file:delete(?TESTMODOBJ), + file:delete(?TESTMODSRC), + end_per_testcase(Config); end_per_testcase(TC, Config) when TC == mult_lib_roots; TC == big_boot_embedded -> {ok, HostName} = inet:gethostname(), @@ -1757,6 +1771,172 @@ do_normalized_paths([M|Ms]) -> do_normalized_paths([]) -> ok. +%% Test that module_status/1 behaves as expected +module_status(_Config) -> + %% basics + not_loaded = code:module_status(fubar), % nonexisting + {file, preloaded} = code:is_loaded(erlang), + loaded = code:module_status(erlang), % preloaded + loaded = code:module_status(?MODULE), % normal known loaded + + non_existing = code:which(?TESTMOD), % verify dummy name not in path + code:purge(?TESTMOD), % ensure no previous version in memory + code:delete(?TESTMOD), + code:purge(?TESTMOD), + + %% generated code is detected as such + {ok,?TESTMOD,Bin} = compile:forms(dummy_ast(), []), + {module,?TESTMOD} = code:load_binary(?TESTMOD,"",Bin), % no source file + ok = ?TESTMOD:f(), + "" = code:which(?TESTMOD), % verify empty string for source file + loaded = code:module_status(?TESTMOD), + + %% deleting generated code + true = code:delete(?TESTMOD), + non_existing = code:which(?TESTMOD), % verify still not in path + not_loaded = code:module_status(?TESTMOD), + + %% beam file exists but not loaded + make_source_file(<<"0">>), + compile_beam(0), + true = (non_existing =/= code:which(?TESTMOD)), % verify in path + not_loaded = code:module_status(?TESTMOD), + + %% loading code from disk makes it loaded + load_code(), + loaded = code:module_status(?TESTMOD), % loaded + + %% cover compiling a module + {ok,?TESTMOD} = cover:compile(?TESTMOD), + {file, cover_compiled} = code:is_loaded(?TESTMOD), % verify cover compiled + modified = code:module_status(?TESTMOD), % loaded cover code but file exists + remove_code(), + removed = code:module_status(?TESTMOD), % removed + compile_beam(0), + modified = code:module_status(?TESTMOD), % recreated + load_code(), + loaded = code:module_status(?TESTMOD), % loading removes cover status + code:purge(?TESTMOD), + true = code:delete(?TESTMOD), + not_loaded = code:module_status(?TESTMOD), % deleted + + %% recompilation ignores timestamps, only md5 matters + load_code(), + compile_beam(1100), + loaded = code:module_status(?TESTMOD), + + %% modifying module detects different md5 + make_source_file(<<"1">>), + compile_beam(0), + modified = code:module_status(?TESTMOD), + + %% loading the modified code from disk makes it loaded + load_code(), + loaded = code:module_status(?TESTMOD), + + %% removing and recreating a module with same md5 + remove_code(), + removed = code:module_status(?TESTMOD), + compile_beam(0), + loaded = code:module_status(?TESTMOD), + + case erlang:system_info(hipe_architecture) of + undefined -> + %% no native support + ok; + _ -> + %% native chunk is ignored if beam code is already loaded + load_code(), + loaded = code:module_status(?TESTMOD), + false = has_native(?TESTMOD), + compile_native(0), + BeamMD5 = erlang:get_module_info(?TESTMOD, md5), + {ok,{?TESTMOD,BeamMD5}} = beam_lib:md5(?TESTMODOBJ), % beam md5 unchanged + loaded = code:module_status(?TESTMOD), + + %% native code reported as loaded, though different md5 from beam + load_code(), + true = has_native(?TESTMOD), + NativeMD5 = erlang:get_module_info(?TESTMOD, md5), + true = (BeamMD5 =/= NativeMD5), + loaded = code:module_status(?TESTMOD), + + %% recompilation ignores timestamps, only md5 matters + compile_native(1100), % later timestamp + loaded = code:module_status(?TESTMOD), + + %% modifying native module detects different md5 + make_source_file(<<"2">>), + compile_native(0), + modified = code:module_status(?TESTMOD), + + %% loading the modified native code from disk makes it loaded + load_code(), + true = has_native(?TESTMOD), + NativeMD5_2 = erlang:get_module_info(?TESTMOD, md5), + true = (NativeMD5 =/= NativeMD5_2), % verify native md5 changed + {ok,{?TESTMOD,BeamMD5_2}} = beam_lib:md5(?TESTMODOBJ), + true = (BeamMD5_2 =/= NativeMD5_2), % verify md5 differs from beam + loaded = code:module_status(?TESTMOD), + + %% removing and recreating a native module with same md5 + remove_code(), + removed = code:module_status(?TESTMOD), + compile_native(0), + loaded = code:module_status(?TESTMOD), + + %% purging/deleting native module + code:purge(?TESTMOD), + true = code:delete(?TESTMOD), + not_loaded = code:module_status(?TESTMOD) + end, + ok. + +compile_beam(Sleep) -> + compile(Sleep, []). + +compile_native(Sleep) -> + compile(Sleep, [native]). + +compile(Sleep, Opts) -> + timer:sleep(Sleep), % increment compilation timestamp + {ok,?TESTMOD} = compile:file(?TESTMODSRC, Opts). + +load_code() -> + code:purge(?TESTMOD), + {module,?TESTMOD} = code:load_file(?TESTMOD). + +remove_code() -> + ok = file:delete(?TESTMODOBJ). + +has_native(Module) -> + case erlang:get_module_info(Module, native_addresses) of + [] -> false; + [_|_] -> true + end. + +make_source_file(Body) -> + ok = file:write_file(?TESTMODSRC, dummy_source(Body)). + +dummy_source(Body) -> + [<<"-module(" ?TESTMODSTR ").\n" + "-export([f/0]).\n" + "f() -> ">>, Body, <<".\n">>]. + +dummy_ast() -> + dummy_ast(?TESTMODSTR). + +dummy_ast(Mod) when is_atom(Mod) -> + dummy_ast(atom_to_list(Mod)); +dummy_ast(ModStr) -> + [scan_form("-module(" ++ ModStr ++ ")."), + scan_form("-export([f/0])."), + scan_form("f() -> ok.")]. + +scan_form(String) -> + {ok,Ts,_} = erl_scan:string(String), + {ok,F} = erl_parse:parse_form(Ts), + F. %%----------------------------------------------------------------- %% error_logger handler. -- cgit v1.2.3 From 9bb7aee366b04f6e8b6ea8491c0d7ebbdb304bb6 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 15 Nov 2016 18:49:39 +0100 Subject: Clarify that the type for disk log data is iodata() --- lib/kernel/doc/src/disk_log.xml | 13 +++---------- lib/kernel/src/disk_log.erl | 18 +++++++----------- lib/kernel/src/disk_log.hrl | 3 +-- 3 files changed, 11 insertions(+), 23 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index 3c9bc7f6e8..aebeacee28 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -109,8 +109,7 @@ These functions log one or more Erlang terms. By prefixing each of the functions with a b (for "binary"), we get the corresponding blog() functions for the external format. - These functions log one or more deep lists of bytes or, alternatively, - binaries of deep lists of bytes. + These functions log one or more chunks of bytes. For example, to log the string "hello" in ASCII format, you can use disk_log:blog(Log, "hello"), or disk_log:blog(Log, list_to_binary("hello")). The two @@ -218,9 +217,6 @@ - - - @@ -233,9 +229,6 @@ chunk/2,3, bchunk/2,3, or chunk_step/3.

- - - @@ -953,7 +946,7 @@ written first on the log file. If the log is a wrap log, the item Head is written first in each new file. Head is to be a term if the format is - internal, otherwise a deep list of bytes (or a binary). + internal, otherwise a sequence of bytes. Defaults to none, which means that no header is written first on the file.

@@ -965,7 +958,7 @@ The call M:F(A) is assumed to return {ok, Head}. The item Head is written first in each file. Head is to be a term if the format is - internal, otherwise a deep list of bytes (or a binary). + internal, otherwise a sequence of bytes.

{mode, Mode} diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 1b28d05691..bc31f1fbbd 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -75,8 +75,6 @@ -opaque continuation() :: #continuation{}. --type bytes() :: binary() | [byte()]. - -type file_error() :: term(). % XXX: refine -type invalid_header() :: term(). % XXX: refine @@ -131,7 +129,7 @@ log(Log, Term) -> -spec blog(Log, Bytes) -> ok | {error, Reason :: log_error_rsn()} when Log :: log(), - Bytes :: bytes(). + Bytes :: iodata(). blog(Log, Bytes) -> req(Log, {blog, ensure_binary(Bytes)}). @@ -145,7 +143,7 @@ log_terms(Log, Terms) -> -spec blog_terms(Log, BytesList) -> ok | {error, Reason :: log_error_rsn()} when Log :: log(), - BytesList :: [bytes()]. + BytesList :: [iodata()]. blog_terms(Log, Bytess) -> Bs = ensure_binary_list(Bytess), req(Log, {blog, Bs}). @@ -167,13 +165,13 @@ alog_terms(Log, Terms) -> -spec balog(Log, Bytes) -> notify_ret() when Log :: log(), - Bytes :: bytes(). + Bytes :: iodata(). balog(Log, Bytes) -> notify(Log, {balog, ensure_binary(Bytes)}). -spec balog_terms(Log, ByteList) -> notify_ret() when Log :: log(), - ByteList :: [bytes()]. + ByteList :: [iodata()]. balog_terms(Log, Bytess) -> Bs = ensure_binary_list(Bytess), notify(Log, {balog, Bs}). @@ -219,7 +217,7 @@ truncate(Log, Head) -> -spec btruncate(Log, BHead) -> 'ok' | {'error', trunc_error_rsn()} when Log :: log(), - BHead :: bytes(). + BHead :: iodata(). btruncate(Log, Head) -> req(Log, {truncate, {ok, ensure_binary(Head)}, btruncate, 2}). @@ -248,7 +246,7 @@ reopen(Log, NewFile, NewHead) -> -spec breopen(Log, File, BHead) -> 'ok' | {'error', reopen_error_rsn()} when Log :: log(), File :: file:filename(), - BHead :: bytes(). + BHead :: iodata(). breopen(Log, NewFile, NewHead) -> req(Log, {reopen, NewFile, {ok, ensure_binary(NewHead)}, breopen, 3}). @@ -1348,10 +1346,8 @@ make_binary_list([B | Bs]) -> make_binary_list([]) -> []. -ensure_binary(Binary) when is_binary(Binary) -> - Binary; ensure_binary(Bytes) -> - list_to_binary(Bytes). + iolist_to_binary(Bytes). %%----------------------------------------------------------------- %% Change size of the logs in runtime. diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index 3262d979ee..3cf8a3b3a2 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.hrl @@ -54,11 +54,10 @@ %% Types -- alphabetically %%------------------------------------------------------------------------ --type dlog_byte() :: [dlog_byte()] | byte(). -type dlog_format() :: 'external' | 'internal'. -type dlog_format_type() :: 'halt_ext' | 'halt_int' | 'wrap_ext' | 'wrap_int'. -type dlog_head() :: 'none' | {'ok', binary()} | mfa(). --type dlog_head_opt() :: none | term() | binary() | [dlog_byte()]. +-type dlog_head_opt() :: none | term() | iodata(). -type log() :: term(). % XXX: refine -type dlog_mode() :: 'read_only' | 'read_write'. -type dlog_name() :: atom() | string(). -- cgit v1.2.3 From 3900d246682a46cec3b4dcf4c1b13259038ab358 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Wed, 16 Nov 2016 15:11:45 +0100 Subject: Simplify for rflat --- lib/kernel/src/disk_log.erl | 11 ++++------- lib/kernel/test/disk_log_SUITE.erl | 10 +++++----- 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index bc31f1fbbd..2a7afb4c53 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -125,13 +125,13 @@ open(A) -> Log :: log(), Term :: term(). log(Log, Term) -> - req(Log, {log, term_to_binary(Term)}). + req(Log, {log, [term_to_binary(Term)]}). -spec blog(Log, Bytes) -> ok | {error, Reason :: log_error_rsn()} when Log :: log(), Bytes :: iodata(). blog(Log, Bytes) -> - req(Log, {blog, ensure_binary(Bytes)}). + req(Log, {blog, [ensure_binary(Bytes)]}). -spec log_terms(Log, TermList) -> ok | {error, Resaon :: log_error_rsn()} when Log :: log(), @@ -154,7 +154,7 @@ blog_terms(Log, Bytess) -> Log :: log(), Term :: term(). alog(Log, Term) -> - notify(Log, {alog, term_to_binary(Term)}). + notify(Log, {alog, [term_to_binary(Term)]}). -spec alog_terms(Log, TermList) -> notify_ret() when Log :: log(), @@ -167,7 +167,7 @@ alog_terms(Log, Terms) -> Log :: log(), Bytes :: iodata(). balog(Log, Bytes) -> - notify(Log, {balog, ensure_binary(Bytes)}). + notify(Log, {balog, [ensure_binary(Bytes)]}). -spec balog_terms(Log, ByteList) -> notify_ret() when Log :: log(), @@ -1093,12 +1093,9 @@ log_end_sync(S, Sync) -> state_err(S, Res). %% Inlined. -rflat([B]=L) when is_binary(B) -> L; rflat([B]) -> B; rflat(B) -> rflat(B, []). -rflat([B | Bs], L) when is_binary(B) -> - rflat(Bs, [B | L]); rflat([B | Bs], L) -> rflat(Bs, B ++ L); rflat([], L) -> L. diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index f7ad9c0c04..a25b315d9d 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -421,7 +421,7 @@ halt_ro_alog(Conf) when is_list(Conf) -> halt_ro_alog_wait_notify(Log, T) -> Term = term_to_binary(T), receive - {disk_log, _, Log,{read_only, Term}} -> + {disk_log, _, Log,{read_only, [Term]}} -> ok; Other -> Other @@ -449,7 +449,7 @@ halt_ro_balog(Conf) when is_list(Conf) -> halt_ro_balog_wait_notify(Log, T) -> Term = list_to_binary(T), receive - {disk_log, _, Log,{read_only, Term}} -> + {disk_log, _, Log,{read_only, [Term]}} -> ok; Other -> Other @@ -1385,15 +1385,15 @@ blocked_notif(Conf) when is_list(Conf) -> "The requested operation" ++ _ = format_error(Error1), ok = disk_log:blog(n, B), ok = disk_log:alog(n, B), - rec(1, {disk_log, node(), n, {format_external, term_to_binary(B)}}), + rec(1, {disk_log, node(), n, {format_external, [term_to_binary(B)]}}), ok = disk_log:alog_terms(n, [B,B,B,B]), rec(1, {disk_log, node(), n, {format_external, lists:map(fun term_to_binary/1, [B,B,B,B])}}), ok = disk_log:block(n, false), ok = disk_log:alog(n, B), - rec(1, {disk_log, node(), n, {blocked_log, term_to_binary(B)}}), + rec(1, {disk_log, node(), n, {blocked_log, [term_to_binary(B)]}}), ok = disk_log:balog(n, B), - rec(1, {disk_log, node(), n, {blocked_log, list_to_binary(B)}}), + rec(1, {disk_log, node(), n, {blocked_log, [list_to_binary(B)]}}), ok = disk_log:balog_terms(n, [B,B,B,B]), disk_log:close(n), rec(1, {disk_log, node(), n, {blocked_log, -- cgit v1.2.3 From 3aadf13da204f955fe7cb6932c75bf71a856650b Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Wed, 16 Nov 2016 21:53:34 +0100 Subject: Eliminate more code duplication --- lib/kernel/src/disk_log.erl | 62 +++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 44 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 2a7afb4c53..ad3c5ae227 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -125,20 +125,20 @@ open(A) -> Log :: log(), Term :: term(). log(Log, Term) -> - req(Log, {log, [term_to_binary(Term)]}). + req(Log, {log, internal, [term_to_binary(Term)]}). -spec blog(Log, Bytes) -> ok | {error, Reason :: log_error_rsn()} when Log :: log(), Bytes :: iodata(). blog(Log, Bytes) -> - req(Log, {blog, [ensure_binary(Bytes)]}). + req(Log, {log, external, [ensure_binary(Bytes)]}). -spec log_terms(Log, TermList) -> ok | {error, Resaon :: log_error_rsn()} when Log :: log(), TermList :: [term()]. log_terms(Log, Terms) -> Bs = terms2bins(Terms), - req(Log, {log, Bs}). + req(Log, {log, internal, Bs}). -spec blog_terms(Log, BytesList) -> ok | {error, Reason :: log_error_rsn()} when @@ -146,7 +146,7 @@ log_terms(Log, Terms) -> BytesList :: [iodata()]. blog_terms(Log, Bytess) -> Bs = ensure_binary_list(Bytess), - req(Log, {blog, Bs}). + req(Log, {log, external, Bs}). -type notify_ret() :: 'ok' | {'error', 'no_such_log'}. @@ -154,27 +154,27 @@ blog_terms(Log, Bytess) -> Log :: log(), Term :: term(). alog(Log, Term) -> - notify(Log, {alog, [term_to_binary(Term)]}). + notify(Log, {alog, internal, [term_to_binary(Term)]}). -spec alog_terms(Log, TermList) -> notify_ret() when Log :: log(), TermList :: [term()]. alog_terms(Log, Terms) -> Bs = terms2bins(Terms), - notify(Log, {alog, Bs}). + notify(Log, {alog, internal, Bs}). -spec balog(Log, Bytes) -> notify_ret() when Log :: log(), Bytes :: iodata(). balog(Log, Bytes) -> - notify(Log, {balog, [ensure_binary(Bytes)]}). + notify(Log, {alog, external, [ensure_binary(Bytes)]}). -spec balog_terms(Log, ByteList) -> notify_ret() when Log :: log(), ByteList :: [iodata()]. balog_terms(Log, Bytess) -> Bs = ensure_binary_list(Bytess), - notify(Log, {balog, Bs}). + notify(Log, {alog, external, Bs}). -type close_error_rsn() ::'no_such_log' | 'nonode' | {'file_error', file:filename(), file_error()}. @@ -684,25 +684,12 @@ handle({From, write_cache}, S) when From =:= self() -> Error -> loop(S#state{cache_error = Error}) end; -handle({From, {log, B}}=Message, S) -> +handle({From, {log, Format, B}}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> reply(From, {error, {read_only_mode, L#log.name}}, S); - L when L#log.status =:= ok, L#log.format =:= internal -> - log_loop(S, From, [B], []); - L when L#log.status =:= ok, L#log.format =:= external -> + L when L#log.status =:= ok, L#log.format =:= external, Format =:= internal -> reply(From, {error, {format_external, L#log.name}}, S); - L when L#log.status =:= {blocked, false} -> - reply(From, {error, {blocked_log, L#log.name}}, S); - L when L#log.blocked_by =:= From -> - reply(From, {error, {blocked_log, L#log.name}}, S); - _ -> - enqueue(Message, S) - end; -handle({From, {blog, B}}=Message, S) -> - case get(log) of - L when L#log.mode =:= read_only -> - reply(From, {error, {read_only_mode, L#log.name}}, S); L when L#log.status =:= ok -> log_loop(S, From, [B], []); L when L#log.status =:= {blocked, false} -> @@ -712,27 +699,14 @@ handle({From, {blog, B}}=Message, S) -> _ -> enqueue(Message, S) end; -handle({alog, B}=Message, S) -> +handle({alog, Format, B}=Message, S) -> case get(log) of L when L#log.mode =:= read_only -> notify_owners({read_only,B}), loop(S); - L when L#log.status =:= ok, L#log.format =:= internal -> - log_loop(S, [], [B], []); - L when L#log.status =:= ok -> + L when L#log.status =:= ok, L#log.format =:= external, Format =:= internal -> notify_owners({format_external, B}), loop(S); - L when L#log.status =:= {blocked, false} -> - notify_owners({blocked_log, B}), - loop(S); - _ -> - enqueue(Message, S) - end; -handle({balog, B}=Message, S) -> - case get(log) of - L when L#log.mode =:= read_only -> - notify_owners({read_only,B}), - loop(S); L when L#log.status =:= ok -> log_loop(S, [], [B], []); L when L#log.status =:= {blocked, false} -> @@ -1053,15 +1027,15 @@ log_loop(#state{messages = [M | Ms]}=S, Pids, Bins, Sync, Sz, F) -> log_loop(M, Pids, Bins, Sync, Sz, F, S1). %% Items logged after the last sync request found are sync:ed as well. -log_loop({alog,B}, Pids, Bins, Sync, Sz, internal=F, S) -> - %% {alog, _} allowed for the internal format only. +log_loop({alog, internal, B}, Pids, Bins, Sync, Sz, internal=F, S) -> + %% alog of terms allowed for the internal format only log_loop(S, Pids, [B | Bins], Sync, Sz+iolist_size(B), F); -log_loop({balog, B}, Pids, Bins, Sync, Sz, F, S) -> +log_loop({alog, binary, B}, Pids, Bins, Sync, Sz, F, S) -> log_loop(S, Pids, [B | Bins], Sync, Sz+iolist_size(B), F); -log_loop({From, {log, B}}, Pids, Bins, Sync, Sz, internal=F, S) -> - %% {log, _} allowed for the internal format only. +log_loop({From, {log, internal, B}}, Pids, Bins, Sync, Sz, internal=F, S) -> + %% log of terms allowed for the internal format only log_loop(S, [From | Pids], [B | Bins], Sync, Sz+iolist_size(B), F); -log_loop({From, {blog, B}}, Pids, Bins, Sync, Sz, F, S) -> +log_loop({From, {log, binary, B}}, Pids, Bins, Sync, Sz, F, S) -> log_loop(S, [From | Pids], [B | Bins], Sync, Sz+iolist_size(B), F); log_loop({From, sync}, Pids, Bins, Sync, Sz, F, S) -> log_loop(S, Pids, Bins, [From | Sync], Sz, F); -- cgit v1.2.3 From 5a8a1a963edd6d6dbb35bf615a4bad7d77041443 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Wed, 16 Nov 2016 23:07:29 +0100 Subject: Use pattern matching for records where suitable --- lib/kernel/src/disk_log.erl | 166 ++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 84 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index ad3c5ae227..69c65c9c43 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -668,13 +668,12 @@ init(Parent, Server) -> process_flag(trap_exit, true), loop(#state{parent = Parent, server = Server}). -loop(State) when State#state.messages =:= [] -> +loop(#state{messages = []}=State) -> receive Message -> handle(Message, State) end; -loop(State) -> - [M | Ms] = State#state.messages, +loop(#state{messages = [M | Ms]}=State) -> handle(M, State#state{messages = Ms}). handle({From, write_cache}, S) when From =:= self() -> @@ -686,30 +685,30 @@ handle({From, write_cache}, S) when From =:= self() -> end; handle({From, {log, Format, B}}=Message, S) -> case get(log) of - L when L#log.mode =:= read_only -> + #log{mode = read_only}=L -> reply(From, {error, {read_only_mode, L#log.name}}, S); - L when L#log.status =:= ok, L#log.format =:= external, Format =:= internal -> + #log{status = ok, format=external}=L when Format =:= internal -> reply(From, {error, {format_external, L#log.name}}, S); - L when L#log.status =:= ok -> + #log{status = ok} -> log_loop(S, From, [B], []); - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> enqueue(Message, S) end; handle({alog, Format, B}=Message, S) -> case get(log) of - L when L#log.mode =:= read_only -> + #log{mode = read_only} -> notify_owners({read_only,B}), loop(S); - L when L#log.status =:= ok, L#log.format =:= external, Format =:= internal -> + #log{status = ok, format = external} when Format =:= internal -> notify_owners({format_external, B}), loop(S); - L when L#log.status =:= ok -> + #log{status = ok} -> log_loop(S, [], [B], []); - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}} -> notify_owners({blocked_log, B}), loop(S); _ -> @@ -717,21 +716,21 @@ handle({alog, Format, B}=Message, S) -> end; handle({From, {block, QueueLogRecs}}=Message, S) -> case get(log) of - L when L#log.status =:= ok -> + #log{status = ok}=L -> do_block(From, QueueLogRecs, L), reply(From, ok, S); - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> enqueue(Message, S) end; handle({From, unblock}, S) -> case get(log) of - L when L#log.status =:= ok -> + #log{status = ok}=L -> reply(From, {error, {not_blocked, L#log.name}}, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> S2 = do_unblock(L, S), reply(From, ok, S2); L -> @@ -739,24 +738,24 @@ handle({From, unblock}, S) -> end; handle({From, sync}=Message, S) -> case get(log) of - L when L#log.mode =:= read_only -> + #log{mode = read_only}=L -> reply(From, {error, {read_only_mode, L#log.name}}, S); - L when L#log.status =:= ok -> + #log{status = ok} -> log_loop(S, [], [], [From]); - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> enqueue(Message, S) end; handle({From, {truncate, Head, F, A}}=Message, S) -> case get(log) of - L when L#log.mode =:= read_only -> + #log{mode = read_only}=L -> reply(From, {error, {read_only_mode, L#log.name}}, S); - L when L#log.status =:= ok, S#state.cache_error =/= ok -> + #log{status = ok} when S#state.cache_error =/= ok -> loop(cache_error(S, [From])); - L when L#log.status =:= ok -> + #log{status = ok}=L -> H = merge_head(Head, L#log.head), case catch do_trunc(L, H) of ok -> @@ -767,46 +766,46 @@ handle({From, {truncate, Head, F, A}}=Message, S) -> Error -> do_exit(S, From, Error, ?failure(Error, F, A)) end; - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> enqueue(Message, S) end; handle({From, {chunk, Pos, B, N}}=Message, S) -> case get(log) of - L when L#log.status =:= ok, S#state.cache_error =/= ok -> + #log{status = ok} when S#state.cache_error =/= ok -> loop(cache_error(S, [From])); - L when L#log.status =:= ok -> + #log{status = ok}=L -> R = do_chunk(L, Pos, B, N), reply(From, R, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> R = do_chunk(L, Pos, B, N), reply(From, R, S); - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _L -> enqueue(Message, S) end; handle({From, {chunk_step, Pos, N}}=Message, S) -> case get(log) of - L when L#log.status =:= ok, S#state.cache_error =/= ok -> + #log{status = ok} when S#state.cache_error =/= ok -> loop(cache_error(S, [From])); - L when L#log.status =:= ok -> + #log{status = ok}=L -> R = do_chunk_step(L, Pos, N), reply(From, R, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> R = do_chunk_step(L, Pos, N), reply(From, R, S); - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> enqueue(Message, S) end; handle({From, {change_notify, Pid, NewNotify}}=Message, S) -> case get(log) of - L when L#log.status =:= ok -> + #log{status = ok}=L -> case do_change_notify(L, Pid, NewNotify) of {ok, L1} -> put(log, L1), @@ -814,37 +813,37 @@ handle({From, {change_notify, Pid, NewNotify}}=Message, S) -> Error -> reply(From, Error, S) end; - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> enqueue(Message, S) end; handle({From, {change_header, NewHead}}=Message, S) -> case get(log) of - L when L#log.mode =:= read_only -> + #log{mode = read_only}=L -> reply(From, {error, {read_only_mode, L#log.name}}, S); - L when L#log.status =:= ok -> - case check_head(NewHead, L#log.format) of + #log{status = ok, format = Format}=L -> + case check_head(NewHead, Format) of {ok, Head} -> - put(log, L#log{head = mk_head(Head, L#log.format)}), + put(log, L#log{head = mk_head(Head, Format)}), reply(From, ok, S); Error -> reply(From, Error, S) end; - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> enqueue(Message, S) end; handle({From, {change_size, NewSize}}=Message, S) -> case get(log) of - L when L#log.mode =:= read_only -> + #log{mode = read_only}=L -> reply(From, {error, {read_only_mode, L#log.name}}, S); - L when L#log.status =:= ok -> + #log{status = ok}=L -> case check_size(L#log.type, NewSize) of ok -> case catch do_change_size(L, NewSize) of % does the put @@ -861,22 +860,22 @@ handle({From, {change_size, NewSize}}=Message, S) -> not_ok -> reply(From, {error, {badarg, size}}, S) end; - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> enqueue(Message, S) end; handle({From, inc_wrap_file}=Message, S) -> case get(log) of - L when L#log.mode =:= read_only -> + #log{mode = read_only}=L -> reply(From, {error, {read_only_mode, L#log.name}}, S); - L when L#log.type =:= halt -> + #log{type = halt}=L -> reply(From, {error, {halt_log, L#log.name}}, S); - L when L#log.status =:= ok, S#state.cache_error =/= ok -> + #log{status = ok} when S#state.cache_error =/= ok -> loop(cache_error(S, [From])); - L when L#log.status =:= ok -> + #log{status = ok}=L -> case catch do_inc_wrap_file(L) of {ok, L2, Lost} -> put(log, L2), @@ -886,20 +885,22 @@ handle({From, inc_wrap_file}=Message, S) -> put(log, L2), reply(From, Error, state_err(S, Error)) end; - L when L#log.status =:= {blocked, false} -> + #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); - L when L#log.blocked_by =:= From -> + #log{blocked_by = From}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); _ -> enqueue(Message, S) end; handle({From, {reopen, NewFile, Head, F, A}}, S) -> case get(log) of - L when L#log.mode =:= read_only -> + #log{mode = read_only}=L -> reply(From, {error, {read_only_mode, L#log.name}}, S); - L when L#log.status =:= ok, S#state.cache_error =/= ok -> + #log{status = ok} when S#state.cache_error =/= ok -> loop(cache_error(S, [From])); - L when L#log.status =:= ok, L#log.filename =/= NewFile -> + #log{status = ok, filename = NewFile}=L -> + reply(From, {error, {same_file_name, L#log.name}}, S); + #log{status = ok}=L -> case catch close_disk_log2(L) of closed -> File = L#log.filename, @@ -932,8 +933,6 @@ handle({From, {reopen, NewFile, Head, F, A}}, S) -> Error -> do_exit(S, From, Error, ?failure(Error, F, A)) end; - L when L#log.status =:= ok -> - reply(From, {error, {same_file_name, L#log.name}}, S); L -> reply(From, {error, {blocked_log, L#log.name}}, S) end; @@ -971,11 +970,11 @@ handle({From, close}, S) -> end; handle({From, info}, S) -> reply(From, do_info(get(log), S#state.cnt), S); -handle({'EXIT', From, Reason}, S) when From =:= S#state.parent -> +handle({'EXIT', From, Reason}, #state{parent=From}=S) -> %% Parent orders shutdown. _ = do_stop(S), exit(Reason); -handle({'EXIT', From, Reason}, S) when From =:= S#state.server -> +handle({'EXIT', From, Reason}, #state{server=From}=S) -> %% The server is gone. _ = do_stop(S), exit(Reason); @@ -1000,8 +999,8 @@ handle({system, From, Req}, S) -> handle(_, S) -> loop(S). -enqueue(Message, S) -> - loop(S#state{queue = [Message | S#state.queue]}). +enqueue(Message, #state{queue = Queue}=S) -> + loop(S#state{queue = [Message | Queue]}). %% Collect further log and sync requests already in the mailbox or queued @@ -1045,17 +1044,17 @@ log_loop(Message, Pids, Bins, Sync, Sz, _F, S) -> log_end(S, [], [], Sync, _Sz) -> log_end_sync(S, Sync); -log_end(S, Pids, Bins, Sync, Sz) -> +log_end(#state{cnt = Cnt}=S, Pids, Bins, Sync, Sz) -> case do_log(get(log), rflat(Bins), Sz) of N when is_integer(N) -> ok = replies(Pids, ok), - S1 = (state_ok(S))#state{cnt = S#state.cnt+N}, + S1 = (state_ok(S))#state{cnt = Cnt + N}, log_end_sync(S1, Sync); {error, {error, {full, _Name}}, N} when Pids =:= [] -> - log_end_sync(state_ok(S#state{cnt = S#state.cnt + N}), Sync); + log_end_sync(state_ok(S#state{cnt = Cnt + N}), Sync); {error, Error, N} -> ok = replies(Pids, Error), - state_err(S#state{cnt = S#state.cnt + N}, Error) + state_err(S#state{cnt = Cnt + N}, Error) end. %% Inlined. @@ -1106,17 +1105,17 @@ close_owner(Pid, L, S) -> S2 = do_unblock(Pid, get(log), S), unlink(Pid), do_close2(L1, S2). - + %% -> {stop, S} | {continue, S} -close_user(Pid, L, S) when L#log.users > 0 -> - L1 = L#log{users = L#log.users - 1}, +close_user(Pid, #log{users=Users}=L, S) when Users > 0 -> + L1 = L#log{users = Users - 1}, put(log, L1), S2 = do_unblock(Pid, get(log), S), do_close2(L1, S2); close_user(_Pid, _L, S) -> {continue, S}. -do_close2(L, S) when L#log.users =:= 0, L#log.owners =:= [] -> +do_close2(#log{users = 0, owners = []}, S) -> {stop, S}; do_close2(_L, S) -> {continue, S}. @@ -1195,14 +1194,14 @@ add_pid(Pid, Notify, L) when is_pid(Pid) -> add_pid(_NotAPid, _Notify, L) -> {ok, L#log{users = L#log.users + 1}}. -unblock_pid(L) when L#log.blocked_by =:= none -> +unblock_pid(#log{blocked_by = none}) -> ok; -unblock_pid(L) -> - case is_owner(L#log.blocked_by, L) of +unblock_pid(#log{blocked_by = Pid}=L) -> + case is_owner(Pid, L) of {true, _Notify} -> ok; false -> - unlink(L#log.blocked_by) + unlink(Pid) end. %% -> true | false @@ -1324,7 +1323,7 @@ ensure_binary(Bytes) -> %% Change size of the logs in runtime. %%----------------------------------------------------------------- %% -> ok | {big, CurSize} | throw(Error) -do_change_size(L, NewSize) when L#log.type =:= halt -> +do_change_size(#log{type = halt}=L, NewSize) -> Halt = L#log.extra, CurB = Halt#halt.curB, NewLog = L#log{extra = Halt#halt{size = NewSize}}, @@ -1340,7 +1339,7 @@ do_change_size(L, NewSize) when L#log.type =:= halt -> true -> {big, CurB} end; -do_change_size(L, NewSize) when L#log.type =:= wrap -> +do_change_size(#log{type = wrap}=L, NewSize) -> #log{extra = Extra, version = Version} = L, {ok, Handle} = disk_log_1:change_size_wrap(Extra, NewSize, Version), erase(is_full), @@ -1641,7 +1640,7 @@ do_block(Pid, QueueLogRecs, L) -> link(Pid) end. -do_unblock(Pid, L, S) when L#log.blocked_by =:= Pid -> +do_unblock(Pid, #log{blocked_by = Pid}=L, S) -> do_unblock(L, S); do_unblock(_Pid, _L, S) -> S. @@ -1662,7 +1661,7 @@ do_unblock(L, S) -> do_log(L, B) -> do_log(L, B, iolist_size(B)). -do_log(L, B, BSz) when L#log.type =:= halt -> +do_log(#log{type = halt}=L, B, BSz) -> #log{format = Format, extra = Halt} = L, #halt{curB = CurSize, size = Sz} = Halt, {Bs, BSize} = logl(B, Format, BSz), @@ -1674,7 +1673,7 @@ do_log(L, B, BSz) when L#log.type =:= halt -> undefined -> halt_write_full(L, B, Format, 0) end; -do_log(L, B, _BSz) when L#log.format_type =:= wrap_int -> +do_log(#log{format_type = wrap_int}=L, B, _BSz) -> case disk_log_1:mf_int_log(L#log.extra, B, L#log.head) of {ok, Handle, Logged, Lost, Wraps} -> notify_owners_wrap(Wraps), @@ -1687,7 +1686,7 @@ do_log(L, B, _BSz) when L#log.format_type =:= wrap_int -> put(log, L#log{extra = Handle}), {error, Error, Logged - Lost} end; -do_log(L, B, _BSz) when L#log.format_type =:= wrap_ext -> +do_log(#log{format_type = wrap_ext}=L, B, _BSz) -> case disk_log_1:mf_ext_log(L#log.extra, B, L#log.head) of {ok, Handle, Logged, Lost, Wraps} -> notify_owners_wrap(Wraps), @@ -1762,7 +1761,7 @@ do_sync(#log{type = wrap, extra = Handle} = Log) -> Reply. %% -> ok | Error | throw(Error) -do_trunc(L, Head) when L#log.type =:= halt -> +do_trunc(#log{type = halt}=L, Head) -> #log{filename = FName, extra = Halt} = L, FdC = Halt#halt.fdc, {Reply1, FdC2} = @@ -1791,7 +1790,7 @@ do_trunc(L, Head) when L#log.type =:= halt -> end, put(log, L#log{extra = NewHalt}), Reply; -do_trunc(L, Head) when L#log.type =:= wrap -> +do_trunc(#log{type = wrap}=L, Head) -> Handle = L#log.extra, OldHead = L#log.head, {MaxB, MaxF} = disk_log_1:get_wrap_size(Handle), @@ -1985,8 +1984,7 @@ notify_owners(Note) -> (_) -> ok end, L#log.owners). -cache_error(S, Pids) -> - Error = S#state.cache_error, +cache_error(#state{cache_error=Error}=S, Pids) -> ok = replies(Pids, Error), state_err(S#state{cache_error = ok}, Error). -- cgit v1.2.3 From eda5c4859f561fae7d3a3b74f19dd8596c212966 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 1 Nov 2016 15:36:57 +0100 Subject: Improve caching in disk_log Avoid starting timers for flushing when the written data is empty or larger than the max cache size. Previously, a single huge write to an empty cache would be put in the cache until the next write or the timer event. Also increase the cache size from 16K to 64K. --- lib/kernel/src/disk_log.hrl | 1 + lib/kernel/src/disk_log_1.erl | 32 ++++++++++++++++++++++---------- lib/kernel/test/disk_log_SUITE.erl | 4 ++-- 3 files changed, 25 insertions(+), 12 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index 3cf8a3b3a2..593dbb31ab 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.hrl @@ -39,6 +39,7 @@ -define(MAX_FILES, 65000). -define(MAX_BYTES, ((1 bsl 64) - 1)). -define(MAX_CHUNK_SIZE, 65536). +-define(MAX_FWRITE_CACHE, 65536). %% Object defines -define(LOGMAGIC, <<1,2,3,4>>). diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl index 2e61363aa6..d83c30f35f 100644 --- a/lib/kernel/src/disk_log_1.erl +++ b/lib/kernel/src/disk_log_1.erl @@ -1416,24 +1416,36 @@ open_truncate(FileName) -> %%% Functions that access files, and throw on error. --define(MAX, 16384). % bytes -define(TIMEOUT, 2000). % ms %% -> {Reply, cache()}; Reply = ok | Error -fwrite(#cache{c = []} = FdC, _FN, B, Size) -> +fwrite(FdC, _FN, _B, 0) -> + {ok, FdC}; % avoid starting a timer for empty writes +fwrite(#cache{fd = Fd, c = C, sz = Sz} = FdC, FileName, B, Size) -> + Sz1 = Sz + Size, + C1 = cache_append(C, B), + if Sz1 > ?MAX_FWRITE_CACHE -> + write_cache(Fd, FileName, C1); + true -> + maybe_start_timer(C), + {ok, FdC#cache{sz = Sz1, c = C1}} + end. + +cache_append([], B) -> B; +cache_append(C, B) -> [C | B]. + +%% if the cache was empty, start timer (unless it's already running) +maybe_start_timer([]) -> case get(write_cache_timer_is_running) of - true -> + true -> ok; - _ -> + _ -> put(write_cache_timer_is_running, true), erlang:send_after(?TIMEOUT, self(), {self(), write_cache}), ok - end, - {ok, FdC#cache{sz = Size, c = B}}; -fwrite(#cache{sz = Sz, c = C} = FdC, _FN, B, Size) when Sz < ?MAX -> - {ok, FdC#cache{sz = Sz+Size, c = [C | B]}}; -fwrite(#cache{fd = Fd, c = C}, FileName, B, _Size) -> - write_cache(Fd, FileName, [C | B]). + end; +maybe_start_timer(_C) -> + ok. fwrite_header(Fd, B, Size) -> {ok, #cache{fd = Fd, sz = Size, c = B}}. diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index a25b315d9d..23fe975ef7 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -4666,7 +4666,7 @@ other_groups(Conf) when is_list(Conf) -> ok. --define(MAX, 16384). % MAX in disk_log_1.erl +-define(MAX, ?MAX_FWRITE_CACHE). % as in disk_log_1.erl %% Evil cases such as closed file descriptor port. evil(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), @@ -4690,7 +4690,7 @@ evil(Conf) when is_list(Conf) -> {size,?MAX+50},{format,external}]), [Fd] = erlang:ports() -- Ports0, {B,_} = x_mk_bytes(30), - ok = disk_log:blog(Log, <<0:(?MAX+1)/unit:8>>), + ok = disk_log:blog(Log, <<0:(?MAX-1)/unit:8>>), exit(Fd, kill), {error, {file_error,_,einval}} = disk_log:blog_terms(Log, [B,B]), ok= disk_log:close(Log), -- cgit v1.2.3 From 93ac8d2b4b2937b9b7651b5e043c31929f3b2c7c Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Fri, 25 Nov 2016 21:26:19 +0100 Subject: Pass log format through from handle() --- lib/kernel/src/disk_log.erl | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 69c65c9c43..2ade7fd77a 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -689,8 +689,8 @@ handle({From, {log, Format, B}}=Message, S) -> reply(From, {error, {read_only_mode, L#log.name}}, S); #log{status = ok, format=external}=L when Format =:= internal -> reply(From, {error, {format_external, L#log.name}}, S); - #log{status = ok} -> - log_loop(S, From, [B], []); + #log{status = ok, format=LogFormat} -> + log_loop(S, From, [B], [], iolist_size(B), LogFormat); #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); #log{blocked_by = From}=L -> @@ -706,8 +706,8 @@ handle({alog, Format, B}=Message, S) -> #log{status = ok, format = external} when Format =:= internal -> notify_owners({format_external, B}), loop(S); - #log{status = ok} -> - log_loop(S, [], [B], []); + #log{status = ok, format=LogFormat} -> + log_loop(S, [], [B], [], iolist_size(B), LogFormat); #log{status = {blocked, false}} -> notify_owners({blocked_log, B}), loop(S); @@ -740,8 +740,8 @@ handle({From, sync}=Message, S) -> case get(log) of #log{mode = read_only}=L -> reply(From, {error, {read_only_mode, L#log.name}}, S); - #log{status = ok} -> - log_loop(S, [], [], [From]); + #log{status = ok, format=LogFormat} -> + log_loop(S, [], [], [From], 0, LogFormat); #log{status = {blocked, false}}=L -> reply(From, {error, {blocked_log, L#log.name}}, S); #log{blocked_by = From}=L -> @@ -1006,9 +1006,6 @@ enqueue(Message, #state{queue = Queue}=S) -> -define(MAX_LOOK_AHEAD, 64*1024). -log_loop(S, Pids, Bins, Sync) -> - log_loop(S, Pids, Bins, Sync, iolist_size(Bins), (get(log))#log.format). - %% Inlined. log_loop(#state{cache_error = CE}=S, Pids, _Bins, _Sync, _Sz, _F) when CE =/= ok -> loop(cache_error(S, Pids)); -- cgit v1.2.3 From 3eddb0f762de248d3230b38bc9d478bfbc8e7331 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 7 Dec 2016 13:15:31 +0100 Subject: Update copyright-year --- lib/kernel/src/global_group.erl | 2 +- lib/kernel/src/inet_tcp_dist.erl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/global_group.erl b/lib/kernel/src/global_group.erl index 8ac0bd9551..f5ead2a4c5 100644 --- a/lib/kernel/src/global_group.erl +++ b/lib/kernel/src/global_group.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2015. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl index 3084bd599a..8c8fe86811 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-2015. All Rights Reserved. +%% Copyright Ericsson AB 1997-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. -- cgit v1.2.3 From fc0427be6d482182ec70f3cd87c73027cfb17ea9 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 9 Dec 2016 11:45:22 +0100 Subject: Prepare release --- lib/kernel/doc/src/notes.xml | 33 +++++++++++++++++++++++++++++++++ lib/kernel/vsn.mk | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 5bcc0b7c09..9277c2d353 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,39 @@

This document describes the changes made to the Kernel application.

+
Kernel 5.1.1 + +
Fixed Bugs and Malfunctions + + +

+ code:add_pathsa/1 and command line option + -pa both revert the given list of directories when + adding it at the beginning of the code path. This is now + documented.

+

+ Own Id: OTP-13920 Aux Id: ERL-267

+
+ +

+ Add lost runtime dependency to erts-8.1. This should have + been done in kernel-5.1 (OTP-19.1) as it cannot run + without at least erts-8.1 (OTP-19.1).

+

+ Own Id: OTP-14003

+
+ +

+ Type and doc for gen_{tcp,udp,sctp}:controlling_process/2 + has been improved.

+

+ Own Id: OTP-14022 Aux Id: PR-1208

+
+
+
+ +
+
Kernel 5.1
Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index d3b2d18ae5..8d2517e680 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.1 +KERNEL_VSN = 5.1.1 -- cgit v1.2.3 From 68728bb7fb82331c1aa7aeee71a971de842eff0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 11 Jan 2017 13:21:33 +0100 Subject: seq_trace: Remove superfluous reference to R3B MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Loïc Hoguin --- lib/kernel/doc/src/seq_trace.xml | 6 ------ 1 file changed, 6 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml index ba7259219d..b80e87c118 100644 --- a/lib/kernel/doc/src/seq_trace.xml +++ b/lib/kernel/doc/src/seq_trace.xml @@ -427,12 +427,6 @@ prev_cnt := tcurr built with Erl_Interface only maintains one trace token, which means that the C-node appears as one process from the sequential tracing point of view.

-

To be able to perform sequential tracing between - distributed Erlang nodes, the distribution protocol has been - extended (in a backward compatible way). An Erlang node - supporting sequential tracing can communicate with an older - (Erlang/OTP R3B) node but messages passed within that node can - not be traced.

-- cgit v1.2.3 From 5056a16cfcfdcdcb1b48e24936f12a70269dcf02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 11 Jan 2017 13:24:12 +0100 Subject: code.xml: Remove superfluous reference to R12B --- lib/kernel/doc/src/code.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index f881fd76fd..878a450f0f 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -258,7 +258,7 @@ zip:create("mnesia-4.4.7.ez", both strings and atoms, but a future release will probably only allow the arguments that are documented.

-

As from Erlang/OTP R12B, functions in this module generally fail with an +

Functions in this module generally fail with an exception if they are passed an incorrect type (for example, an integer or a tuple where an atom is expected). An error tuple is returned if the argument type is correct, but there are some other errors (for example, a non-existing directory -- cgit v1.2.3 From b69086df7487e74879de6b6f027df6507ec4fc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 11 Jan 2017 14:13:49 +0100 Subject: config.xml: Remove superfluous reference to R10B --- lib/kernel/doc/src/config.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/config.xml b/lib/kernel/doc/src/config.xml index c5f37fd036..c10f11b187 100644 --- a/lib/kernel/doc/src/config.xml +++ b/lib/kernel/doc/src/config.xml @@ -77,8 +77,8 @@ to update the application configurations.

This means that specifying another .config file, or more .config files, leads to inconsistent update of application - configurations. Therefore, in Erlang 5.4/OTP R10B, the syntax of - sys.config was extended to allow pointing out other + configurations. There is, however, a syntax for + sys.config that allows pointing out other .config files:

[{Application, [{Par, Val}]} | File]. -- cgit v1.2.3 From 5aff60d96efac96a41b514ed167f13eb787a415f Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 26 Sep 2016 17:05:50 +0200 Subject: Support for dirty BIFs --- lib/kernel/src/erts_debug.erl | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index 7b3f1e313a..ad92aafc2f 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -35,7 +35,8 @@ dump_monitors/1, dump_links/1, flat_size/1, get_internal_state/1, instructions/0, lock_counters/1, map_info/1, same/2, set_internal_state/2, - size_shared/1, copy_shared/1]). + size_shared/1, copy_shared/1, dirty_cpu/2, dirty_io/2, + dirty/3]). -spec breakpoint(MFA, Flag) -> non_neg_integer() when MFA :: {Module :: module(), @@ -182,6 +183,28 @@ same(_, _) -> set_internal_state(_, _) -> erlang:nif_error(undef). +-spec dirty_cpu(Term1, Term2) -> term() when + Term1 :: term(), + Term2 :: term(). + +dirty_cpu(_, _) -> + erlang:nif_error(undef). + +-spec dirty_io(Term1, Term2) -> term() when + Term1 :: term(), + Term2 :: term(). + +dirty_io(_, _) -> + erlang:nif_error(undef). + +-spec dirty(Term1, Term2, Term3) -> term() when + Term1 :: term(), + Term2 :: term(), + Term3 :: term(). + +dirty(_, _, _) -> + erlang:nif_error(undef). + %%% End of BIFs %% size(Term) -- cgit v1.2.3 From a7b52ad679e6a58a9351a26e198eee70067b000f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 13 Apr 2015 18:47:06 +0200 Subject: kernel: Add gen_event signal server and default handler --- lib/kernel/src/Makefile | 1 + lib/kernel/src/erl_signal_handler.erl | 47 +++++++++++++++++++++++++++++++++++ lib/kernel/src/kernel.app.src | 1 + lib/kernel/src/kernel.erl | 13 +++++++++- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 lib/kernel/src/erl_signal_handler.erl (limited to 'lib/kernel') diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile index 2b72f78dcf..2a89faaf13 100644 --- a/lib/kernel/src/Makefile +++ b/lib/kernel/src/Makefile @@ -71,6 +71,7 @@ MODULES = \ erl_distribution \ erl_epmd \ erl_reply \ + erl_signal_handler \ erts_debug \ error_handler \ error_logger \ diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl new file mode 100644 index 0000000000..6bd8f992a7 --- /dev/null +++ b/lib/kernel/src/erl_signal_handler.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(erl_signal_handler). +-behaviour(gen_event). +-export([init/1, format_status/2, + handle_event/2, handle_call/2, handle_info/2, + terminate/2, code_change/3]). + +-record(state,{}). + +init(_Args) -> + {ok, #state{}}. + +handle_event(_SignalMsg, S) -> + {ok, S}. + +handle_info(_Info, S) -> + {ok, S}. + +handle_call(_Request, S) -> + {ok, ok, S}. + +format_status(_Opt, [_Pdict,_S]) -> + ok. + +code_change(_OldVsn, S, _Extra) -> + {ok, S}. + +terminate(_Args, _S) -> + ok. diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 4d08a55c7c..25e4ddd95c 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -34,6 +34,7 @@ erl_boot_server, erl_distribution, erl_reply, + erl_signal_handler, error_handler, error_logger, file, diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl index 3d0ef81318..59eca242b1 100644 --- a/lib/kernel/src/kernel.erl +++ b/lib/kernel/src/kernel.erl @@ -32,6 +32,14 @@ start(_, []) -> case supervisor:start_link({local, kernel_sup}, kernel, []) of {ok, Pid} -> + %% add signal handler + case whereis(erl_signal_server) of + %% in case of minimal mode + undefined -> ok; + _ -> + ok = gen_event:add_handler(erl_signal_server, erl_signal_handler, []) + end, + %% add error handler Type = get_error_logger_type(), case error_logger:swap_handler(Type) of ok -> {ok, Pid, []}; @@ -131,6 +139,9 @@ init([]) -> permanent, 2000, worker, [inet_db]}, NetSup = {net_sup, {erl_distribution, start_link, []}, permanent, infinity, supervisor,[erl_distribution]}, + SigSrv = #{id => erl_signal_server, + start => {gen_event, start_link, [{local, erl_signal_server}]}, + type => worker, restart => permanent, shutdown => 2000, modules => dynamic}, DistAC = start_dist_ac(), Timer = start_timer(), @@ -141,7 +152,7 @@ init([]) -> permanent, infinity, supervisor, [?MODULE]}, {ok, {SupFlags, [Code, Rpc, Global, InetDb | DistAC] ++ - [NetSup, Glo_grp, File, + [NetSup, Glo_grp, File, SigSrv, StdError, User, Config, SafeSupervisor] ++ Timer}} end; init(safe) -> -- cgit v1.2.3 From 40c82769def0cfa59e75669ff1c6fc4abcecd764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 15 Dec 2016 18:07:13 +0100 Subject: erts: Handle SIGTERM via signal service instead --- lib/kernel/src/erl_signal_handler.erl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl index 6bd8f992a7..04130eac66 100644 --- a/lib/kernel/src/erl_signal_handler.erl +++ b/lib/kernel/src/erl_signal_handler.erl @@ -28,6 +28,10 @@ init(_Args) -> {ok, #state{}}. +handle_event(sigterm, S) -> + error_logger:info_msg("SIGTERM received - shutting down~n"), + ok = init:stop(), + {ok, S}; handle_event(_SignalMsg, S) -> {ok, S}. -- cgit v1.2.3 From 2d3bf84d8167b50728b0a5411a4e2dfa71d52c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 16 Dec 2016 12:24:13 +0100 Subject: erts: Handle SIGUSR1 via signal service instead --- lib/kernel/src/erl_signal_handler.erl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl index 04130eac66..43cc307ffd 100644 --- a/lib/kernel/src/erl_signal_handler.erl +++ b/lib/kernel/src/erl_signal_handler.erl @@ -28,6 +28,9 @@ init(_Args) -> {ok, #state{}}. +handle_event(sigusr1, S) -> + erlang:halt("Received SIGUSR1"), + {ok, S}; handle_event(sigterm, S) -> error_logger:info_msg("SIGTERM received - shutting down~n"), ok = init:stop(), -- cgit v1.2.3 From 26b59dfe67ef551cd94765557cdd8c79794bcc38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 31 May 2016 14:28:54 +0200 Subject: Add new AtU8 beam chunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new chunk stores atoms encoded in UTF-8. beam_lib has also been modified to handle the new 'utf8_atoms' attribute while the 'atoms' attribute may be a missing chunk from now on. The binary_to_atom/2 BIF can now encode any utf8 binary with up to 255 characters. The list_to_atom/1 BIF can now accept codepoints higher than 255 with up to 255 characters (thanks to Björn Gustavsson). --- lib/kernel/test/code_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 4914ce9e4c..f368232bfc 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -323,7 +323,7 @@ load_abs(Config) when is_list(Config) -> {error, nofile} = code:load_abs(TestDir ++ "/duuuumy_mod"), {error, badfile} = code:load_abs(TestDir ++ "/code_a_test"), {'EXIT', _} = (catch code:load_abs({})), - {'EXIT', _} = (catch code:load_abs("Non-latin-имя-файла")), + {error, nofile} = code:load_abs("Non-latin-имя-файла"), {module, code_b_test} = code:load_abs(TestDir ++ "/code_b_test"), code:stick_dir(TestDir), {error, sticky_directory} = code:load_abs(TestDir ++ "/code_b_test"), -- cgit v1.2.3 From c02ea6ca5154f6f9f2fa4cc89ab70077df0dd66b Mon Sep 17 00:00:00 2001 From: pulitta Date: Wed, 14 Dec 2016 18:23:24 +0300 Subject: file: match enoent and enotdir in path_open --- lib/kernel/src/file.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 58b601e456..6d94f7770f 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -1413,7 +1413,7 @@ path_open_first([Path|Rest], Name, Mode, LastError) -> case open(FileName, Mode) of {ok, Fd} -> {ok, Fd, FileName}; - {error, enoent} -> + {error, Reason} when Reason =:= enoent; Reason =:= enotdir -> path_open_first(Rest, Name, Mode, LastError); Error -> Error -- cgit v1.2.3 From 120f04387ade07ef5b8b6d20a04de7d21e0c40ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 5 Jan 2017 17:17:52 +0100 Subject: erts: Use generic signal handler --- lib/kernel/src/erl_signal_handler.erl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl index 43cc307ffd..8f924d2adc 100644 --- a/lib/kernel/src/erl_signal_handler.erl +++ b/lib/kernel/src/erl_signal_handler.erl @@ -31,6 +31,9 @@ init(_Args) -> handle_event(sigusr1, S) -> erlang:halt("Received SIGUSR1"), {ok, S}; +handle_event(sigquit, S) -> + erlang:halt(), + {ok, S}; handle_event(sigterm, S) -> error_logger:info_msg("SIGTERM received - shutting down~n"), ok = init:stop(), -- cgit v1.2.3 From d4bd17da9759af54227891a90d9fb83d5bfe6d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 24 Jan 2017 10:59:30 +0100 Subject: erts: Use os module instead of erts_internal for set_signal/2 * Add specs * Change return signature to 'ok' instead of 'true' --- lib/kernel/src/os.erl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index f8519d3a5e..c3ffcb3f70 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -29,7 +29,7 @@ -export([getenv/0, getenv/1, getenv/2, getpid/0, perf_counter/0, perf_counter/1, - putenv/2, system_time/0, system_time/1, + putenv/2, set_signal/2, system_time/0, system_time/1, timestamp/0, unsetenv/1]). -spec getenv() -> [string()]. @@ -104,6 +104,15 @@ timestamp() -> unsetenv(_) -> erlang:nif_error(undef). +-spec set_signal(Signal, Option) -> 'ok' when + Signal :: 'sighup' | 'sigquit' | 'sigabrt' | 'sigalrm' | + 'sigterm' | 'sigusr1' | 'sigusr2' | 'sigchld' | + 'sigstop' | 'sigtstp', + Option :: 'default' | 'handle' | 'ignore'. + +set_signal(_Signal, _Option) -> + erlang:nif_error(undef). + %%% End of BIFs -spec type() -> {Osfamily, Osname} when -- cgit v1.2.3 From 1409b6ae110f60c410e83d1923dd59ae3659a887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 1 Feb 2017 16:44:50 +0100 Subject: kernel: Document signal server --- lib/kernel/doc/src/kernel_app.xml | 59 +++++++++++++++++++++++++++++++++++++-- lib/kernel/doc/src/os.xml | 31 ++++++++++++++++++-- 2 files changed, 84 insertions(+), 6 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index df681a505f..c581fa9d1e 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -11,7 +11,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software @@ -19,7 +19,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - + kernel @@ -57,6 +57,60 @@ error_logger(3).

+
+ OS Signal Event Handler +

Asynchronous OS signals may be subscribed to via the Kernel applications event manager + (see OTP Design Principles and + gen_event(3)) registered as erl_signal_server. + A default signal handler is installed which handles the following signals:

+ + sigusr1 +

The default handler will halt Erlang and produce a crashdump + with slogan "Received SIGUSR1". + This is equivalent to calling erlang:halt("Received SIGUSR1"). +

+ + sigquit +

The default handler will halt Erlang immediately. + This is equivalent to calling erlang:halt(). +

+ + sigterm +

The default handler will terminate Erlang normally. + This is equivalent to calling init:stop(). +

+
+ +
+ Events +

Any event handler added to erl_signal_server must handle the following events.

+ + sighup +

Hangup detected on controlling terminal or death of controlling process

+ sigquit +

Quit from keyboard

+ sigabrt +

Abort signal from abort

+ sigalrm +

Timer signal from alarm

+ sigterm +

Termination signal

+ sigusr1 +

User-defined signal 1

+ sigusr2 +

User-defined signal 2

+ sigchld +

Child process stopped or terminated

+ sigstop +

Stop process

+ sigtstp +

Stop typed at terminal

+
+ +

Setting OS signals are described in os:set_signal/2.

+
+
+
Configuration

The following configuration parameters are defined for the Kernel @@ -405,4 +459,3 @@ MaxT = TickTime + TickTime / 4 timer(3)

- diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml index 739ac35d2a..6ba69d12a3 100644 --- a/lib/kernel/doc/src/os.xml +++ b/lib/kernel/doc/src/os.xml @@ -11,7 +11,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software @@ -19,7 +19,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - + os @@ -155,6 +155,32 @@ DirOut = os:cmd("dir"), % on Win32 platform + + + Enables or disables handling of OS signals. + +

Enables or disables OS signals.

+

Each signal my be set to one of the following options:

+ + ignore + + This signal will be ignored. + + + default + + This signal will use the default signal handler for the operating system. + + + handle + + This signal will notify erl_signal_server when it is received by + the Erlang runtime system. + + +
+
+ Current OS system time. @@ -296,4 +322,3 @@ calendar:now_to_universal_time(TS), - -- cgit v1.2.3 From 5f7f86be7bc7ec7a1c9b0042ff08254dca063d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 3 Feb 2017 13:27:09 +0100 Subject: Store messages for 'rex' and 'error_logger' off heap Performance for processes that receive huge amounts of messages can be increased by storing the incoming messages outside the heap (that avoids copying the message in a garbage collection). Two OTP processes that are known to receive many messages are 'rex' (used by 'rpc') and 'error_logger'. --- lib/kernel/src/error_logger.erl | 8 ++++++-- lib/kernel/src/rpc.erl | 14 ++++++++++++-- lib/kernel/test/error_logger_SUITE.erl | 13 ++++++++++++- lib/kernel/test/rpc_SUITE.erl | 12 ++++++++++-- 4 files changed, 40 insertions(+), 7 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index 3523f680a3..3ee8e2c6e6 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -360,8 +360,12 @@ init(Max) when is_integer(Max) -> %% go back. init({go_back, _PostState}) -> {ok, {?buffer_size, 0, []}}; -init(_) -> %% Start and just relay to other - {ok, []}. %% node if node(GLeader) =/= node(). +init(_) -> + %% The error logger process may receive a huge amount of + %% messages. Make sure that they are stored off heap to + %% avoid exessive GCs. + process_flag(message_queue_data, off_heap), + {ok, []}. -spec handle_event(term(), state()) -> {'ok', state()}. diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl index 21bff02214..bd6ea26678 100644 --- a/lib/kernel/src/rpc.erl +++ b/lib/kernel/src/rpc.erl @@ -67,17 +67,27 @@ %%------------------------------------------------------------------------ + +%% The rex server may receive a huge amount of +%% messages. Make sure that they are stored off heap to +%% avoid exessive GCs. + +-define(SPAWN_OPTS, [{spawn_opt,[{message_queue_data,off_heap}]}]). + %% Remote execution and broadcasting facility -spec start() -> {'ok', pid()} | 'ignore' | {'error', term()}. start() -> - gen_server:start({local,?NAME}, ?MODULE, [], []). + gen_server:start({local,?NAME}, ?MODULE, [], ?SPAWN_OPTS). -spec start_link() -> {'ok', pid()} | 'ignore' | {'error', term()}. start_link() -> - gen_server:start_link({local,?NAME}, ?MODULE, [], []). + %% The rex server process may receive a huge amount of + %% messages. Make sure that they are stored off heap to + %% avoid exessive GCs. + gen_server:start_link({local,?NAME}, ?MODULE, [], ?SPAWN_OPTS). -spec stop() -> term(). diff --git a/lib/kernel/test/error_logger_SUITE.erl b/lib/kernel/test/error_logger_SUITE.erl index b6e7551741..bb01c2384d 100644 --- a/lib/kernel/test/error_logger_SUITE.erl +++ b/lib/kernel/test/error_logger_SUITE.erl @@ -30,6 +30,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, + off_heap/1, error_report/1, info_report/1, error/1, info/1, emulator/1, tty/1, logfile/1, add/1, delete/1]). @@ -45,7 +46,7 @@ suite() -> {timetrap,{minutes,1}}]. all() -> - [error_report, info_report, error, info, emulator, tty, + [off_heap, error_report, info_report, error, info, emulator, tty, logfile, add, delete]. groups() -> @@ -66,6 +67,16 @@ end_per_group(_GroupName, Config) -> %%----------------------------------------------------------------- +off_heap(_Config) -> + %% The error_logger process may receive a huge amount of + %% messages. Make sure that they are stored off heap to + %% avoid exessive GCs. + MQD = message_queue_data, + {MQD,off_heap} = process_info(whereis(error_logger), MQD), + ok. + +%%----------------------------------------------------------------- + error_report(Config) when is_list(Config) -> error_logger:add_report_handler(?MODULE, self()), Rep1 = [{tag1,"data1"},{tag2,data2},{tag3,3}], diff --git a/lib/kernel/test/rpc_SUITE.erl b/lib/kernel/test/rpc_SUITE.erl index 1c72ddc87f..d76c4097d8 100644 --- a/lib/kernel/test/rpc_SUITE.erl +++ b/lib/kernel/test/rpc_SUITE.erl @@ -21,7 +21,8 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). --export([call/1, block_call/1, multicall/1, multicall_timeout/1, +-export([off_heap/1, + call/1, block_call/1, multicall/1, multicall_timeout/1, multicall_dies/1, multicall_node_dies/1, called_dies/1, called_node_dies/1, called_throws/1, call_benchmark/1, async_call/1]). @@ -35,7 +36,7 @@ suite() -> {timetrap,{minutes,2}}]. all() -> - [call, block_call, multicall, multicall_timeout, + [off_heap, call, block_call, multicall, multicall_timeout, multicall_dies, multicall_node_dies, called_dies, called_node_dies, called_throws, call_benchmark, async_call]. @@ -55,6 +56,13 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +off_heap(_Config) -> + %% The rex server process may receive a huge amount of + %% messages. Make sure that they are stored off heap to + %% avoid exessive GCs. + MQD = message_queue_data, + {MQD,off_heap} = process_info(whereis(rex), MQD), + ok. %% Test different rpc calls. -- cgit v1.2.3 From eab4b024957a27be018f8bc155bdd1dc05ec7969 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Thu, 19 Jan 2017 17:11:19 +0100 Subject: Document the kernel source_search_rules parameter --- lib/kernel/doc/src/kernel_app.xml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index df681a505f..0db3aa50c5 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -379,6 +379,28 @@ MaxT = TickTime + TickTime / 4 return as soon as possible for application_controller to terminate properly.

+ source_search_rules = [DirRule] | [SuffixRule] + + +

Where:

+ + DirRule = {ObjDirSuffix,SrcDirSuffix} + SuffixRule = {ObjSuffix,SrcSuffix,[DirRule]} + ObjDirSuffix = string() + SrcDirSuffix = string() + ObjSuffix = string() + SrcSuffix = string() + +

Specifies a list of rules for use by filelib:find_file/2 and + filelib:find_source/2. If this is set to some other value + than the empty list, it replaces the default rules. Rules can be + simple pairs of directory suffixes, such as {"ebin", + "src"}, which are used by filelib:find_file/2, or + triples specifying separate directory suffix rules depending on + file name extensions, for example [{".beam", ".erl", [{"ebin", + "src"}]}, which are used by filelib:find_source/2. Both + kinds of rules can be mixed in the list.

+
-- cgit v1.2.3 From 5a97997217e5c3f901e8fefbd7bbf6c64652c9a8 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 23 Jan 2017 17:07:23 +0100 Subject: Use magic refs for code loading state --- lib/kernel/src/code.erl | 12 ++++++------ lib/kernel/test/multi_load_SUITE.erl | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 5a7ca493cc..2a06d0cb15 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -489,13 +489,13 @@ prepare_check_uniq_1([], [_|_]=Errors) -> {error,Errors}. partition_on_load(Prep) -> - P = fun({_,{Bin,_,_}}) -> - erlang:has_prepared_code_on_load(Bin) + P = fun({_,{PC,_,_}}) -> + erlang:has_prepared_code_on_load(PC) end, lists:partition(P, Prep). verify_prepared([{M,{Prep,Name,_Native}}|T]) - when is_atom(M), is_binary(Prep), is_list(Name) -> + when is_atom(M), is_list(Name) -> try erlang:has_prepared_code_on_load(Prep) of false -> verify_prepared(T); @@ -562,10 +562,10 @@ prepare_loading_fun() -> GetNative = get_native_fun(), fun(Mod, FullName, Beam) -> case erlang:prepare_loading(Mod, Beam) of - Prepared when is_binary(Prepared) -> - {ok,{Prepared,FullName,GetNative(Beam)}}; {error,_}=Error -> - Error + Error; + Prepared -> + {ok,{Prepared,FullName,GetNative(Beam)}} end end. diff --git a/lib/kernel/test/multi_load_SUITE.erl b/lib/kernel/test/multi_load_SUITE.erl index 369e25ac64..920839f4f9 100644 --- a/lib/kernel/test/multi_load_SUITE.erl +++ b/lib/kernel/test/multi_load_SUITE.erl @@ -144,14 +144,14 @@ prep_magic([H|T]) -> prep_magic(Tuple) when is_tuple(Tuple) -> L = prep_magic(tuple_to_list(Tuple)), list_to_tuple(L); -prep_magic(Bin) when is_binary(Bin) -> - try erlang:has_prepared_code_on_load(Bin) of +prep_magic(Ref) when is_reference(Ref) -> + try erlang:has_prepared_code_on_load(Ref) of false -> - %% Create a different kind of magic binary. + %% Create a different kind of magic ref. ets:match_spec_compile([{'_',[true],['$_']}]) catch _:_ -> - Bin + Ref end; prep_magic(Other) -> Other. -- cgit v1.2.3 From ace8b57ec6be7292f7b6c27fa8eabeb8fe1c716b Mon Sep 17 00:00:00 2001 From: Juraj Hlista Date: Sat, 11 Feb 2017 16:41:07 +0000 Subject: Fix function name From camel case to snake case. --- lib/kernel/src/dist_ac.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/dist_ac.erl b/lib/kernel/src/dist_ac.erl index 6c2fa0b6b1..e63c969b79 100644 --- a/lib/kernel/src/dist_ac.erl +++ b/lib/kernel/src/dist_ac.erl @@ -123,7 +123,7 @@ load_application(AppName, DistNodes) -> gen_server:call(?DIST_AC, {load_application, AppName, DistNodes}, infinity). takeover_application(AppName, RestartType) -> - case validRestartType(RestartType) of + case valid_restart_type(RestartType) of true -> wait_for_sync_dacs(), Nodes = get_nodes(AppName), @@ -1514,10 +1514,10 @@ dist_del_node(Appls, Node) -> Appl#appl{run = NRun} end, Appls). -validRestartType(permanent) -> true; -validRestartType(temporary) -> true; -validRestartType(transient) -> true; -validRestartType(_RestartType) -> false. +valid_restart_type(permanent) -> true; +valid_restart_type(temporary) -> true; +valid_restart_type(transient) -> true; +valid_restart_type(_RestartType) -> false. dist_mismatch(AppName, Node) -> error_msg("Distribution mismatch for application \"~p\" on nodes ~p and ~p~n", -- cgit v1.2.3 From 517db4752997cf19e18c65302d21eed1f1eb6e1b Mon Sep 17 00:00:00 2001 From: Andrew Dryga Date: Sun, 12 Feb 2017 19:45:39 +0200 Subject: Fixed typos in lib/kernel --- lib/kernel/doc/src/notes.xml | 4 ++-- lib/kernel/include/inet.hrl | 2 +- lib/kernel/src/inet_parse.erl | 4 ++-- lib/kernel/src/inet_udp.erl | 6 +++--- lib/kernel/test/application_SUITE.erl | 2 +- lib/kernel/test/erl_distribution_SUITE.erl | 4 ++-- lib/kernel/test/erl_distribution_wb_SUITE.erl | 2 +- lib/kernel/test/file_SUITE.erl | 2 +- lib/kernel/test/file_SUITE_data/realmen.html | 4 ++-- 9 files changed, 15 insertions(+), 15 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 9277c2d353..d80c4f077c 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -108,7 +108,7 @@

Close stdin of commands run in os:cmd. This is a - backwards compatiblity fix that restores the behaviour of + backwards compatibility fix that restores the behaviour of pre 19.0 os:cmd.

Own Id: OTP-13867 Aux Id: seq13178

@@ -1445,7 +1445,7 @@ dependent, so applications aiming to be portable should consider using {ipv6_v6only,true} when creating an inet6 listening/destination socket, and if - neccesary also create an inet socket on the same + necessary also create an inet socket on the same port for IPv4 traffic. See the documentation.

Own Id: OTP-8928 Aux Id: kunagi-193 [104]

diff --git a/lib/kernel/include/inet.hrl b/lib/kernel/include/inet.hrl index b39df8c3f2..df788aca08 100644 --- a/lib/kernel/include/inet.hrl +++ b/lib/kernel/include/inet.hrl @@ -22,7 +22,7 @@ -record(hostent, { - h_name :: inet:hostname(), %% offical name of host + h_name :: inet:hostname(), %% official name of host h_aliases = [] :: [inet:hostname()], %% alias list h_addrtype :: 'inet' | 'inet6', %% host address type h_length :: non_neg_integer(), %% length of address diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl index b0a3ee3008..9b47199e08 100644 --- a/lib/kernel/src/inet_parse.erl +++ b/lib/kernel/src/inet_parse.erl @@ -701,8 +701,8 @@ dup(N, E, L) when is_integer(N), N >= 1 -> -%% Convert IPv4 adress to ascii -%% Convert IPv6 / IPV4 adress to ascii (plain format) +%% Convert IPv4 address to ascii +%% Convert IPv6 / IPV4 address to ascii (plain format) ntoa({A,B,C,D}) -> integer_to_list(A) ++ "." ++ integer_to_list(B) ++ "." ++ integer_to_list(C) ++ "." ++ integer_to_list(D); diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl index 8a8aa8ecca..c69791b9aa 100644 --- a/lib/kernel/src/inet_udp.erl +++ b/lib/kernel/src/inet_udp.erl @@ -113,7 +113,7 @@ fdopen(Fd, Opts) -> %% Here's how: %% Reverse the list. %% For each head option go through the tail and remove -%% all occurences of the same option from the tail. +%% all occurrences of the same option from the tail. %% Store that head option and iterate using the new tail. %% Return the list of stored head options. optuniquify(List) -> @@ -122,8 +122,8 @@ optuniquify(List) -> optuniquify([], Result) -> Result; optuniquify([Opt | Tail], Result) -> - %% Remove all occurences of Opt in Tail, - %% prepend Opt to Result, + %% Remove all occurrences of Opt in Tail, + %% prepend Opt to Result, %% then iterate back here. optuniquify(Opt, Tail, [], Result). diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl index 81407e9d96..b4cf31b210 100644 --- a/lib/kernel/test/application_SUITE.erl +++ b/lib/kernel/test/application_SUITE.erl @@ -1498,7 +1498,7 @@ otp_5363(Conf) when is_list(Conf) -> %% Ticket: OTP-5606 %% Slogan: Problems with starting a distributed application %%----------------------------------------------------------------- -%% Test of several processes simultanously starting the same +%% Test of several processes simultaneously starting the same %% distributed application. otp_5606(Conf) when is_list(Conf) -> diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index f630896e03..09c80a0956 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -233,7 +233,7 @@ time_ping(Node) -> erlang:convert_time_unit(T1 - T0, native, millisecond). %% Keep the connection with the client node up. -%% This is neccessary as the client node runs with much shorter +%% This is necessary as the client node runs with much shorter %% tick time !! keep_conn(Node) -> sleep(1), @@ -1059,7 +1059,7 @@ monitor_nodes_otp_6481_test(Config, TestType) when is_list(Config) -> RemotePid = spawn(Node, fun () -> receive after 1500 -> ok end, - %% infinit loop of msgs + %% infinite loop of msgs %% we want an endless stream of messages and the kill %% the node mercilessly. %% We then want to ensure that the nodedown message arrives diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl index 6a23ad0d11..61aa3b32ee 100644 --- a/lib/kernel/test/erl_distribution_wb_SUITE.erl +++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl @@ -30,7 +30,7 @@ %% 1) %% -%% Connections are now always set up symetrically with respect to +%% Connections are now always set up symmetrically with respect to %% publication. If connecting node doesn't send DFLAG_PUBLISHED %% the other node wont send DFLAG_PUBLISHED. If the connecting %% node send DFLAG_PUBLISHED but the other node doesn't send diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index f2094431d8..b402f01758 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -18,7 +18,7 @@ %% %CopyrightEnd% %% -%% This is a developement feature when developing a new file module, +%% This is a development feature when developing a new file module, %% ugly but practical. -ifndef(FILE_MODULE). -define(FILE_MODULE, file). diff --git a/lib/kernel/test/file_SUITE_data/realmen.html b/lib/kernel/test/file_SUITE_data/realmen.html index c810a5d088..92e13f23b8 100644 --- a/lib/kernel/test/file_SUITE_data/realmen.html +++ b/lib/kernel/test/file_SUITE_data/realmen.html @@ -237,7 +237,7 @@ destroy most of the interesting uses for EQUIVALENCE, and make it impossible to modify the operating system code with negative subscripts. Worst of all, bounds checking is inefficient. -
  • Source code maintainance systems. A Real Programmer keeps his +
  • Source code maintenance systems. A Real Programmer keeps his code locked up in a card file, because it implies that its owner cannot leave his important programs unguarded [5]. @@ -396,7 +396,7 @@ double stuff Oreos for special occasions.
  • Underneath the Oreos is a flow-charting template, left there by the previous occupant of the office. (Real Programmers write programs, -not documentation. Leave that to the maintainence people.) +not documentation. Leave that to the maintenance people.)

    -- cgit v1.2.3 From 44ab65763bbeb307a3431de284805325114a3d35 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 20 Feb 2017 10:31:42 +0100 Subject: kernel: Fail sticky_dir tc if module not sticky Running this test when for some reason stdlib has been unstickied could cause the emulator to die. So we check first to make sure that the expected files are sticky. --- lib/kernel/test/code_SUITE.erl | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index c5167efa56..5777b397b8 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -588,20 +588,28 @@ sticky_compiler(Files, PrivDir) -> [R || R <- Rets, R =/= ok]. do_sticky_compile(Mod, Dir) -> - %% Make sure that the module is loaded. A module being sticky - %% only prevents it from begin reloaded, not from being loaded - %% from the wrong place to begin with. - Mod = Mod:module_info(module), - File = filename:append(Dir, atom_to_list(Mod)), - Src = io_lib:format("-module(~s).\n" - "-export([test/1]).\n" - "test(me) -> fail.\n", [Mod]), - ok = file:write_file(File++".erl", Src), - case c:c(File, [{outdir,Dir}]) of - {ok,Module} -> - Module:test(me); - {error,sticky_directory} -> - ok + case code:is_sticky(Mod) of + true -> + %% Make sure that the module is loaded. A module being sticky + %% only prevents it from begin reloaded, not from being loaded + %% from the wrong place to begin with. + Mod = Mod:module_info(module), + File = filename:append(Dir, atom_to_list(Mod)), + Src = io_lib:format("-module(~s).\n" + "-export([test/1]).\n" + "test(me) -> fail.\n", [Mod]), + ok = file:write_file(File++".erl", Src), + case c:c(File, [{outdir,Dir}]) of + {ok,Module} -> + Module:test(me); + {error,sticky_directory} -> + ok + end; + false -> + %% For some reason the module is not sticky + %% could be that the .erlang file has + %% unstuck it? + {Mod, is_not_sticky} end. %% Test that the -pa and -pz options work as expected. -- cgit v1.2.3 From bf9f79e81530b37d5ac4abe1494f270986d92cb4 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 21 Feb 2017 10:34:13 +0100 Subject: kernel: Fix hanging os:cmd race condition If the port terminates before Port ! close is issued, there will be no 'closed' reply, so the old code would hang. As it turns out there is no way to figure out if a closed reply is supposed to come as that reply is sent after all links and monitors are triggered. So we have to use the synchronous port_close to close the port. --- lib/kernel/src/os.erl | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index f8519d3a5e..03d4324992 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -289,12 +289,11 @@ get_data(Port, MonRef, Eot, Sofar) -> more -> get_data(Port, MonRef, Eot, [Sofar,Bytes]); Last -> - Port ! {self(), close}, - flush_until_closed(Port), - flush_exit(Port), + catch port_close(Port), + flush_until_down(Port, MonRef), iolist_to_binary([Sofar, Last]) end; - {'DOWN', MonRef, _, _ , _} -> + {'DOWN', MonRef, _, _, _} -> flush_exit(Port), iolist_to_binary(Sofar) end. @@ -308,18 +307,25 @@ eot(Bs, Eot) -> binary:part(Bs,{0, Pos}) end. -flush_until_closed(Port) -> +%% When port_close returns we know that all the +%% messages sent have been sent and that the +%% DOWN message is after them all. +flush_until_down(Port, MonRef) -> receive {Port, {data, _Bytes}} -> - flush_until_closed(Port); - {Port, closed} -> - true + flush_until_down(Port, MonRef); + {'DOWN', MonRef, _, _, _} -> + flush_exit(Port) end. +%% The exit signal is always delivered before +%% the down signal, so we can be sure that if there +%% was an exit message sent, it will be in the +%% mailbox now. flush_exit(Port) -> receive {'EXIT', Port, _} -> ok - after 1 -> % force context switch + after 0 -> ok end. -- cgit v1.2.3 From 310e7fd72c241929fca010ae3f39c967aa2856c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 1 Mar 2017 10:35:01 +0100 Subject: Ensure code_SUITE:on_load_embedded/1 does not leak links Make sure that the symlink created in the lib directory is deleted even if the test case fails. --- lib/kernel/test/code_SUITE.erl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 1f4591a5a3..b665d7e592 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -107,6 +107,10 @@ init_per_testcase(big_boot_embedded, Config) -> _Else -> {skip, "Needs crypto!"} end; +init_per_testcase(on_load_embedded, Config) -> + LibRoot = code:lib_dir(), + LinkName = filename:join(LibRoot, "on_load_app-1.0"), + [{link_name,LinkName}|Config]; init_per_testcase(_Func, Config) -> P = code:get_path(), [{code_path, P}|Config]. @@ -124,6 +128,10 @@ end_per_testcase(TC, Config) when TC == mult_lib_roots; NodeName = list_to_atom(atom_to_list(TC)++"@"++HostName), test_server:stop_node(NodeName), end_per_testcase(Config); +end_per_testcase(on_load_embedded, Config) -> + LinkName = proplists:get_value(link_name, Config), + _ = del_link(LinkName), + end_per_testcase(Config); end_per_testcase(_Func, Config) -> end_per_testcase(Config). @@ -1271,10 +1279,9 @@ on_load_embedded(Config) when is_list(Config) -> on_load_embedded_1(Config) -> DataDir = proplists:get_value(data_dir, Config), + LinkName = proplists:get_value(link_name, Config), %% Link the on_load_app application into the lib directory. - LibRoot = code:lib_dir(), - LinkName = filename:join(LibRoot, "on_load_app-1.0"), OnLoadApp = filename:join(DataDir, "on_load_app-1.0"), del_link(LinkName), io:format("LinkName :~p, OnLoadApp: ~p~n",[LinkName,OnLoadApp]), @@ -1308,8 +1315,7 @@ on_load_embedded_1(Config) -> ok = rpc:call(Node, on_load_embedded, status, []), %% Clean up. - stop_node(Node), - ok = del_link(LinkName). + stop_node(Node). del_link(LinkName) -> case file:delete(LinkName) of -- cgit v1.2.3 From a0381d6ee2164bf8ae03d5b9fb01f0dfaf5b394f Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Wed, 8 Mar 2017 12:35:20 +0100 Subject: Update appups in kernel and stdlib for OTP-19.3 --- lib/kernel/src/kernel.appup.src | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 82cf73cbda..15e9e7c462 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + [{<<"5\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.* %% Down to - max one major revision back - [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + [{<<"5\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.* }. -- cgit v1.2.3 From d37a0d105f5332d4f4b23642eb311012a5fe3a64 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 13 Feb 2017 15:51:30 +0100 Subject: kernel: Fix handling of locations and annotations --- lib/kernel/src/application_controller.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl index 0e61153613..3b642f5873 100644 --- a/lib/kernel/src/application_controller.erl +++ b/lib/kernel/src/application_controller.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1620,7 +1620,7 @@ conv(_) -> []. make_term(Str) -> case erl_scan:string(Str) of {ok, Tokens, _} -> - case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of + case erl_parse:parse_term(Tokens ++ [{dot, erl_anno:new(1)}]) of {ok, Term} -> Term; {error, {_,M,Reason}} -> -- cgit v1.2.3 From 6a4d4b43914a5898671e7f9dea7988771450af0f Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 2 Mar 2017 17:36:48 +0100 Subject: Remove typer application The application now has an own repo, https://github.com/erlang/typer --- lib/kernel/test/code_SUITE.erl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 1f4591a5a3..19d36a7613 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -1360,9 +1360,8 @@ create_big_boot(Config) -> %% corresponding beam file (if hipe is not enabled). filter_app("hipe",_) -> false; -%% Dialyzer and typer depends on hipe +%% Dialyzer depends on hipe filter_app("dialyzer",_) -> false; -filter_app("typer",_) -> false; %% Orber requires explicit configuration filter_app("orber",_) -> false; -- cgit v1.2.3 From 26c3cd82529836cb5b6eefbf7f92f318fd91f847 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 10 Mar 2017 15:00:46 +0100 Subject: Update copyright year --- lib/kernel/src/error_logger.erl | 2 +- lib/kernel/src/kernel.appup.src | 2 +- lib/kernel/src/os.erl | 2 +- lib/kernel/src/rpc.erl | 2 +- lib/kernel/test/code_SUITE.erl | 2 +- lib/kernel/test/error_logger_SUITE.erl | 2 +- lib/kernel/test/rpc_SUITE.erl | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index 3ee8e2c6e6..81f1bf8d97 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 15e9e7c462..e1173cd2f4 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-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 03d4324992..a90a6dcca7 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl index bd6ea26678..0e0b7dffa3 100644 --- a/lib/kernel/src/rpc.erl +++ b/lib/kernel/src/rpc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 5777b397b8..62ad7b6a27 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/error_logger_SUITE.erl b/lib/kernel/test/error_logger_SUITE.erl index bb01c2384d..2d26a7246c 100644 --- a/lib/kernel/test/error_logger_SUITE.erl +++ b/lib/kernel/test/error_logger_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/rpc_SUITE.erl b/lib/kernel/test/rpc_SUITE.erl index d76c4097d8..a89a7600a2 100644 --- a/lib/kernel/test/rpc_SUITE.erl +++ b/lib/kernel/test/rpc_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. -- cgit v1.2.3 From 5d9bb41114544c9205a8b8f26642bad8231e8d4e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 10 Mar 2017 15:42:13 +0100 Subject: kernel: Try mend disk_log whitebox tests after atom encoding got 1 byte smaller when changed from <<$d, Len:16, Bytes/binary>> to <<$w, Len:8, Bytes/binary>> --- lib/kernel/test/disk_log_SUITE.erl | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index 23fe975ef7..079cc2f90f 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -481,7 +481,7 @@ halt_ro_crash(Conf) when is_list(Conf) -> %% This is how it was before R6B: %% {C1,T1,15} = disk_log:chunk(a,start), %% {C2,T2} = disk_log:chunk(a,C1), - {C1,_OneItem,7478} = disk_log:chunk(a,start), + {C1,_OneItem,7476} = disk_log:chunk(a,start), {C2, [], 7} = disk_log:chunk(a,C1), eof = disk_log:chunk(a,C2), ok = disk_log:close(a), @@ -2502,8 +2502,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), BadFile = add_ext(File, 2), % current file set_opened(BadFile), - crash(BadFile, 28), % the binary is now invalid - {repaired,n,{recovered,0},{badbytes,26}} = + crash(BadFile, 26), % the binary is now invalid + {repaired,n,{recovered,0},{badbytes,24}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {40,No}}]), ok = disk_log:close(n), @@ -2518,8 +2518,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), BadFile2 = add_ext(File, 1), % current file set_opened(BadFile2), - crash(BadFile2, 51), % the second binary is now invalid - {repaired,n,{recovered,1},{badbytes,26}} = + crash(BadFile2, 47), % the second binary is now invalid + {repaired,n,{recovered,1},{badbytes,24}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {4000,No}}]), ok = disk_log:close(n), @@ -2571,7 +2571,7 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), set_opened(File), crash(File, 30), - {repaired,n,{recovered,3},{badbytes,16}} = + {repaired,n,{recovered,3},{badbytes,15}} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal},{repair,true}, {head_func, {?MODULE, head_fun, [{ok,"head"}]}}]), @@ -2797,7 +2797,7 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:log_terms(n, [{some,terms}]), % second file full 2 = curf(n), BadFile = add_ext(File, 1), - crash(BadFile, 28), % the _binary_ is now invalid + crash(BadFile, 26), % the _binary_ is now invalid {error, {corrupt_log_file, BFile}} = disk_log:chunk(n, start, 1), BadFile = BFile, ok = disk_log:close(n), @@ -2807,7 +2807,7 @@ chunk(Conf) when is_list(Conf) -> {format, internal}]), ok = disk_log:log_terms(n, [{this,is}]), ok = disk_log:sync(n), - crash(File, 28), % the _binary_ is now invalid + crash(File, 26), % the _binary_ is now invalid {error, {corrupt_log_file, File2}} = disk_log:chunk(n, start, 1), crash(File, 10), {error,{corrupt_log_file,_}} = disk_log:bchunk(n, start, 1), @@ -2901,8 +2901,8 @@ chunk(Conf) when is_list(Conf) -> {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {mode, read_only}]), CrashFile = add_ext(File, 1), - crash(CrashFile, 51), % the binary term {some,terms} is now bad - {H1, [{this,is}], 18} = disk_log:chunk(n, start, 10), + crash(CrashFile, 46), % the binary term {some,terms} is now bad + {H1, [{this,is}], 16} = disk_log:chunk(n, start, 10), {H2, [{on,a},{wrap,file}]} = disk_log:chunk(n, H1), eof = disk_log:chunk(n, H2), ok = disk_log:close(n), @@ -2916,8 +2916,8 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal}, {mode, read_only}]), - crash(File, 51), % the binary term {some,terms} is now bad - {J1, [{this,is}], 18} = disk_log:chunk(n, start, 10), + crash(File, 46), % the binary term {some,terms} is now bad + {J1, [{this,is}], 16} = disk_log:chunk(n, start, 10), {J2, [{on,a},{halt,file}]} = disk_log:chunk(n, J1), eof = disk_log:chunk(n, J2), ok = disk_log:close(n), @@ -2932,8 +2932,8 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal}, {mode, read_only}]), - crash(File, 44), % the binary term {s} is now bad - {J11, [{this,is}], 7} = disk_log:chunk(n, start, 10), + crash(File, 40), % the binary term {s} is now bad + {J11, [{this,is}], 6} = disk_log:chunk(n, start, 10), {J21, [{on,a},{halt,file}]} = disk_log:chunk(n, J11), eof = disk_log:chunk(n, J21), ok = disk_log:close(n), @@ -3052,7 +3052,7 @@ truncate(Conf) when is_list(Conf) -> ok = disk_log:truncate(n, apa), rec(1, {disk_log, node(), n, {truncated, 6}}), {0, 0} = no_overflows(n), - 23 = curb(n), + 22 = curb(n), 1 = curf(n), 1 = cur_cnt(n), true = (Size == sz(n)), @@ -3072,7 +3072,7 @@ truncate(Conf) when is_list(Conf) -> ok = disk_log:truncate(n, apa), rec(1, {disk_log, node(), n, {truncated, 3}}), {0, 0} = no_overflows(n), - 23 = curb(n), + 22 = curb(n), 1 = curf(n), 1 = cur_cnt(n), true = (Size == sz(n)), @@ -3181,45 +3181,45 @@ info_current(Conf) when is_list(Conf) -> %% Internal with header. {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {head, header}, {size, {100,No}}]), - {26, 1} = {curb(n), cur_cnt(n)}, + {25, 1} = {curb(n), cur_cnt(n)}, {1, 1} = {no_written_items(n), no_items(n)}, ok = disk_log:log(n, B), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {2, 2} = {no_written_items(n), no_items(n)}, ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {notify, true}, {head, header}, {size, {100,No}}]), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {0, 2} = {no_written_items(n), no_items(n)}, ok = disk_log:log(n, B), rec(1, {disk_log, node(), n, {wrap, 0}}), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {2, 4} = {no_written_items(n), no_items(n)}, disk_log:inc_wrap_file(n), rec(1, {disk_log, node(), n, {wrap, 0}}), - {26, 1} = {curb(n), cur_cnt(n)}, + {25, 1} = {curb(n), cur_cnt(n)}, {3, 4} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. rec(1, {disk_log, node(), n, {wrap, 0}}), rec(1, {disk_log, node(), n, {wrap, 2}}), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {8, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [B]), rec(1, {disk_log, node(), n, {wrap, 2}}), ok = disk_log:log_terms(n, [B]), rec(1, {disk_log, node(), n, {wrap, 2}}), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {12, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [BB,BB]), %% Used to be one message, but now one per wrapped file. rec(2, {disk_log, node(), n, {wrap, 2}}), - {194, 2} = {curb(n), cur_cnt(n)}, + {193, 2} = {curb(n), cur_cnt(n)}, {16, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [SB,SB,SB]), rec(1, {disk_log, node(), n, {wrap, 2}}), - {80, 4} = {curb(n), cur_cnt(n)}, + {79, 4} = {curb(n), cur_cnt(n)}, {20, 9} = {no_written_items(n), no_items(n)}, ok = disk_log:close(n), del(File, No), -- cgit v1.2.3 From af8bc77e32af655f57c82409939ad674e22f3ccf Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 13 Mar 2017 18:20:16 +0100 Subject: kernel: Rewrite distribution flag verification --- lib/kernel/src/dist_util.erl | 48 ++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index 8d2fc4d4b7..a2cebfc2c6 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -131,7 +131,7 @@ handshake_other_started(#hs_data{request_type=ReqType}=HSData0) -> other_version=Version, other_node=Node, other_started=true}, - check_dflag_xnc(HSData), + check_dflags(HSData), is_allowed(HSData), ?debug({"MD5 connection from ~p (V~p)~n", [Node, HSData#hs_data.other_version]}), @@ -168,27 +168,23 @@ is_allowed(#hs_data{other_node = Node, %% Check that both nodes can handle the same types of extended %% node containers. If they can not, abort the connection. %% -check_dflag_xnc(#hs_data{other_node = Node, - other_flags = OtherFlags, - other_started = OtherStarted} = HSData) -> - XRFlg = ?DFLAG_EXTENDED_REFERENCES, - XPPFlg = case erlang:system_info(compat_rel) of - R when R >= 10 -> - ?DFLAG_EXTENDED_PIDS_PORTS; - _ -> - 0 - end, - ReqXncFlags = XRFlg bor XPPFlg, - case OtherFlags band ReqXncFlags =:= ReqXncFlags of - true -> - ok; - false -> - What = case {OtherFlags band XRFlg =:= XRFlg, - OtherFlags band XPPFlg =:= XPPFlg} of - {false, false} -> "references, pids and ports"; - {true, false} -> "pids and ports"; - {false, true} -> "references" - end, +check_dflags(#hs_data{other_node = Node, + other_flags = OtherFlags, + other_started = OtherStarted} = HSData) -> + + Mandatory = [{?DFLAG_EXTENDED_REFERENCES, "EXTENDED_REFERENCES"}, + {?DFLAG_EXTENDED_PIDS_PORTS, "EXTENDED_PIDS_PORTS"}], + Missing = lists:filtermap(fun({Bit, Str}) -> + case Bit band OtherFlags of + Bit -> false; + 0 -> {true, Str} + end + end, + Mandatory), + case Missing of + [] -> + ok; + _ -> case OtherStarted of true -> send_status(HSData, not_allowed), @@ -199,9 +195,9 @@ check_dflag_xnc(#hs_data{other_node = Node, How = "aborted" end, error_msg("** ~w: Connection attempt ~s node ~w ~s " - "since it cannot handle extended ~s. " - "**~n", [node(), Dir, Node, How, What]), - ?shutdown2(Node, {check_dflag_xnc_failed, What}) + "since it cannot handle ~p." + "**~n", [node(), Dir, Node, How, Missing]), + ?shutdown2(Node, {check_dflags_failed, Missing}) end. @@ -327,7 +323,7 @@ handshake_we_started(#hs_data{request_type=ReqType, NewHSData = HSData#hs_data{this_flags = ThisFlags, other_flags = OtherFlags, other_started = false}, - check_dflag_xnc(NewHSData), + check_dflags(NewHSData), MyChallenge = gen_challenge(), {MyCookie,HisCookie} = get_cookies(Node), send_challenge_reply(NewHSData,MyChallenge, -- cgit v1.2.3 From 6c236a63e0ac8ce5851f853d11e4f1374146c6c8 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 13 Mar 2017 18:20:43 +0100 Subject: kernel: Make DFLAG_UTF8_ATOMS mandatory --- lib/kernel/src/dist_util.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index a2cebfc2c6..d929179715 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -173,7 +173,8 @@ check_dflags(#hs_data{other_node = Node, other_started = OtherStarted} = HSData) -> Mandatory = [{?DFLAG_EXTENDED_REFERENCES, "EXTENDED_REFERENCES"}, - {?DFLAG_EXTENDED_PIDS_PORTS, "EXTENDED_PIDS_PORTS"}], + {?DFLAG_EXTENDED_PIDS_PORTS, "EXTENDED_PIDS_PORTS"}, + {?DFLAG_UTF8_ATOMS, "UTF8_ATOMS"}], Missing = lists:filtermap(fun({Bit, Str}) -> case Bit band OtherFlags of Bit -> false; -- cgit v1.2.3 From 4d658008be5a08ddadbe75ebadb9ef124436b76e Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 14 Mar 2017 15:59:23 +0100 Subject: Prepare release --- lib/kernel/doc/src/notes.xml | 39 +++++++++++++++++++++++++++++++++++++++ lib/kernel/vsn.mk | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 9277c2d353..f5a0e68805 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,45 @@

    This document describes the changes made to the Kernel application.

    +
    Kernel 5.2 + +
    Fixed Bugs and Malfunctions + + +

    + Fix a race during cleanup of os:cmd that would cause + os:cmd to hang indefinitely.

    +

    + Own Id: OTP-14232 Aux Id: seq13275

    +
    +
    +
    + + +
    Improvements and New Features + + +

    The functions in the 'file' module that take a + list of paths (e.g. file:path_consult/2) will now + continue to search in the path if the path contains + something that is not a directory.

    +

    + Own Id: OTP-14191

    +
    + +

    Two OTP processes that are known to receive many + messages are 'rex' (used by 'rpc') and 'error_logger'. + Those processes will now store unprocessed messages + outside the process heap, which will potentially decrease + the cost of garbage collections.

    +

    + Own Id: OTP-14192

    +
    +
    +
    + +
    +
    Kernel 5.1.1
    Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 8d2517e680..76b020e8ed 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.1.1 +KERNEL_VSN = 5.2 -- cgit v1.2.3 From 0ef9dd12e5e77d67244dca580c1a706878c272bf Mon Sep 17 00:00:00 2001 From: vans163 Date: Tue, 31 Jan 2017 14:07:27 -0500 Subject: Update inet.xml. Note buffer relation to MTU The documentation does not indicate this is the buffer responsible for the maximum bytes we can receive from a recv call. --- lib/kernel/doc/src/inet.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index 4c4a5c39cb..d557efb6a8 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -659,7 +659,8 @@ get_tcpi_sacked(Sock) -> {buffer, Size}

    The size of the user-level software buffer used by - the driver. Not to be confused with options sndbuf + the driver. + Not to be confused with options sndbuf and recbuf, which correspond to the Kernel socket buffers. It is recommended to have val(buffer) >= max(val(sndbuf),val(recbuf)) to @@ -670,6 +671,9 @@ get_tcpi_sacked(Sock) -> usually become larger, you are encouraged to use getopts/2 to analyze the behavior of your operating system.

    +

    Note that this is also the maximum amount of data that can be + received from a single recv call. If you are using higher than + normal MTU consider setting buffer higher.

    {delay_send, Boolean} -- cgit v1.2.3 From 0b821683cb11d78945bbf9cef65ffeb9dc2e357e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 20 Mar 2017 18:59:32 +0100 Subject: kernel: Remove pg2_SUITE:compat as it tests removed compatibility with R13 node. --- lib/kernel/test/pg2_SUITE.erl | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl index fdc268cb5a..9460608a3e 100644 --- a/lib/kernel/test/pg2_SUITE.erl +++ b/lib/kernel/test/pg2_SUITE.erl @@ -31,7 +31,7 @@ -export([ otp_7277/1, otp_8259/1, otp_8653/1, - compat/1, basic/1]). + basic/1]). -define(TESTCASE, testcase_name). -define(testcase, proplists:get_value(?TESTCASE, Config)). @@ -56,7 +56,7 @@ all() -> groups() -> [{tickets, [], - [otp_7277, otp_8259, otp_8653, compat, basic]}]. + [otp_7277, otp_8259, otp_8653, basic]}]. init_per_suite(Config) -> Config. @@ -218,29 +218,6 @@ loop() -> exit(normal) end. -%% OTP-8259. Check that 'exchange' and 'del_member' work. -compat(Config) when is_list(Config) -> - case test_server:is_release_available("r13b") of - true -> - Pid = spawn(forever()), - G = a, - ok = pg2:create(G), - ok = pg2:join(G, Pid), - ok = pg2:join(G, Pid), - {ok, A} = start_node_rel(r13, r13b, slave), - pong = net_adm:ping(A), - wait_for_ready_net(Config), - {ok, _} = rpc:call(A, pg2, start, []), - ?UNTIL([Pid,Pid] =:= rpc:call(A, pg2, get_members, [a])), - true = exit(Pid, kill), - ?UNTIL([] =:= pg2:get_members(a)), - ?UNTIL([] =:= rpc:call(A, pg2, get_members, [a])), - test_server:stop_node(A), - ok; - false -> - {skipped, "No support for old node"} - end. - %% OTP-8259. Some basic tests. basic(Config) when is_list(Config) -> _ = [pg2:delete(G) || G <- pg2:which_groups()], -- cgit v1.2.3 From a72e675fce23b9bebb7c9ff8beb6f962c4f9930a Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 20 Mar 2017 19:08:58 +0100 Subject: kernel: Fix erl_distribution_wb_SUITE:whitebox for OTP 20. --- lib/kernel/test/erl_distribution_wb_SUITE.erl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl index 61aa3b32ee..c1dc208cc1 100644 --- a/lib/kernel/test/erl_distribution_wb_SUITE.erl +++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl @@ -56,10 +56,14 @@ -define(DFLAG_HIDDEN_ATOM_CACHE,16#40). -define(DFLAG_NEW_FUN_TAGS,16#80). -define(DFLAG_EXTENDED_PIDS_PORTS,16#100). +-define(DFLAG_UTF8_ATOMS, 16#10000). %% From R9 and forward extended references is compulsory %% From R10 and forward extended pids and ports are compulsory --define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor ?DFLAG_EXTENDED_PIDS_PORTS)). +%% From R20 and forward UTF8 atoms are compulsory +-define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor + ?DFLAG_EXTENDED_PIDS_PORTS bor + ?DFLAG_UTF8_ATOMS)). -define(shutdown(X), exit(X)). -- cgit v1.2.3 From 1b4dedb155a4fe6faf35448c2d119e391204701a Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 16 Mar 2017 10:38:23 +0100 Subject: kernel: Expand gen_tcp:close docs with send text This commit attempts to clarify some of the guarantees given by the TCP standard when issuing close. This is quite a complex topic so there are probably corner cases still left, but this at least tells the user that things can go wrong when doing a close. --- lib/kernel/doc/src/gen_tcp.xml | 17 +++++++++++++++++ lib/kernel/doc/src/inet.xml | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index e97db20062..bef8096aed 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -140,6 +140,23 @@ do_recv(Sock, Bs) -> Close a TCP socket.

    Closes a TCP socket.

    +

    Note that in most implementations of TCP, doing a close does + not guarantee that any data sent is delivered to the recipient before + the close is detected at the remote side. If you want to guarantee + delivery of the data to the recipient there are two common ways to + achieve this.

    + +

    Use + gen_tcp:shutdown(Sock, write) to signal that + no more data is to be sent and wait for the read side of the + socket to be closed.

    +
    +

    Use the socket option + {packet, N} (or something similar) to make + it possible for the receiver to close the connection when it + knowns it has received all the data.

    +
    +
    diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index 4c4a5c39cb..36a99f7a7a 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -909,7 +909,7 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp
    {packet, PacketType}(TCP/IP sockets) -

    Defines the type of packets to use for a socket. +

    Defines the type of packets to use for a socket. Possible values:

    raw | 0 -- cgit v1.2.3 From 3edc6dbf8f150bb6ba7c800ed5cc379771f8b279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 30 Mar 2017 15:26:55 +0200 Subject: kernel: Refactor supervision tree Use maps in definitions to make them more readable. --- lib/kernel/src/kernel.erl | 244 ++++++++++++++++++++++++++++++---------------- 1 file changed, 159 insertions(+), 85 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl index 59eca242b1..b901da95b8 100644 --- a/lib/kernel/src/kernel.erl +++ b/lib/kernel/src/kernel.erl @@ -100,63 +100,112 @@ get_error_logger_type() -> %%%----------------------------------------------------------------- init([]) -> - SupFlags = {one_for_all, 0, 1}, - - Config = {kernel_config, - {kernel_config, start_link, []}, - permanent, 2000, worker, [kernel_config]}, - Code = {code_server, - {code, start_link, []}, - permanent, 2000, worker, [code]}, - File = {file_server_2, - {file_server, start_link, []}, - permanent, 2000, worker, - [file, file_server, file_io_server, prim_file]}, - StdError = {standard_error, - {standard_error, start_link, []}, - temporary, 2000, supervisor, [user_sup]}, - User = {user, - {user_sup, start, []}, - temporary, 2000, supervisor, [user_sup]}, - + SupFlags = #{strategy => one_for_all, + intensity => 0, + period => 1}, + + Config = #{id => kernel_config, + start => {kernel_config, start_link, []}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => [kernel_config]}, + + Code = #{id => code_server, + start => {code, start_link, []}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => [code]}, + + File = #{id => file_server_2, + start => {file_server, start_link, []}, + restart => permanent, + shutdown => 2000, + type => worker, + modeules => [file, file_server, file_io_server, prim_file]}, + + StdError = #{id => standard_error, + start => {standard_error, start_link, []}, + restart => temporary, + shutdown => 2000, + type => supervisor, + modules => [user_sup]}, + + User = #{id => user, + start => {user_sup, start, []}, + restart => temporary, + shutdown => 2000, + type => supervisor, + modules => [user_sup]}, + + SafeSup = #{id => kernel_safe_sup, + start =>{supervisor, start_link, [{local, kernel_safe_sup}, ?MODULE, safe]}, + restart => permanent, + shutdown => infinity, + type => supervisor, + modules => [?MODULE]}, + case init:get_argument(mode) of - {ok, [["minimal"]]} -> - SafeSupervisor = {kernel_safe_sup, - {supervisor, start_link, - [{local, kernel_safe_sup}, ?MODULE, safe]}, - permanent, infinity, supervisor, [?MODULE]}, - {ok, {SupFlags, - [Code, File, StdError, User, - Config, SafeSupervisor]}}; - _ -> - Rpc = {rex, {rpc, start_link, []}, - permanent, 2000, worker, [rpc]}, - Global = {global_name_server, {global, start_link, []}, - permanent, 2000, worker, [global]}, - Glo_grp = {global_group, {global_group,start_link,[]}, - permanent, 2000, worker, [global_group]}, - InetDb = {inet_db, {inet_db, start_link, []}, - permanent, 2000, worker, [inet_db]}, - NetSup = {net_sup, {erl_distribution, start_link, []}, - permanent, infinity, supervisor,[erl_distribution]}, + {ok, [["minimal"]]} -> + {ok, {SupFlags, [Code, File, StdError, User, Config, SafeSup]}}; + _ -> + Rpc = #{id => rex, + start => {rpc, start_link, []}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => [rpc]}, + + Global = #{id => global_name_server, + start => {global, start_link, []}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => [global]}, + + GlGroup = #{id => global_group, + start => {global_group,start_link,[]}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => [global_group]}, + + InetDb = #{id => inet_db, + start => {inet_db, start_link, []}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => [inet_db]}, + + NetSup = #{id => net_sup, + start => {erl_distribution, start_link, []}, + restart => permanent, + shutdown => infinity, + type => supervisor, + modules => [erl_distribution]}, + SigSrv = #{id => erl_signal_server, start => {gen_event, start_link, [{local, erl_signal_server}]}, - type => worker, restart => permanent, shutdown => 2000, modules => dynamic}, - DistAC = start_dist_ac(), - - Timer = start_timer(), - - SafeSupervisor = {kernel_safe_sup, - {supervisor, start_link, - [{local, kernel_safe_sup}, ?MODULE, safe]}, - permanent, infinity, supervisor, [?MODULE]}, - {ok, {SupFlags, - [Code, Rpc, Global, InetDb | DistAC] ++ - [NetSup, Glo_grp, File, SigSrv, - StdError, User, Config, SafeSupervisor] ++ Timer}} + restart => permanent, + shutdown => 2000, + type => worker, + modules => dynamic}, + + DistAC = start_dist_ac(), + + Timer = start_timer(), + + {ok, {SupFlags, + [Code, Rpc, Global, InetDb | DistAC] ++ + [NetSup, GlGroup, File, SigSrv, + StdError, User, Config, SafeSup] ++ Timer}} end; init(safe) -> - SupFlags = {one_for_one, 4, 3600}, + SupFlags = #{strategy => one_for_one, + intensity => 4, + period => 3600}, + Boot = start_boot_server(), DiskLog = start_disk_log(), Pg2 = start_pg2(), @@ -170,60 +219,85 @@ init(safe) -> {ok, {SupFlags, Boot ++ DiskLog ++ Pg2}}. start_dist_ac() -> - Spec = [{dist_ac,{dist_ac,start_link,[]},permanent,2000,worker,[dist_ac]}], + Spec = [#{id => dist_ac, + start => {dist_ac,start_link,[]}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => [dist_ac]}], case application:get_env(kernel, start_dist_ac) of - {ok, true} -> Spec; - {ok, false} -> []; - undefined -> - case application:get_env(kernel, distributed) of - {ok, _} -> Spec; - _ -> [] - end + {ok, true} -> Spec; + {ok, false} -> []; + undefined -> + case application:get_env(kernel, distributed) of + {ok, _} -> Spec; + _ -> [] + end end. start_boot_server() -> case application:get_env(kernel, start_boot_server) of - {ok, true} -> - Args = get_boot_args(), - [{boot_server, {erl_boot_server, start_link, [Args]}, permanent, - 1000, worker, [erl_boot_server]}]; - _ -> - [] + {ok, true} -> + Args = get_boot_args(), + [#{id => boot_server, + start => {erl_boot_server, start_link, [Args]}, + restart => permanent, + shutdown => 1000, + type => worker, + modules => [erl_boot_server]}]; + _ -> + [] end. get_boot_args() -> case application:get_env(kernel, boot_server_slaves) of - {ok, Slaves} -> Slaves; - _ -> [] + {ok, Slaves} -> Slaves; + _ -> [] end. start_disk_log() -> case application:get_env(kernel, start_disk_log) of - {ok, true} -> - [{disk_log_server, - {disk_log_server, start_link, []}, - permanent, 2000, worker, [disk_log_server]}, - {disk_log_sup, {disk_log_sup, start_link, []}, permanent, - 1000, supervisor, [disk_log_sup]}]; - _ -> - [] + {ok, true} -> + [#{id => disk_log_server, + start => {disk_log_server, start_link, []}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => [disk_log_server]}, + #{id => disk_log_sup, + start => {disk_log_sup, start_link, []}, + restart => permanent, + shutdown => 1000, + type => supervisor, + modules => [disk_log_sup]}]; + _ -> + [] end. start_pg2() -> case application:get_env(kernel, start_pg2) of - {ok, true} -> - [{pg2, {pg2, start_link, []}, permanent, 1000, worker, [pg2]}]; - _ -> - [] + {ok, true} -> + [#{id => pg2, + start => {pg2, start_link, []}, + restart => permanent, + shutdown => 1000, + type => worker, + modules => [pg2]}]; + _ -> + [] end. start_timer() -> case application:get_env(kernel, start_timer) of - {ok, true} -> - [{timer_server, {timer, start_link, []}, permanent, 1000, worker, - [timer]}]; - _ -> - [] + {ok, true} -> + [#{id => timer_server, + start => {timer, start_link, []}, + restart => permanent, + shutdown => 1000, + type => worker, + modules => [timer]}]; + _ -> + [] end. %%----------------------------------------------------------------- -- cgit v1.2.3 From b87894a1e91ad8370196a0c0d9ec6bfefab1dcbd Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 10 Apr 2017 11:25:53 +0200 Subject: kernel: Add mem check to prim_file:large_write tc --- lib/kernel/test/prim_file_SUITE.erl | 47 ++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 8be94f1e57..0c84a7d1cc 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -19,8 +19,8 @@ %% -module(prim_file_SUITE). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - read_write_file/1]). + init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2, + read_write_file/1, free_memory/0]). -export([cur_dir_0a/1, cur_dir_0b/1, cur_dir_1a/1, cur_dir_1b/1, make_del_dir_a/1, make_del_dir_b/1, @@ -115,6 +115,18 @@ groups() -> [make_link_a, make_link_b, read_link_info_for_non_link, symlinks_a, symlinks_b, list_dir_error]}]. +init_per_testcase(large_write, Config) -> + {ok, Started} = application:ensure_all_started(os_mon), + [{started, Started}|Config]; +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(large_write, Config) -> + [application:stop(App) || App <- lists:reverse(proplists:get_value(started, Config))], + ok; +end_per_testcase(_, _Config) -> + ok. + init_per_group(_GroupName, Config) -> Config. @@ -2022,11 +2034,13 @@ run_large_file_test(Config, Run, Name) -> {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; {{unix,_},_} -> - N = unix_free(proplists:get_value(priv_dir, Config)), - io:format("Free disk: ~w KByte~n", [N]), - if N < 5 bsl 20 -> + DiscFree = unix_free(proplists:get_value(priv_dir, Config)), + MemFree = free_memory(), + io:format("Free disk: ~w KByte~n", [DiscFree]), + io:format("Free mem: ~w MByte~n", [MemFree]), + if DiscFree < 5 bsl 20; MemFree < 5 bsl 10 -> %% Less than 5 GByte free - {skip,"Less than 5 GByte free disk"}; + {skip,"Less than 5 GByte free disk/mem"}; true -> do_run_large_file_test(Config, Run, Name) end; @@ -2079,6 +2093,27 @@ zip_data([], Bs) -> zip_data(As, []) -> As. +%% Stolen from emulator -> alloc_SUITE +free_memory() -> + %% Free memory in MB. + try + SMD = memsup:get_system_memory_data(), + {value, {free_memory, Free}} = lists:keysearch(free_memory, 1, SMD), + TotFree = (Free + + case lists:keysearch(cached_memory, 1, SMD) of + {value, {cached_memory, Cached}} -> Cached; + false -> 0 + end + + case lists:keysearch(buffered_memory, 1, SMD) of + {value, {buffered_memory, Buffed}} -> Buffed; + false -> 0 + end), + TotFree div (1024*1024) + catch + error : undef -> + ct:fail({"os_mon not built"}) + end. + %%%----------------------------------------------------------------- %%% Utilities rm_rf(Mod,Dir) -> -- cgit v1.2.3 From 308841d8c99907a364d6876ed9375507153729eb Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Thu, 2 Feb 2017 11:17:17 +0100 Subject: implement SO_BINDTODEVICE for inet protocols bind to device is needed to properly support VRF-Lite under Linux (see [1] for details). [1]: https://www.kernel.org/doc/Documentation/networking/vrf.txt --- lib/kernel/doc/src/inet.xml | 26 ++++++++++++++++ lib/kernel/src/inet.erl | 8 ++--- lib/kernel/src/inet_int.hrl | 1 + lib/kernel/test/inet_SUITE.erl | 70 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 99 insertions(+), 6 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index 076e50cd10..947e4d4560 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -897,6 +897,32 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp file:native_name_encoding/0.

    + {bind_to_device, Ifname :: binary()} + +

    Binds a socket to a specific network interface. This option + must be used in a function call that creates a socket, that is, + gen_tcp:connect/3,4, + gen_tcp:listen/2, + gen_udp:open/1,2, or + gen_sctp:open/0,1,2.

    +

    Unlike getifaddrs/0, Ifname + is encoded a binary. In the unlikely case that a system is using + non-7-bit-ASCII characters in network device names, special care + has to be taken when encoding this argument.

    +

    This option uses the Linux-specific socket option + SO_BINDTODEVICE, such as in Linux kernel 2.0.30 or later, + and therefore only exists when the runtime system + is compiled for such an operating system.

    +

    Before Linux 3.8, this socket option could be set, but could not retrieved + with getopts/2. Since Linux 3.8, + it is readable.

    +

    The virtual machine also needs elevated privileges, either + running as superuser or (for Linux) having capability + CAP_NET_RAW.

    +

    The primary use case for this option is to bind sockets into + Linux VRF instances. +

    +
    list

    Received Packet is delivered as a list.

    diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index f5c13ecdd7..5be790b7d9 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -702,7 +702,7 @@ connect_options() -> header, active, packet, packet_size, buffer, mode, deliver, line_delimiter, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw, - show_econnreset]. + show_econnreset, bind_to_device]. connect_options(Opts, Mod) -> BaseOpts = @@ -770,7 +770,7 @@ listen_options() -> header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, - packet_size, raw, show_econnreset]. + packet_size, raw, show_econnreset, bind_to_device]. listen_options(Opts, Mod) -> BaseOpts = @@ -850,7 +850,7 @@ udp_options() -> deliver, ipv6_v6only, broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop, add_membership, drop_membership, read_packets,raw, - high_msgq_watermark, low_msgq_watermark]. + high_msgq_watermark, low_msgq_watermark, bind_to_device]. udp_options(Opts, Mod) -> @@ -919,6 +919,7 @@ sctp_options() -> [ % The following are generic inet options supported for SCTP sockets: mode, active, buffer, tos, tclass, priority, dontroute, reuseaddr, linger, sndbuf, recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark, + bind_to_device, % Other options are SCTP-specific (though they may be similar to their % TCP and UDP counter-parts): @@ -1055,7 +1056,6 @@ binary2filename(Bin) -> Bin end. - translate_ip(any, inet) -> {0,0,0,0}; translate_ip(loopback, inet) -> {127,0,0,1}; translate_ip(any, inet6) -> {0,0,0,0,0,0,0,0}; diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl index 4e8f59a3b9..e6cd48935a 100644 --- a/lib/kernel/src/inet_int.hrl +++ b/lib/kernel/src/inet_int.hrl @@ -154,6 +154,7 @@ -define(INET_LOPT_TCP_SHOW_ECONNRESET, 39). -define(INET_LOPT_LINE_DELIM, 40). -define(INET_OPT_TCLASS, 41). +-define(INET_OPT_BIND_TO_DEVICE, 42). % Specific SCTP options: separate range: -define(SCTP_OPT_RTOINFO, 100). -define(SCTP_OPT_ASSOCINFO, 101). diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index f60c13d2e3..86f6b95fb9 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -40,7 +40,8 @@ lookup_bad_search_option/1, getif/1, getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1, - parse_strict_address/1, simple_netns/1, simple_netns_open/1]). + parse_strict_address/1, simple_netns/1, simple_netns_open/1, + simple_bind_to_device/1, simple_bind_to_device_open/1]). -export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1, kill_gethost/0, parallell_gethost/0, test_netns/0]). @@ -58,7 +59,8 @@ all() -> gethostnative_debug_level, gethostnative_soft_restart, lookup_bad_search_option, getif, getif_ifr_name_overflow, getservbyname_overflow, - getifaddrs, parse_strict_address, simple_netns, simple_netns_open]. + getifaddrs, parse_strict_address, simple_netns, simple_netns_open, + simple_bind_to_device, simple_bind_to_device_open]. groups() -> [{parse, [], [parse_hosts, parse_address]}]. @@ -1247,3 +1249,67 @@ cmd(CmdString) -> io:put_chars(["# ",CmdString,io_lib:nl()]), io:put_chars([os:cmd(CmdString++" ; echo ' =>' $?")]), ok. + +-define(CAP_NET_RAW, 13). %% from /usr/include/linux/capability.h + +can_bind_to_device({unix, linux}, {Major, _, _}) + when Major > 2 -> + Status = os:cmd("cat /proc/self/status | grep CapEff"), + [_, CapEffStr] = string:tokens(Status, [$\n, $\t]), + CapEff = list_to_integer(CapEffStr, 16), + if CapEff band (1 bsl ?CAP_NET_RAW) =/= 0 -> + ok; + true -> + {skip,"insufficient capabilities, CAP_NET_RAW not granted"} + end; +can_bind_to_device(_OS, _Version) -> + {skip,"socket option bind_to_device not supported on this OS or version"}. + +simple_bind_to_device(Config) when is_list(Config) -> + case can_bind_to_device(os:type(), os:version()) of + ok -> + {ok,U} = gen_udp:open(0), + jog_bind_to_device_opt(U), + ok = gen_udp:close(U), + %% + {ok,L} = gen_tcp:listen(0, []), + jog_bind_to_device_opt(L), + ok = gen_tcp:close(L), + %% + case gen_sctp:open() of + {ok,S} -> + jog_bind_to_device_opt(S), + ok = gen_sctp:close(S); + {error,eprotonosupport} -> + ok + end; + Other -> + Other + end. + +%% Smoke test bind_to_device support. +simple_bind_to_device_open(Config) when is_list(Config) -> + case can_bind_to_device(os:type(), os:version()) of + ok -> + {ok,U} = gen_udp:open(0, [binary,{bind_to_device,<<"lo">>},inet]), + ok = gen_udp:close(U), + {ok,T} = gen_tcp:listen(0, [binary,{bind_to_device,<<"lo">>},inet]), + ok = gen_tcp:close(T), + + case gen_sctp:open(0, [binary,{bind_to_device,<<"lo">>},inet]) of + {ok,S} -> + ok = gen_sctp:close(S); + {error,eprotonosupport} -> + ok + end; + Other -> + Other + end. + +jog_bind_to_device_opt(S) -> + %% This is just jogging the option mechanics + ok = inet:setopts(S, [{bind_to_device,<<>>}]), + {ok,[{bind_to_device,<<>>}]} = inet:getopts(S, [bind_to_device]), + ok = inet:setopts(S, [{bind_to_device,<<"lo">>}]), + {ok,[{bind_to_device,<<"lo">>}]} = inet:getopts(S, [bind_to_device]), + ok. -- cgit v1.2.3 From 571912132247220e062db73819456e3c54476d64 Mon Sep 17 00:00:00 2001 From: Zandra Norman Date: Tue, 25 Apr 2017 17:17:08 +0200 Subject: Kernel: fix file_name_SUITE:icky test case --- lib/kernel/test/file_name_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl index 10b6b105d0..b2051af050 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -383,7 +383,7 @@ check_icky(Mod) -> ok end, - _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir">>)), + _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir"/utf8>>)), if UniMode and (OS =/= win32) -> {error,enoent} = Mod:set_cwd("åäö_dir"); -- cgit v1.2.3 From 25952bf726e4dc20fb3e2067e0b92c55932ce616 Mon Sep 17 00:00:00 2001 From: Zandra Norman Date: Fri, 28 Apr 2017 12:12:52 +0200 Subject: kernel: Do not allow unicode in nodenames Verify that unicode isn't used in a node name and logi an info message if it is. Filter the head part of the name a bit harder to work with epmd. --- lib/kernel/src/net_kernel.erl | 38 ++++++++++-- lib/kernel/test/erl_distribution_SUITE.erl | 99 ++++++++++++++++++++++++++++-- 2 files changed, 129 insertions(+), 8 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl index 0a9f9316b0..9921a0adfd 100644 --- a/lib/kernel/src/net_kernel.erl +++ b/lib/kernel/src/net_kernel.erl @@ -1262,11 +1262,22 @@ create_name(Name, LongOrShortNames, Try) -> {Head,Host1} = create_hostpart(Name, LongOrShortNames), case Host1 of {ok,HostPart} -> - {ok,list_to_atom(Head ++ HostPart)}; + case valid_name_head(Head) of + true -> + {ok,list_to_atom(Head ++ HostPart)}; + false -> + error_logger:info_msg("Invalid node name!\n" + "Please check your configuration\n"), + {error, badarg} + end; {error,long} when Try =:= 1 -> %% It could be we haven't read domain name from resolv file yet inet_config:do_load_resolv(os:type(), longnames), create_name(Name, LongOrShortNames, 0); + {error, hostname_not_allowed} -> + error_logger:info_msg("Invalid node name!\n" + "Please check your configuration\n"), + {error, badarg}; {error,Type} -> error_logger:info_msg( lists:concat(["Can\'t set ", @@ -1279,12 +1290,13 @@ create_name(Name, LongOrShortNames, Try) -> create_hostpart(Name, LongOrShortNames) -> {Head,Host} = split_node(Name), Host1 = case {Host,LongOrShortNames} of - {[$@,_|_],longnames} -> - {ok,Host}; + {[$@,_|_] = Host,longnames} -> + validate_hostname(Host); {[$@,_|_],shortnames} -> case lists:member($.,Host) of true -> {error,short}; - _ -> {ok,Host} + _ -> + validate_hostname(Host) end; {_,shortnames} -> case inet_db:gethostname() of @@ -1304,6 +1316,24 @@ create_hostpart(Name, LongOrShortNames) -> end, {Head,Host1}. +validate_hostname([$@|HostPart] = Host) -> + {ok, MP} = re:compile("^[!-ÿ]*$", [unicode]), + case re:run(HostPart, MP) of + {match, _} -> + {ok, Host}; + nomatch -> + {error, hostname_not_allowed} + end. + +valid_name_head(Head) -> + {ok, MP} = re:compile("^[0-9A-Za-z_\\-]*$", [unicode]), + case re:run(Head, MP) of + {match, _} -> + true; + nomatch -> + false + end. + split_node(Name) -> lists:splitwith(fun(C) -> C =/= $@ end, atom_to_list(Name)). diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index 09c80a0956..ecfa3d6cdb 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -24,7 +24,9 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). --export([tick/1, tick_change/1, illegal_nodenames/1, hidden_node/1, +-export([tick/1, tick_change/1, + nodenames/1, hostnames/1, + illegal_nodenames/1, hidden_node/1, setopts/1, table_waste/1, net_setuptime/1, inet_dist_options_options/1, @@ -53,7 +55,6 @@ -export([pinger/1]). - -define(DUMMY_NODE,dummy@test01). %%----------------------------------------------------------------- @@ -68,8 +69,8 @@ suite() -> {timetrap,{minutes,4}}]. all() -> - [tick, tick_change, illegal_nodenames, hidden_node, - setopts, + [tick, tick_change, nodenames, hostnames, illegal_nodenames, + hidden_node, setopts, table_waste, net_setuptime, inet_dist_options_options, {group, monitor_nodes}]. @@ -179,7 +180,97 @@ table_waste(Config) when is_list(Config) -> stop_node(N), ok. +%% Test that starting nodes with different legal name part works, and that illegal +%% ones are filtered +nodenames(Config) when is_list(Config) -> + legal("a1@b"), + legal("a-1@b"), + legal("a_1@b"), + + illegal("cdé@a"), + illegal("te欢st@a"). + +%% Test that starting nodes with different legal host part works, and that illegal +%% ones are filtered +hostnames(Config) when is_list(Config) -> + Host = gethostname(), + legal([$a,$@|atom_to_list(Host)]), + legal("1@b1"), + legal("b@b1-c"), + legal("c@b1_c"), + legal("d@b1#c"), + legal("f@::1"), + legal("g@1:bc3:4e3f:f20:0:1"), + + case file:native_name_encoding() of + latin1 -> ignore; + _ -> legal("e@b1é") + end, + long_hostnames(net_kernel:longnames()), + + illegal("h@testالع"), + illegal("i@языtest"), + illegal("j@te欢st"). + +long_hostnames(true) -> + legal("k@b.b.c"), + legal("l@b.b-c.d"), + legal("m@b.b_c.d"), + legal("n@127.0.0.1"), + legal("o@207.123.456.789"); +long_hostnames(false) -> + illegal("k@b.b.c"). + +legal(Name) -> + case test_node(Name) of + started -> + ok; + not_started -> + ct:fail("no ~p node started", [Name]) + end. + +illegal(Name) -> + case test_node(Name) of + not_started -> + ok; + started -> + ct:fail("~p node started with illegal name", [Name]) + end. +test_node(Name) -> + ProgName = atom_to_list(lib:progname()), + Command = ProgName ++ " -noinput " ++ long_or_short() ++ Name ++ + " -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"", + net_kernel:monitor_nodes(true), + BinCommand = unicode:characters_to_binary(Command, utf8), + open_port({spawn, BinCommand}, [stream]), + Node = list_to_atom(Name), + receive + {nodeup, Node} -> + net_kernel:monitor_nodes(false), + slave:stop(Node), + started + after 5000 -> + net_kernel:monitor_nodes(false), + not_started + end. + +long_or_short() -> + case net_kernel:longnames() of + true -> " -name "; + false -> " -sname " + end. + +% get the localhost's name, depending on the using name policy +gethostname() -> + Hostname = case net_kernel:longnames() of + true-> + net_adm:localhost(); + _-> + {ok, Name}=inet:gethostname(), + Name + end, + list_to_atom(Hostname). %% Test that pinging an illegal nodename does not kill the node. illegal_nodenames(Config) when is_list(Config) -> -- cgit v1.2.3 From afa12d457b0e71f1ffe917c4d43e96350c6b4f4e Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 4 May 2017 09:42:19 +0200 Subject: Fix missing release note --- lib/kernel/doc/src/notes.xml | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index ad349c5aaf..6d6367a2bd 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -166,6 +166,14 @@

    Own Id: OTP-13564

    + +

    + Rudimentary support for DSCP has been implemented + in the guise of a tclass socket option + for IPv6 sockets.

    +

    + Own Id: OTP-13582

    +
    -- cgit v1.2.3 From df75dcf7287cb0c0ffd4dc7f253161eb3f3779c3 Mon Sep 17 00:00:00 2001 From: Kenji Rikitake Date: Thu, 4 May 2017 19:45:30 +0900 Subject: inet.xml: fix invalid IPv4-mapped-address examples * IPv6 address FFFF::192.168.42.2 is an invalid form as an IPv4-mapped address. This should be fixed as ::FFFF:192.168.42.2. The assigned address block is ::ffff:0:0/96. See RFC6890 Table 20 in the Section 2.2.2 for the further details. And for this IPv4-mapped address use *only*, the 32bit LSB of the IPv6 address can be written with the respective IPv4 address. See RFC4291 Section 2.2 Form 3 for the further details. --- lib/kernel/doc/src/inet.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index 947e4d4560..b9f5f87efb 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -75,8 +75,8 @@ Address ip_address() ------- ------------ ::1 {0,0,0,0,0,0,0,1} ::192.168.42.2 {0,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2} -FFFF::192.168.42.2 - {16#FFFF,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2} +::FFFF:192.168.42.2 + {0,0,0,0,0,16#FFFF,(192 bsl 8) bor 168,(42 bsl 8) bor 2} 3ffe:b80:1f8d:2:204:acff:fe17:bf38 {16#3ffe,16#b80,16#1f8d,16#2,16#204,16#acff,16#fe17,16#bf38} fe80::204:acff:fe17:bf38 @@ -87,8 +87,8 @@ fe80::204:acff:fe17:bf38
     1> inet:parse_address("192.168.42.2").
     {ok,{192,168,42,2}}
    -2> inet:parse_address("FFFF::192.168.42.2").
    -{ok,{65535,0,0,0,0,0,49320,10754}}
    +2> inet:parse_address("::FFFF:192.168.42.2"). +{ok,{0,0,0,0,0,65535,49320,10754}} -- cgit v1.2.3 From 83e20c62057ebc1d8064bf57b01be560cd244e1d Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 4 May 2017 15:42:21 +0200 Subject: Update copyright year --- lib/kernel/doc/src/code.xml | 2 +- lib/kernel/doc/src/config.xml | 2 +- lib/kernel/doc/src/gen_tcp.xml | 2 +- lib/kernel/doc/src/inet.xml | 2 +- lib/kernel/doc/src/kernel_app.xml | 2 +- lib/kernel/doc/src/notes.xml | 2 +- lib/kernel/doc/src/os.xml | 2 +- lib/kernel/doc/src/seq_trace.xml | 2 +- lib/kernel/include/inet.hrl | 2 +- lib/kernel/src/code.erl | 2 +- lib/kernel/src/disk_log.erl | 2 +- lib/kernel/src/disk_log.hrl | 2 +- lib/kernel/src/dist_ac.erl | 2 +- lib/kernel/src/dist_util.erl | 2 +- lib/kernel/src/erl_signal_handler.erl | 2 +- lib/kernel/src/error_logger.erl | 2 +- lib/kernel/src/file.erl | 2 +- lib/kernel/src/global.erl | 2 +- lib/kernel/src/inet.erl | 2 +- lib/kernel/src/inet_int.hrl | 2 +- lib/kernel/src/inet_parse.erl | 2 +- lib/kernel/src/inet_udp.erl | 2 +- lib/kernel/src/kernel.appup.src | 2 +- lib/kernel/src/kernel.erl | 2 +- lib/kernel/src/net_kernel.erl | 2 +- lib/kernel/src/os.erl | 2 +- lib/kernel/src/rpc.erl | 2 +- lib/kernel/test/application_SUITE.erl | 2 +- lib/kernel/test/code_SUITE.erl | 2 +- lib/kernel/test/disk_log_SUITE.erl | 2 +- lib/kernel/test/erl_distribution_SUITE.erl | 2 +- lib/kernel/test/erl_distribution_wb_SUITE.erl | 2 +- lib/kernel/test/error_logger_SUITE.erl | 2 +- lib/kernel/test/file_SUITE.erl | 2 +- lib/kernel/test/file_name_SUITE.erl | 2 +- lib/kernel/test/inet_SUITE.erl | 2 +- lib/kernel/test/multi_load_SUITE.erl | 2 +- lib/kernel/test/pg2_SUITE.erl | 2 +- lib/kernel/test/prim_file_SUITE.erl | 2 +- lib/kernel/test/rpc_SUITE.erl | 2 +- 40 files changed, 40 insertions(+), 40 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 878a450f0f..c94f612c01 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -4,7 +4,7 @@
    - 19962016 + 19962017 Ericsson AB. All Rights Reserved. diff --git a/lib/kernel/doc/src/config.xml b/lib/kernel/doc/src/config.xml index c10f11b187..fdb2d29f63 100644 --- a/lib/kernel/doc/src/config.xml +++ b/lib/kernel/doc/src/config.xml @@ -4,7 +4,7 @@
    - 19972016 + 19972017 Ericsson AB. All Rights Reserved. diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index bef8096aed..070782e1f3 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -4,7 +4,7 @@
    - 19972016 + 19972017 Ericsson AB. All Rights Reserved. diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index 947e4d4560..b7c904ff45 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -4,7 +4,7 @@
    - 19972016 + 19972017 Ericsson AB. All Rights Reserved. diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index b342fff0d3..28af155493 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -4,7 +4,7 @@
    - 19962016 + 19962017 Ericsson AB. All Rights Reserved. diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 6d6367a2bd..7127a59a0c 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -4,7 +4,7 @@
    - 20042016 + 20042017 Ericsson AB. All Rights Reserved. diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml index 6ba69d12a3..64c5cbe571 100644 --- a/lib/kernel/doc/src/os.xml +++ b/lib/kernel/doc/src/os.xml @@ -4,7 +4,7 @@
    - 19972016 + 19972017 Ericsson AB. All Rights Reserved. diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml index b80e87c118..197851021f 100644 --- a/lib/kernel/doc/src/seq_trace.xml +++ b/lib/kernel/doc/src/seq_trace.xml @@ -4,7 +4,7 @@
    - 19982016 + 19982017 Ericsson AB. All Rights Reserved. diff --git a/lib/kernel/include/inet.hrl b/lib/kernel/include/inet.hrl index df788aca08..daa2e14b46 100644 --- a/lib/kernel/include/inet.hrl +++ b/lib/kernel/include/inet.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 2a06d0cb15..9969021a6c 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 2ade7fd77a..50a20c918c 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2015. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index 593dbb31ab..c9fda8bef5 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2015. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/dist_ac.erl b/lib/kernel/src/dist_ac.erl index e63c969b79..2a5cf0ba92 100644 --- a/lib/kernel/src/dist_ac.erl +++ b/lib/kernel/src/dist_ac.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index d929179715..1c326afca8 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl index 8f924d2adc..22f235d4e4 100644 --- a/lib/kernel/src/erl_signal_handler.erl +++ b/lib/kernel/src/erl_signal_handler.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. 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 diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index 3ee8e2c6e6..81f1bf8d97 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 79e72cdc6d..933f2d5f65 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index 5e8bc2ba5d..3d6415036c 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2015. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 5be790b7d9..6aef5476f1 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl index e6cd48935a..bc5b67f7bf 100644 --- a/lib/kernel/src/inet_int.hrl +++ b/lib/kernel/src/inet_int.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl index 9b47199e08..0f5dc40553 100644 --- a/lib/kernel/src/inet_parse.erl +++ b/lib/kernel/src/inet_parse.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl index c69791b9aa..1e624b9e90 100644 --- a/lib/kernel/src/inet_udp.erl +++ b/lib/kernel/src/inet_udp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 2dc90e2b3e..77085b2064 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-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl index b901da95b8..6e5022a405 100644 --- a/lib/kernel/src/kernel.erl +++ b/lib/kernel/src/kernel.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl index 9921a0adfd..ddda396713 100644 --- a/lib/kernel/src/net_kernel.erl +++ b/lib/kernel/src/net_kernel.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 7e83b17add..0250783632 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl index bd6ea26678..0e0b7dffa3 100644 --- a/lib/kernel/src/rpc.erl +++ b/lib/kernel/src/rpc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl index b4cf31b210..866043cfb4 100644 --- a/lib/kernel/test/application_SUITE.erl +++ b/lib/kernel/test/application_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 088d851b09..7831777726 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index 079cc2f90f..069df5a11d 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index ecfa3d6cdb..d7a9ac39a3 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl index c1dc208cc1..03aaee56b7 100644 --- a/lib/kernel/test/erl_distribution_wb_SUITE.erl +++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/error_logger_SUITE.erl b/lib/kernel/test/error_logger_SUITE.erl index bb01c2384d..2d26a7246c 100644 --- a/lib/kernel/test/error_logger_SUITE.erl +++ b/lib/kernel/test/error_logger_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index b402f01758..119e1f24bb 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl index b2051af050..899102c908 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index 86f6b95fb9..97f789b61c 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/multi_load_SUITE.erl b/lib/kernel/test/multi_load_SUITE.erl index 920839f4f9..f3258ea520 100644 --- a/lib/kernel/test/multi_load_SUITE.erl +++ b/lib/kernel/test/multi_load_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl index 9460608a3e..acecd34ead 100644 --- a/lib/kernel/test/pg2_SUITE.erl +++ b/lib/kernel/test/pg2_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2016. All Rights Reserved. +%% Copyright Ericsson AB 2008-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 0c84a7d1cc..2f4330c217 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/rpc_SUITE.erl b/lib/kernel/test/rpc_SUITE.erl index d76c4097d8..a89a7600a2 100644 --- a/lib/kernel/test/rpc_SUITE.erl +++ b/lib/kernel/test/rpc_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. -- cgit v1.2.3 From dc57404252c47520f352834ad9be45ad684f96c9 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Thu, 4 May 2017 17:05:25 +0200 Subject: Prepare release --- lib/kernel/doc/src/notes.xml | 84 ++++++++++++++++++++++++++++++++++++++++++++ lib/kernel/vsn.mk | 2 +- 2 files changed, 85 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 7127a59a0c..efb822f1b3 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,90 @@

    This document describes the changes made to the Kernel application.

    +
    Kernel 5.3 + +
    Fixed Bugs and Malfunctions + + +

    + Fix bug where gethostname would incorrectly fail with + enametoolong on Linux.

    +

    + Own Id: OTP-14310

    +
    +
    +
    + + +
    Improvements and New Features + + +

    + Since Unicode is now allowed in atoms an extra check is + needed for node names, which are restricted to Latin-1.

    +

    + Own Id: OTP-13805

    +
    + +

    Replaced usage of deprecated symbolic time + unit representations.

    +

    + Own Id: OTP-13831 Aux Id: OTP-13735

    +
    + +

    file:write_file(Name, Data, [raw]) would turn + Data into a single binary before writing. This + meant it could not take advantage of the writev() + system call if it was given a list of binaries and told + to write with raw mode.

    +

    + Own Id: OTP-13909

    +
    + +

    The performance of the disk_log has been + somewhat improved in some corner cases (big items), and + the documentation has been clarified.

    +

    + Own Id: OTP-14057 Aux Id: PR-1245

    +
    + +

    Functions for detecting changed code has been added. + code:modified_modules/0 returns all currently + loaded modules that have changed on disk. + code:module_status/1 returns the status for a + module. In the shell and in c module, mm/0 + is short for code:modified_modules/0, and + lm/0 reloads all currently loaded modules that + have changed on disk.

    +

    + Own Id: OTP-14059

    +
    + +

    + Introduce an event manager in Erlang to handle OS + signals. A subset of OS signals may be subscribed to and + those are described in the Kernel application.

    +

    + Own Id: OTP-14186

    +
    + +

    Sockets can now be bound to device (SO_BINDTODEVICE) + on platforms where it is supported.

    This has + been implemented e.g to support VRF-Lite under Linux; see + + VRF , and GitHub pull request #1326. +

    +

    + Own Id: OTP-14357 Aux Id: PR-1326

    +
    +
    +
    + +
    +
    Kernel 5.2
    Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 76b020e8ed..4edecd8969 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.2 +KERNEL_VSN = 5.3 -- cgit v1.2.3 From eace29905be436d77245656b2511c9a9c2c67c90 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Fri, 5 May 2017 13:15:42 +0200 Subject: Revert "Prepare release" This reverts commit dc57404252c47520f352834ad9be45ad684f96c9. --- lib/kernel/doc/src/notes.xml | 84 -------------------------------------------- lib/kernel/vsn.mk | 2 +- 2 files changed, 1 insertion(+), 85 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index efb822f1b3..7127a59a0c 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,90 +31,6 @@

    This document describes the changes made to the Kernel application.

    -
    Kernel 5.3 - -
    Fixed Bugs and Malfunctions - - -

    - Fix bug where gethostname would incorrectly fail with - enametoolong on Linux.

    -

    - Own Id: OTP-14310

    -
    -
    -
    - - -
    Improvements and New Features - - -

    - Since Unicode is now allowed in atoms an extra check is - needed for node names, which are restricted to Latin-1.

    -

    - Own Id: OTP-13805

    -
    - -

    Replaced usage of deprecated symbolic time - unit representations.

    -

    - Own Id: OTP-13831 Aux Id: OTP-13735

    -
    - -

    file:write_file(Name, Data, [raw]) would turn - Data into a single binary before writing. This - meant it could not take advantage of the writev() - system call if it was given a list of binaries and told - to write with raw mode.

    -

    - Own Id: OTP-13909

    -
    - -

    The performance of the disk_log has been - somewhat improved in some corner cases (big items), and - the documentation has been clarified.

    -

    - Own Id: OTP-14057 Aux Id: PR-1245

    -
    - -

    Functions for detecting changed code has been added. - code:modified_modules/0 returns all currently - loaded modules that have changed on disk. - code:module_status/1 returns the status for a - module. In the shell and in c module, mm/0 - is short for code:modified_modules/0, and - lm/0 reloads all currently loaded modules that - have changed on disk.

    -

    - Own Id: OTP-14059

    -
    - -

    - Introduce an event manager in Erlang to handle OS - signals. A subset of OS signals may be subscribed to and - those are described in the Kernel application.

    -

    - Own Id: OTP-14186

    -
    - -

    Sockets can now be bound to device (SO_BINDTODEVICE) - on platforms where it is supported.

    This has - been implemented e.g to support VRF-Lite under Linux; see - - VRF , and GitHub pull request #1326. -

    -

    - Own Id: OTP-14357 Aux Id: PR-1326

    -
    -
    -
    - -
    -
    Kernel 5.2
    Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 4edecd8969..76b020e8ed 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.3 +KERNEL_VSN = 5.2 -- cgit v1.2.3 From 513ea88e6c16e205cfb3c4164d1ca90b989d4ac7 Mon Sep 17 00:00:00 2001 From: Ben Tyler Date: Sat, 6 May 2017 22:09:50 +0200 Subject: Fix typo in child spec for file_server 'modeules' -> 'modules' Introduced in 3edc6dbf8f150bb6ba7c800ed5cc379771f8b279 (present in 20.0-rc1, but not in the 19 release series). --- lib/kernel/src/kernel.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl index 6e5022a405..cba57088ec 100644 --- a/lib/kernel/src/kernel.erl +++ b/lib/kernel/src/kernel.erl @@ -123,7 +123,7 @@ init([]) -> restart => permanent, shutdown => 2000, type => worker, - modeules => [file, file_server, file_io_server, prim_file]}, + modules => [file, file_server, file_io_server, prim_file]}, StdError = #{id => standard_error, start => {standard_error, start_link, []}, -- cgit v1.2.3 From 515d00c3f2a4d2fc4cd4eca0af870789d8632d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 12 May 2017 10:55:43 +0200 Subject: Don't crash in end_per_testcase/2 in code_SUITE:on_load_embedded/1 --- lib/kernel/test/code_SUITE.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 7831777726..afc32283ba 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -107,14 +107,19 @@ init_per_testcase(big_boot_embedded, Config) -> _Else -> {skip, "Needs crypto!"} end; -init_per_testcase(on_load_embedded, Config) -> +init_per_testcase(on_load_embedded, Config0) -> LibRoot = code:lib_dir(), LinkName = filename:join(LibRoot, "on_load_app-1.0"), - [{link_name,LinkName}|Config]; + Config = [{link_name,LinkName}|Config0], + init_per_testcase(Config); init_per_testcase(_Func, Config) -> + init_per_testcase(Config). + +init_per_testcase(Config) -> P = code:get_path(), [{code_path, P}|Config]. + end_per_testcase(module_status, Config) -> code:purge(?TESTMOD), code:delete(?TESTMOD), -- cgit v1.2.3 From 8a1138ddfec89b23c19d4d12d30dd575c678356b Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sat, 22 Apr 2017 17:36:29 -0400 Subject: Fix type declaration for disk_log.hrl A specific type was given as an atom rather than an actual type defintion. --- lib/kernel/src/disk_log.hrl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index c9fda8bef5..58f6155adf 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.hrl @@ -69,7 +69,7 @@ | {file, FileName :: file:filename()} | {linkto, LinkTo :: none | pid()} | {repair, Repair :: true | false | truncate} - | {type, Type :: dlog_type} + | {type, Type :: dlog_type()} | {format, Format :: dlog_format()} | {size, Size :: dlog_size()} | {distributed, Nodes :: [node()]} -- cgit v1.2.3 From ed4d30888beb58c27f61dcf86384696cc221be35 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sat, 13 May 2017 08:41:32 -0400 Subject: add option 'quiet' to disk_log This option allows to suppress output of info_msgs to error_logger when recoverable errors are encountered in disk_log by setting the value to 'true'. Defaults to 'false', the backwards compatible behaviour. --- lib/kernel/doc/src/disk_log.xml | 6 ++++++ lib/kernel/src/disk_log.erl | 5 ++++- lib/kernel/src/disk_log.hrl | 2 ++ lib/kernel/src/disk_log_1.erl | 28 ++++++++++++++++++++++------ lib/kernel/test/disk_log_SUITE.erl | 17 +++++++++++++++-- 5 files changed, 49 insertions(+), 9 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index aebeacee28..570d3ef9bd 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -968,6 +968,12 @@ read_write.

    + {quiet, Boolean} + +

    Specifies if messages will be sent to + error_logger on recoverable errors with + the log files. Defaults to true.

    +

    open/1 returns {ok, Log} if the log file is successfully opened. If the file is diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 50a20c918c..70cbf1c87c 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -638,6 +638,8 @@ check_arg([{mode, read_only}|Tail], Res) -> check_arg(Tail, Res#arg{mode = read_only}); check_arg([{mode, read_write}|Tail], Res) -> check_arg(Tail, Res#arg{mode = read_write}); +check_arg([{quiet, Boolean}|Tail], Res) when is_boolean(Boolean) -> + check_arg(Tail, Res#arg{quiet = Boolean}); check_arg(Arg, _) -> {error, {badarg, Arg}}. @@ -1276,7 +1278,8 @@ compare_arg(_Attr, _Val, _A) -> do_open(A) -> #arg{type = Type, format = Format, name = Name, head = Head0, file = FName, repair = Repair, size = Size, mode = Mode, - version = V} = A, + quiet = Quiet, version = V} = A, + disk_log_1:set_quiet(Quiet), Head = mk_head(Head0, Format), case do_open2(Type, Format, Name, FName, Repair, Size, Mode, Head, V) of {ok, Ret, Extra, FormatType, NoItems} -> diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index 58f6155adf..a362881f40 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.hrl @@ -76,6 +76,7 @@ | {notify, boolean()} | {head, Head :: dlog_head_opt()} | {head_func, MFA :: {atom(), atom(), list()}} + | {quiet, boolean()} | {mode, Mode :: dlog_mode()}. -type dlog_options() :: [dlog_option()]. -type dlog_repair() :: 'truncate' | boolean(). @@ -102,6 +103,7 @@ head = none, mode = read_write :: dlog_mode(), notify = false :: boolean(), + quiet = false :: boolean(), options = [] :: dlog_options()}). -record(cache, %% Cache for logged terms (per file descriptor). diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl index d83c30f35f..10c22e1ad6 100644 --- a/lib/kernel/src/disk_log_1.erl +++ b/lib/kernel/src/disk_log_1.erl @@ -37,6 +37,7 @@ -export([get_wrap_size/1]). -export([is_head/1]). -export([position/3, truncate_at/3, fwrite/4, fclose/2]). +-export([set_quiet/1, is_quiet/0]). -compile({inline,[{scan_f2,7}]}). @@ -500,7 +501,10 @@ lh(H, _F) -> % cannot happen repair(In, File) -> FSz = file_size(File), - error_logger:info_msg("disk_log: repairing ~tp ...\n", [File]), + case is_quiet() of + true -> ok; + _ -> error_logger:info_msg("disk_log: repairing ~tp ...\n", [File]) + end, Tmp = add_ext(File, "TMP"), {ok, {_Alloc, Out, {0, _}, _FileSize}} = new_int_file(Tmp, none), scan_f_read(<<>>, In, Out, File, FSz, Tmp, ?MAX_CHUNK_SIZE, 0, 0). @@ -769,8 +773,11 @@ mf_int_chunk(Handle, {FileNo, Pos}, Bin, N) -> NFileNo = inc(FileNo, Handle#handle.maxF), case catch int_open(FName, true, read_only, any) of {error, _Reason} -> - error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n", - [FName]), + case is_quiet() of + true -> ok; + _ -> error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n", + [FName]) + end, mf_int_chunk(Handle, {NFileNo, 0}, [], N); {ok, {_Alloc, FdC, _HeadSize, _FileSize}} -> case chunk(FdC, FName, Pos, Bin, N) of @@ -797,9 +804,12 @@ mf_int_chunk_read_only(Handle, {FileNo, Pos}, Bin, N) -> NFileNo = inc(FileNo, Handle#handle.maxF), case catch int_open(FName, true, read_only, any) of {error, _Reason} -> - error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n", - [FName]), - mf_int_chunk_read_only(Handle, {NFileNo, 0}, [], N); + case is_quiet() of + true -> ok; + _ -> error_logger:info_msg("disk_log: chunk error. File ~tp missing.\n\n", + [FName]) + end, + mf_int_chunk_read_only(Handle, {NFileNo, 0}, [], N); {ok, {_Alloc, FdC, _HeadSize, _FileSize}} -> case do_chunk_read_only(FdC, FName, Pos, Bin, N) of {NewFdC, eof} -> @@ -1549,6 +1559,12 @@ fclose(#cache{fd = Fd, c = C}, FileName) -> _ = write_cache_close(Fd, FileName, C), file:close(Fd). +set_quiet(Bool) -> + put(quiet, Bool). + +is_quiet() -> + get(quiet) =:= true. + %% -> {Reply, #cache{}}; Reply = ok | Error write_cache(Fd, _FileName, []) -> {ok, #cache{fd = Fd}}; diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index 069df5a11d..2b11a0381f 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -2493,6 +2493,7 @@ error_repair(Conf) when is_list(Conf) -> del(File, No), ok = file:del_dir(Dir), + error_logger:add_report_handler(?MODULE, self()), %% repair a file P1 = pps(), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, @@ -2509,6 +2510,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), true = (P1 == pps()), del(File, No), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% yet another repair P2 = pps(), @@ -2525,6 +2528,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), true = (P2 == pps()), del(File, No), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% Repair, large term Big = term_to_binary(lists:duplicate(66000,$a)), @@ -2540,6 +2545,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), Got = Big, del(File, No), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% A term a little smaller than a chunk, then big terms. BigSmall = mk_bytes(1024*64-8-12), @@ -2560,6 +2567,8 @@ error_repair(Conf) when is_list(Conf) -> {type, halt}, {format, internal}]), ok = disk_log:close(n), file:delete(File), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% The header is recovered. {ok,n} = @@ -2573,12 +2582,13 @@ error_repair(Conf) when is_list(Conf) -> crash(File, 30), {repaired,n,{recovered,3},{badbytes,15}} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal},{repair,true}, + {format, internal},{repair,true}, {quiet, true}, {head_func, {?MODULE, head_fun, [{ok,"head"}]}}]), ["head",'of',terms] = get_all_terms(n), ok = disk_log:close(n), - + error_logger:delete_report_handler(?MODULE), file:delete(File), + {messages, []} = process_info(self(), messages), ok. @@ -5007,6 +5017,9 @@ init(Tester) -> handle_event({error_report, _GL, {Pid, crash_report, Report}}, Tester) -> Tester ! {crash_report, Pid, Report}, {ok, Tester}; +handle_event({info_msg, _GL, {Pid, F,A}}, Tester) -> + Tester ! {info_msg, Pid, F, A}, + {ok, Tester}; handle_event(_Event, State) -> {ok, State}. -- cgit v1.2.3 From 4b9e1dd37f6e55ba1a04fad36d8ed3c0201b1942 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sat, 22 Apr 2017 17:39:08 -0400 Subject: Add persistence to history of the non-legacy shell This patch adds a mechanism by which shell history gets stored persistently on disk and gets loaded whenever a new shell session begins. The log files are added to the user's cache directory, with multiple files in it, although the location is configurable. All Erlang instances on a given host will share the same log file. There are two hook points in group.erl that are used: when instantiating the buffer, where we fetch from disk, and when adding a line to the buffer (gets stored). This allows all shell instances to use the same base set of lines when loaded, but to keep their history separate after the fact. As lines are added as you go, a new shell session (with ^G -> s -> c) will have access to previous sessions' lines. The implementation makes use of the disk_log library with a rotating log in order to store data, and allow automated repairs. By default, the feature is disabled and must be turned on through OTP environment variable part of the kernel application. The options include: | Option | Accepted values | Default | Description | | ------------------------ | ----------------- |---------- | -------------------- | | shell_history | enabled, disabled | disabled | turn feature on/off | | shell_history_path | any string | user cache| where to put files | | shell_history_file_bytes | 51200..N bytes | 512kb | max data size (>50kb)| | shell_history_drop | ["q().", ...] | [] | blacklisted lines | A version header is added to the disk_log configuration, allowing changes in the storage format to be enacted in the future (i.e. adding segmentation by node name in the same file, or encoding) without conflict. Log rotation is used with multiple log files to ensure proper enforcement of resizing without too much data loss. Because disk_log does not allow to just flush bits of content on rewrite (it truncates any full file), we instead use a wrap log and try to divide the configured size into up to 10 log files so that every time we rotate a log, we lose only 10% of the data. This remains true for corrupted files that cannot fully be repaired. This many-logs-based approach in turn forces the use of a minimal log size for the `shell_history_file_bytes` configuration, since it has to be divided by 10. The shell history is not loaded for the `user` process which, despite running the group.erl module, does not actually require history as it mostly just forwards IO protocol information. --- lib/kernel/doc/src/kernel_app.xml | 23 +++ lib/kernel/src/Makefile | 1 + lib/kernel/src/group.erl | 3 +- lib/kernel/src/group_history.erl | 341 ++++++++++++++++++++++++++++++++++++++ lib/kernel/src/kernel.app.src | 1 + 5 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 lib/kernel/src/group_history.erl (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 28af155493..9fccb4c7ac 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -419,6 +419,29 @@ MaxT = TickTime + TickTime / 4 using this service.

    Defaults to false.

    + shell_history = enabled | disabled + +

    Specifies whether shell history should be logged to disk + between usages of erl.

    +
    + shell_history_drop = [string()] + +

    Specific log lines that should not be persisted. For + example ["q().", "init:stop()."] will allow to + ignore commands that shut the node down. Defaults to + [].

    +
    + shell_history_file_bytes = integer() + +

    how many bytes the shell should remember. By default, the + value is set to 512kb, and the minimal value is 50kb.

    +
    + shell_history_path = string() + +

    Specifies where the shell history files will be stored. + defaults to the user's cache directory as returned by + filename:basedir(user_cache, "erlang-history").

    +
    shutdown_func = {Mod, Func}

    Where:

    diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile index 2a89faaf13..78aa6192a9 100644 --- a/lib/kernel/src/Makefile +++ b/lib/kernel/src/Makefile @@ -85,6 +85,7 @@ MODULES = \ global_group \ global_search \ group \ + group_history \ heart \ hipe_unified_loader \ inet \ diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl index b5e73117dd..0eeaaad8d2 100644 --- a/lib/kernel/src/group.erl +++ b/lib/kernel/src/group.erl @@ -33,7 +33,7 @@ start(Drv, Shell, Options) -> server(Drv, Shell, Options) -> process_flag(trap_exit, true), edlin:init(), - put(line_buffer, proplists:get_value(line_buffer, Options, [])), + put(line_buffer, proplists:get_value(line_buffer, Options, group_history:load())), put(read_mode, list), put(user_drv, Drv), put(expand_fun, @@ -783,6 +783,7 @@ save_line_buffer("\n", Lines) -> save_line_buffer(Line, [Line|_Lines]=Lines) -> save_line_buffer(Lines); save_line_buffer(Line, Lines) -> + group_history:add(Line), save_line_buffer([Line|Lines]). save_line_buffer(Lines) -> diff --git a/lib/kernel/src/group_history.erl b/lib/kernel/src/group_history.erl new file mode 100644 index 0000000000..5ca5e2d1dd --- /dev/null +++ b/lib/kernel/src/group_history.erl @@ -0,0 +1,341 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2017. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(group_history). +-export([load/0, add/1]). + +%% Make a minimal size that should encompass set of lines and then make +%% a file rotation for N files of this size. +-define(DEFAULT_HISTORY_FILE, "erlang-shell-log"). +-define(MAX_HISTORY_FILES, 10). +-define(DEFAULT_SIZE, 1024*512). % 512 kb total default +-define(DEFAULT_STATUS, disabled). +-define(MIN_HISTORY_SIZE, (50*1024)). % 50 kb, in bytes +-define(DEFAULT_DROP, []). +-define(DISK_LOG_FORMAT, internal). % since we want repairs +-define(LOG_NAME, '$#group_history'). +-define(VSN, {0,1,0}). + +%%%%%%%%%%%%%% +%%% PUBLIC %%% +%%%%%%%%%%%%%% + +%% @doc Loads the shell history from memory. This function should only be +%% called from group:server/3 to inject itself in the previous commands +%% stack. +-spec load() -> [string()]. +load() -> + wait_for_kernel_safe_sup(), + case history_status() of + enabled -> + case open_log() of + {ok, ?LOG_NAME} -> + read_full_log(?LOG_NAME); + {repaired, ?LOG_NAME, {recovered, Good}, {badbytes, Bad}} -> + report_repairs(?LOG_NAME, Good, Bad), + read_full_log(?LOG_NAME); + {error, {need_repair, _FileName}} -> + repair_log(?LOG_NAME); + {error, {arg_mismatch, repair, true, false}} -> + repair_log(?LOG_NAME); + {error, {name_already_open, _}} -> + show_rename_warning(), + read_full_log(?LOG_NAME); + {error, {size_mismatch, Current, New}} -> + show_size_warning(Current, New), + resize_log(?LOG_NAME, Current, New), + load(); + {error, {invalid_header, {vsn, Version}}} -> + upgrade_version(?LOG_NAME, Version), + load(); + {error, Reason} -> + handle_open_error(Reason), + disable_history(), + [] + end; + _ -> + [] + end. + +%% @doc adds a log line to the erlang history log, if configured to do so. +-spec add(iodata()) -> ok. +add(Line) -> add(Line, history_status()). + +add(Line, enabled) -> + case lists:member(Line, to_drop()) of + false -> + case disk_log:log(?LOG_NAME, Line) of + ok -> + ok; + {error, no_such_log} -> + _ = open_log(), % a wild attempt we hope works! + disk_log:log(?LOG_NAME, Line); + {error, _Other} -> + % just ignore, we're too late + ok + end; + true -> + ok + end; +add(_Line, disabled) -> + ok. + +%%%%%%%%%%%%%%% +%%% PRIVATE %%% +%%%%%%%%%%%%%%% + +%% Because loading the shell happens really damn early, processes we depend on +%% might not be there yet. Luckily, the load function is called from the shell +%% after a new process has been spawned, so we can block in here +wait_for_kernel_safe_sup() -> + case whereis(kernel_safe_sup) of + undefined -> + timer:sleep(50), + wait_for_kernel_safe_sup(); + _ -> + ok + end. + +%% Repair the log out of band +repair_log(Name) -> + Opts = lists:keydelete(size, 1, log_options()), + case disk_log:open(Opts) of + {repaired, ?LOG_NAME, {recovered, Good}, {badbytes, Bad}} -> + report_repairs(?LOG_NAME, Good, Bad); + _ -> + ok + end, + _ = disk_log:close(Name), + load(). + +%% Return whether the shell history is enabled or not +-spec history_status() -> enabled | disabled. +history_status() -> + case is_user() orelse application:get_env(kernel, shell_history) of + true -> disabled; % don't run for user proc + {ok, enabled} -> enabled; + undefined -> ?DEFAULT_STATUS; + _ -> disabled + end. + +%% Return whether the user process is running this +-spec is_user() -> boolean(). +is_user() -> + case process_info(self(), registered_name) of + {registered_name, user} -> true; + _ -> false + end. + +%% Open a disk_log file while ensuring the required path is there. +open_log() -> + Opts = log_options(), + _ = ensure_path(Opts), + disk_log:open(Opts). + +%% Return logger options +log_options() -> + Path = find_path(), + File = filename:join([Path, ?DEFAULT_HISTORY_FILE]), + Size = find_wrap_values(), + [{name, ?LOG_NAME}, + {file, File}, + {repair, true}, + {format, internal}, + {type, wrap}, + {size, Size}, + {distributed, []}, + {notify, false}, + {head, {vsn, ?VSN}}, + {quiet, true}, + {mode, read_write}]. + +-spec ensure_path([{file, string()} | {atom(), _}, ...]) -> ok | {error, term()}. +ensure_path(Opts) -> + {file, Path} = lists:keyfind(file, 1, Opts), + filelib:ensure_dir(Path). + +%% @private read the logs from an already open file. Treat closed files +%% as wrong and returns an empty list to avoid crash loops in the shell. +-spec read_full_log(term()) -> [string()]. +read_full_log(Name) -> + case disk_log:chunk(Name, start) of + {error, no_such_log} -> + show_unexpected_close_warning(), + []; + eof -> + []; + {Cont, Logs} -> + lists:reverse(maybe_drop_header(Logs) ++ read_full_log(Name, Cont)) + end. + +read_full_log(Name, Cont) -> + case disk_log:chunk(Name, Cont) of + {error, no_such_log} -> + show_unexpected_close_warning(), + []; + eof -> + []; + {NextCont, Logs} -> + maybe_drop_header(Logs) ++ read_full_log(Name, NextCont) + end. + +maybe_drop_header([{vsn, _} | Rest]) -> Rest; +maybe_drop_header(Logs) -> Logs. + +-spec handle_open_error(_) -> ok. +handle_open_error({arg_mismatch, OptName, CurrentVal, NewVal}) -> + show('$#erlang-history-arg-mismatch', + "Log file argument ~p changed value from ~p to ~p " + "and cannot be automatically updated. Please clear the " + "history files and try again.~n", + [OptName, CurrentVal, NewVal]); +handle_open_error({not_a_log_file, FileName}) -> + show_invalid_file_warning(FileName); +handle_open_error({invalid_index_file, FileName}) -> + show_invalid_file_warning(FileName); +handle_open_error({invalid_header, Term}) -> + show('$#erlang-history-invalid-header', + "Shell history expects to be able to use the log files " + "which currently have unknown headers (~p) and may belong to " + "another mechanism. History logging will be " + "disabled.~n", + [Term]); +handle_open_error({file_error, FileName, Reason}) -> + show('$#erlang-history-file-error', + "Error handling File ~s. Reason: ~p~n" + "History logging will be disabled.~n", + [FileName, Reason]); +handle_open_error(Err) -> + show_unexpected_warning({disk_log, open, 1}, Err). + +find_wrap_values() -> + ConfSize = case application:get_env(kernel, shell_history_file_bytes) of + undefined -> ?DEFAULT_SIZE; + {ok, S} -> S + end, + SizePerFile = max(?MIN_HISTORY_SIZE, ConfSize div ?MAX_HISTORY_FILES), + FileCount = if SizePerFile > ?MIN_HISTORY_SIZE -> + ?MAX_HISTORY_FILES + ; SizePerFile =< ?MIN_HISTORY_SIZE -> + max(1, ConfSize div SizePerFile) + end, + {SizePerFile, FileCount}. + +report_repairs(_, _, 0) -> + %% just a regular close repair + ok; +report_repairs(_, Good, Bad) -> + show('$#erlang-history-report-repairs', + "The shell history log file was corrupted and was repaired. " + "~p bytes were recovered and ~p were lost.~n", [Good, Bad]). + +resize_log(Name, _OldSize, NewSize) -> + show('$#erlang-history-resize-attempt', + "Attempting to resize the log history file to ~p...", [NewSize]), + Opts = lists:keydelete(size, 1, log_options()), + _ = case disk_log:open(Opts) of + {error, {need_repair, _}} -> + _ = repair_log(Name), + disk_log:open(Opts); + _ -> + ok + end, + case disk_log:change_size(Name, NewSize) of + ok -> + show('$#erlang-history-resize-result', + "ok~n", []); + {error, {new_size_too_small, _}} -> + show('$#erlang-history-resize-result', + "failed (new size is too small)~n", []), + disable_history(); + {error, Reason} -> + show('$#erlang-history-resize-result', + "failed (~p)~n", [Reason]), + disable_history() + end. + +upgrade_version(_Name, Unsupported) -> + %% We only know of one version and can't support a newer one + show('$#erlang-history-upgrade', + "The version for the shell logs found on disk (~p) is " + "not supported by the current version (~p)~n", + [Unsupported, ?VSN]), + disable_history(). + +disable_history() -> + show('$#erlang-history-disable', "Disabling shell history logging.~n", []), + application:set_env(kernel, shell_history, force_disabled). + +find_path() -> + case application:get_env(kernel, shell_history_path) of + undefined -> filename:basedir(user_cache, "erlang-history"); + {ok, Path} -> Path + end. + +to_drop() -> + case application:get_env(kernel, shell_history_drop) of + undefined -> + application:set_env(kernel, shell_history_drop, ?DEFAULT_DROP), + ?DEFAULT_DROP; + {ok, V} when is_list(V) -> [Ln++"\n" || Ln <- V]; + {ok, _} -> ?DEFAULT_DROP + end. + +%%%%%%%%%%%%%%%%%%%%%%%% +%%% Output functions %%% +%%%%%%%%%%%%%%%%%%%%%%%% +show_rename_warning() -> + show('$#erlang-history-rename-warn', + "A history file with a different path has already " + "been started for the shell of this node. The old " + "name will keep being used for this session.~n", + []). + +show_invalid_file_warning(FileName) -> + show('$#erlang-history-invalid-file', + "Shell history expects to be able to use the file ~s " + "which currently exists and is not a file usable for " + "history logging purposes. History logging will be " + "disabled.~n", [FileName]). + +show_unexpected_warning({M,F,A}, Term) -> + show('$#erlang-history-unexpected-return', + "unexpected return value from ~p:~p/~p: ~p~n" + "shell history will be disabled for this session.~n", + [M,F,A,Term]). + +show_unexpected_close_warning() -> + show('$#erlang-history-unexpected-close', + "The shell log file has mysteriousy closed. Ignoring " + "currently unread history.~n", []). + +show_size_warning(_Current, _New) -> + show('$#erlang-history-size', + "The configured log history file size is different from " + "the size of the log file on disk.~n", []). + +show(Key, Format, Args) -> + case get(Key) of + undefined -> + io:format(standard_error, Format, Args), + put(Key, true), + ok; + true -> + ok + end. diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 25e4ddd95c..1128ee3ec5 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -44,6 +44,7 @@ global_group, global_search, group, + group_history, heart, hipe_unified_loader, inet6_tcp, -- cgit v1.2.3 From f97921c7ea300ddfce3c37735a6373bd85e55da1 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 15 May 2017 14:27:00 +0200 Subject: kernel: Add error_logger:limit_term/1 Calling error_logger:limit_term/1 before sending terms as events to the error_logger can be used for limiting the size of the messages. Doing so will not change the output, but potentially save memory. The Kernel variable error_logger_format_depth is used when limiting the size of terms. --- lib/kernel/src/error_logger.erl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index 81f1bf8d97..93a3f4f2e5 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -31,6 +31,8 @@ handle_event/2, handle_call/2, handle_info/2, terminate/2]). +-export([limit_term/1]). + -define(buffer_size, 10). %%----------------------------------------------------------------- @@ -518,3 +520,19 @@ string_p1([H|T]) when is_list(H) -> end; string_p1([]) -> true; string_p1(_) -> false. + +-spec limit_term(term()) -> term(). + +limit_term(Term) -> + case get_depth() of + unlimited -> Term; + D -> io_lib:limit_term(Term, D) + end. + +get_depth() -> + case application:get_env(kernel, error_logger_format_depth) of + {ok, Depth} when is_integer(Depth) -> + max(10, Depth); + undefined -> + unlimited + end. -- cgit v1.2.3 From a99b0a2a570e7429b05f3ce424880744ee3a8814 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Wed, 17 May 2017 16:16:58 +0200 Subject: kernel: Introcude error_logger:get_format_depth() --- lib/kernel/doc/src/error_logger.xml | 15 ++++++++++++++- lib/kernel/src/error_logger.erl | 8 +++++--- 2 files changed, 19 insertions(+), 4 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index 814e8eac46..27db00819f 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -4,7 +4,7 @@
    - 19962016 + 19962017 Ericsson AB. All Rights Reserved. @@ -162,6 +162,19 @@ ok error_report/1.

    + + + Get the value of the Kernel application variable + error_logger_format_depth. + +

    Returns max(10, Depth), where Depth is the + value of + + error_logger_format_depth + in the Kernel application, if Depth is an integer. Otherwise, + unlimited is returned.

    +
    +
    diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index 93a3f4f2e5..9bf8547745 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -31,7 +31,7 @@ handle_event/2, handle_call/2, handle_info/2, terminate/2]). --export([limit_term/1]). +-export([get_format_depth/0, limit_term/1]). -define(buffer_size, 10). @@ -524,12 +524,14 @@ string_p1(_) -> false. -spec limit_term(term()) -> term(). limit_term(Term) -> - case get_depth() of + case get_format_depth() of unlimited -> Term; D -> io_lib:limit_term(Term, D) end. -get_depth() -> +-spec get_format_depth() -> 'unlimited' | pos_integer(). + +get_format_depth() -> case application:get_env(kernel, error_logger_format_depth) of {ok, Depth} when is_integer(Depth) -> max(10, Depth); -- cgit v1.2.3 From 40a5c8b1dd9e751488c11f47f8c6fe68a4e55aa2 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 19 May 2017 13:10:04 +0200 Subject: kernel: Create table 'global_names' with read_concurrency Measurements showed contention on one of the ETS tables created by the 'global' module. --- lib/kernel/src/global.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index 3d6415036c..a9e92b28b8 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -447,7 +447,8 @@ info() -> init([]) -> process_flag(trap_exit, true), _ = ets:new(global_locks, [set, named_table, protected]), - _ = ets:new(global_names, [set, named_table, protected]), + _ = ets:new(global_names, [set, named_table, protected, + {read_concurrency, true}]), _ = ets:new(global_names_ext, [set, named_table, protected]), _ = ets:new(global_pid_names, [bag, named_table, protected]), -- cgit v1.2.3 From 1d6ec21da2d91f4226fb42506299e782ccdb4644 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 22 May 2017 16:21:58 +0200 Subject: kernel: Skip ipv6 tcs when cpiv6 is disabled For some reason doing a gen_udp:open(0, [inet6,{ipv6_v6only,true}]) works on some systems where ipv6 is disabled. So instead we explicitly require the localhost ip to do the test at which seems to work better. ipv6 was disabled in sysctl using the line net.ipv6.conf.all.disable_ipv6=1 when this behaviour was found. --- lib/kernel/test/gen_tcp_api_SUITE.erl | 8 ++++---- lib/kernel/test/gen_udp_SUITE.erl | 4 ++-- lib/kernel/test/inet_sockopt_SUITE.erl | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index 92a74465b7..3f11e25b93 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -302,9 +302,9 @@ t_implicit_inet6(Config) when is_list(Config) -> end. t_implicit_inet6(Host, Addr) -> - case gen_tcp:listen(0, [inet6]) of + Loopback = {0,0,0,0,0,0,0,1}, + case gen_tcp:listen(0, [inet6, {ip,Loopback}]) of {ok,S1} -> - Loopback = {0,0,0,0,0,0,0,1}, io:format("~s ~p~n", ["::1",Loopback]), implicit_inet6(S1, Loopback), ok = gen_tcp:close(S1), @@ -524,10 +524,10 @@ local_handshake(S, SAddr, C, CAddr) -> t_accept_inet6_tclass(Config) when is_list(Config) -> TClassOpt = {tclass,8#56 bsl 2}, % Expedited forwarding - case gen_tcp:listen(0, [inet6,TClassOpt]) of + Loopback = {0,0,0,0,0,0,0,1}, + case gen_tcp:listen(0, [inet6, {ip, Loopback}, TClassOpt]) of {ok,L} -> LPort = ok(inet:port(L)), - Loopback = {0,0,0,0,0,0,0,1}, Sa = ok(gen_tcp:connect(Loopback, LPort, [])), Sb = ok(gen_tcp:accept(L)), [TClassOpt] = ok(inet:getopts(Sb, [tclass])), diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl index 1029d7ef0a..836e0c5a05 100644 --- a/lib/kernel/test/gen_udp_SUITE.erl +++ b/lib/kernel/test/gen_udp_SUITE.erl @@ -717,9 +717,9 @@ implicit_inet6(Config) when is_list(Config) -> implicit_inet6(Host, Addr) -> Active = {active,false}, - case gen_udp:open(0, [inet6,Active]) of + Loopback = {0,0,0,0,0,0,0,1}, + case gen_udp:open(0, [inet6,Active,{ip, Loopback}]) of {ok,S1} -> - Loopback = {0,0,0,0,0,0,0,1}, io:format("~s ~p~n", ["::1",Loopback]), implicit_inet6(S1, Active, Loopback), ok = gen_udp:close(S1), diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl index 322b9f30fe..9413cbd976 100644 --- a/lib/kernel/test/inet_sockopt_SUITE.erl +++ b/lib/kernel/test/inet_sockopt_SUITE.erl @@ -620,7 +620,7 @@ ipv6_v6only_close(Module, Socket) -> %% Test using socket option ipv6_v6only for UDP. use_ipv6_v6only_udp(Config) when is_list(Config) -> - case gen_udp:open(0, [inet6,{ipv6_v6only,true}]) of + case gen_udp:open(0, [inet6,{ip,{0,0,0,0,0,0,0,1}}, {ipv6_v6only,true}]) of {ok,S6} -> case inet:getopts(S6, [ipv6_v6only]) of {ok,[{ipv6_v6only,true}]} -> -- cgit v1.2.3 From d4bac182e5395ec2d0f4da5b9487488cb4a40707 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 22 May 2017 11:47:23 +0200 Subject: kernel: Add doc link from os man page to signal service --- lib/kernel/doc/src/kernel_app.xml | 1 + lib/kernel/doc/src/os.xml | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 9fccb4c7ac..75e1e18d86 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -58,6 +58,7 @@
    + OS Signal Event Handler

    Asynchronous OS signals may be subscribed to via the Kernel applications event manager (see OTP Design Principles and diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml index 64c5cbe571..0e9add4161 100644 --- a/lib/kernel/doc/src/os.xml +++ b/lib/kernel/doc/src/os.xml @@ -174,8 +174,9 @@ DirOut = os:cmd("dir"), % on Win32 platform handle - This signal will notify erl_signal_server when it is received by - the Erlang runtime system. + This signal will notify + erl_signal_server + when it is received by the Erlang runtime system. -- cgit v1.2.3 From 30f4fc6963e5793368713897f32afd2172dc1578 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 18 May 2017 16:11:11 +0200 Subject: otp: Extend secure distribution docs warnings Warnings have been added to the relevant documentation about not using un-secure distributed nodes in exposed environments. --- lib/kernel/doc/src/net_kernel.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml index 4e2b0c69db..7ddb849824 100644 --- a/lib/kernel/doc/src/net_kernel.xml +++ b/lib/kernel/doc/src/net_kernel.xml @@ -64,6 +64,19 @@ $ erl -sname foobar by the magic cookie system, see section Distributed Erlang in the Erlang Reference Manual.

    + +

    + Starting a distributed node without also specifying + -proto_dist inet_tls + will expose the node to attacks that may give the attacker + complete access to the node and in extension the cluster. + When using un-secure distributed nodes, make sure that the + network is configured to keep potential attackers out. + See the + Using SSL for Erlang Distribution User's Guide + for details on how to setup a secure distributed node. +

    +
    -- cgit v1.2.3 From 2fa8ade78ef987ad1f3ab42bed691ebfcf29d29d Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 23 May 2017 15:06:04 +0200 Subject: kernel: Add early reject of invalid node names --- lib/kernel/src/dist_util.erl | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index 1c326afca8..b3507e5d13 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -572,12 +572,25 @@ recv_name(#hs_data{socket = Socket, f_recv = Recv}) -> ?shutdown(no_node) end. -get_name([$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 | OtherNode]) -> - {?u32(Flag1, Flag2, Flag3, Flag4), list_to_atom(OtherNode), - ?u16(VersionA,VersionB)}; +get_name([$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 | OtherNode] = Data) -> + case is_valid_name(OtherNode) of + true -> + {?u32(Flag1, Flag2, Flag3, Flag4), list_to_atom(OtherNode), + ?u16(VersionA,VersionB)}; + false -> + ?shutdown(Data) + end; get_name(Data) -> ?shutdown(Data). +is_valid_name(OtherNodeName) -> + case string:lexemes(OtherNodeName,"@") of + [_OtherNodeName,_OtherNodeHost] -> + true; + _else -> + false + end. + publish_type(Flags) -> case Flags band ?DFLAG_PUBLISHED of 0 -> -- cgit v1.2.3 From 967a7deaaee2782fb91c8af592096c6b39c666f8 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 23 May 2017 17:35:49 +0200 Subject: kernel: Make sure to cleanup after distr tests Because this test suite did not cleanup after itself, the error_logger_warn_SUITE:file_utc failed to start its node that it needed for the test. --- lib/kernel/test/erl_distribution_SUITE.erl | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index d7a9ac39a3..bbfaa9d147 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -230,7 +230,7 @@ legal(Name) -> end. illegal(Name) -> - case test_node(Name) of + case test_node(Name, true) of not_started -> ok; started -> @@ -238,12 +238,20 @@ illegal(Name) -> end. test_node(Name) -> + test_node(Name, false). +test_node(Name, Illigal) -> ProgName = atom_to_list(lib:progname()), Command = ProgName ++ " -noinput " ++ long_or_short() ++ Name ++ - " -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"", + " -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"" ++ + case Illigal of + true -> + " -eval \"timer:sleep(10000),init:stop().\""; + false -> + "" + end, net_kernel:monitor_nodes(true), BinCommand = unicode:characters_to_binary(Command, utf8), - open_port({spawn, BinCommand}, [stream]), + Prt = open_port({spawn, BinCommand}, [stream]), Node = list_to_atom(Name), receive {nodeup, Node} -> -- cgit v1.2.3 From 7ba1983bb5b5cd0d391a5ba944d1fd28ae4187d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 24 May 2017 10:43:35 +0200 Subject: Stop the cover server after running code_SUITE:module_status/1 Leaving the cover server running could cause problems in other test cases. --- lib/kernel/test/code_SUITE.erl | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'lib/kernel') diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index afc32283ba..6f8e949aac 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -1791,6 +1791,19 @@ do_normalized_paths([]) -> %% Test that module_status/1 behaves as expected module_status(_Config) -> + case test_server:is_cover() of + true -> + module_status(); + false -> + %% Make sure that we terminate the cover server. + try + module_status() + after + cover:stop() + end + end. + +module_status() -> %% basics not_loaded = code:module_status(fubar), % nonexisting {file, preloaded} = code:is_loaded(erlang), -- cgit v1.2.3 From eaf8ca41dfa4850437ad270d3897399c9358ced0 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 30 May 2017 16:15:30 +0200 Subject: Prepare release --- lib/kernel/doc/src/notes.xml | 135 +++++++++++++++++++++++++++++++++++++++++++ lib/kernel/vsn.mk | 2 +- 2 files changed, 136 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 7127a59a0c..975518d791 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,141 @@

    This document describes the changes made to the Kernel application.

    +
    Kernel 5.3 + +
    Fixed Bugs and Malfunctions + + +

    + Fix bug where gethostname would incorrectly fail with + enametoolong on Linux.

    +

    + Own Id: OTP-14310

    +
    + +

    + Fix bug causing code:is_module_native to falsely + return true when local call trace is enabled for + the module.

    +

    + Own Id: OTP-14390

    +
    + +

    + Add early reject of invalid node names from distributed + nodes.

    +

    + Own Id: OTP-14426

    +
    +
    +
    + + +
    Improvements and New Features + + +

    + Since Unicode is now allowed in atoms an extra check is + needed for node names, which are restricted to Latin-1.

    +

    + Own Id: OTP-13805

    +
    + +

    Replaced usage of deprecated symbolic time + unit representations.

    +

    + Own Id: OTP-13831 Aux Id: OTP-13735

    +
    + +

    file:write_file(Name, Data, [raw]) would turn + Data into a single binary before writing. This + meant it could not take advantage of the writev() + system call if it was given a list of binaries and told + to write with raw mode.

    +

    + Own Id: OTP-13909

    +
    + +

    The performance of the disk_log has been + somewhat improved in some corner cases (big items), and + the documentation has been clarified.

    +

    + Own Id: OTP-14057 Aux Id: PR-1245

    +
    + +

    Functions for detecting changed code has been added. + code:modified_modules/0 returns all currently + loaded modules that have changed on disk. + code:module_status/1 returns the status for a + module. In the shell and in c module, mm/0 + is short for code:modified_modules/0, and + lm/0 reloads all currently loaded modules that + have changed on disk.

    +

    + Own Id: OTP-14059

    +
    + +

    + Introduce an event manager in Erlang to handle OS + signals. A subset of OS signals may be subscribed to and + those are described in the Kernel application.

    +

    + Own Id: OTP-14186

    +
    + +

    Sockets can now be bound to device (SO_BINDTODEVICE) + on platforms where it is supported.

    This has + been implemented e.g to support VRF-Lite under Linux; see + + VRF , and GitHub pull request #1326. +

    +

    + Own Id: OTP-14357 Aux Id: PR-1326

    +
    + +

    + Added option to store shell_history on disk so that the + history can be reused between sessions.

    +

    + Own Id: OTP-14409 Aux Id: PR-1420

    +
    + +

    The size of crash reports created by + gen_server, gen_statem and proc_lib + is limited with aid of the Kernel application variable + error_logger_format_depth. The purpose is to limit + the size of the error_logger process when + processes with huge message queues or states crash.

    +

    The new function + error_logger:get_format_depth/0 can be used to + retrieve the value of the Kernel application variable + error_logger_format_depth.

    +

    + Own Id: OTP-14417

    +
    + +

    One of the ETS tables used by the global + module is created with {read_concurrency, true} in + order to reduce contention.

    +

    + Own Id: OTP-14419

    +
    + +

    + Warnings have been added to the relevant documentation + about not using un-secure distributed nodes in exposed + environments.

    +

    + Own Id: OTP-14425

    +
    +
    +
    + +
    +
    Kernel 5.2
    Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 76b020e8ed..4edecd8969 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.2 +KERNEL_VSN = 5.3 -- cgit v1.2.3 From 32275a2fc0b86d1f1b124706afc80f3ff92216eb Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 31 May 2017 16:21:00 +0200 Subject: Revert "Prepare release" This reverts commit eaf8ca41dfa4850437ad270d3897399c9358ced0. --- lib/kernel/doc/src/notes.xml | 135 ------------------------------------------- lib/kernel/vsn.mk | 2 +- 2 files changed, 1 insertion(+), 136 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 975518d791..7127a59a0c 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,141 +31,6 @@

    This document describes the changes made to the Kernel application.

    -
    Kernel 5.3 - -
    Fixed Bugs and Malfunctions - - -

    - Fix bug where gethostname would incorrectly fail with - enametoolong on Linux.

    -

    - Own Id: OTP-14310

    -
    - -

    - Fix bug causing code:is_module_native to falsely - return true when local call trace is enabled for - the module.

    -

    - Own Id: OTP-14390

    -
    - -

    - Add early reject of invalid node names from distributed - nodes.

    -

    - Own Id: OTP-14426

    -
    -
    -
    - - -
    Improvements and New Features - - -

    - Since Unicode is now allowed in atoms an extra check is - needed for node names, which are restricted to Latin-1.

    -

    - Own Id: OTP-13805

    -
    - -

    Replaced usage of deprecated symbolic time - unit representations.

    -

    - Own Id: OTP-13831 Aux Id: OTP-13735

    -
    - -

    file:write_file(Name, Data, [raw]) would turn - Data into a single binary before writing. This - meant it could not take advantage of the writev() - system call if it was given a list of binaries and told - to write with raw mode.

    -

    - Own Id: OTP-13909

    -
    - -

    The performance of the disk_log has been - somewhat improved in some corner cases (big items), and - the documentation has been clarified.

    -

    - Own Id: OTP-14057 Aux Id: PR-1245

    -
    - -

    Functions for detecting changed code has been added. - code:modified_modules/0 returns all currently - loaded modules that have changed on disk. - code:module_status/1 returns the status for a - module. In the shell and in c module, mm/0 - is short for code:modified_modules/0, and - lm/0 reloads all currently loaded modules that - have changed on disk.

    -

    - Own Id: OTP-14059

    -
    - -

    - Introduce an event manager in Erlang to handle OS - signals. A subset of OS signals may be subscribed to and - those are described in the Kernel application.

    -

    - Own Id: OTP-14186

    -
    - -

    Sockets can now be bound to device (SO_BINDTODEVICE) - on platforms where it is supported.

    This has - been implemented e.g to support VRF-Lite under Linux; see - - VRF , and GitHub pull request #1326. -

    -

    - Own Id: OTP-14357 Aux Id: PR-1326

    -
    - -

    - Added option to store shell_history on disk so that the - history can be reused between sessions.

    -

    - Own Id: OTP-14409 Aux Id: PR-1420

    -
    - -

    The size of crash reports created by - gen_server, gen_statem and proc_lib - is limited with aid of the Kernel application variable - error_logger_format_depth. The purpose is to limit - the size of the error_logger process when - processes with huge message queues or states crash.

    -

    The new function - error_logger:get_format_depth/0 can be used to - retrieve the value of the Kernel application variable - error_logger_format_depth.

    -

    - Own Id: OTP-14417

    -
    - -

    One of the ETS tables used by the global - module is created with {read_concurrency, true} in - order to reduce contention.

    -

    - Own Id: OTP-14419

    -
    - -

    - Warnings have been added to the relevant documentation - about not using un-secure distributed nodes in exposed - environments.

    -

    - Own Id: OTP-14425

    -
    -
    -
    - -
    -
    Kernel 5.2
    Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 4edecd8969..76b020e8ed 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.3 +KERNEL_VSN = 5.2 -- cgit v1.2.3 From 95ebfa0b19bd4b1cac8a0eb98e775517ebb2ca6d Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 30 May 2017 17:19:45 +0200 Subject: Update inet:ntoa according to modern RFCs --- lib/kernel/src/inet_parse.erl | 24 +++++-- lib/kernel/test/inet_SUITE.erl | 158 +++++++++++++++++++++++++++-------------- 2 files changed, 123 insertions(+), 59 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl index 0f5dc40553..f150521e92 100644 --- a/lib/kernel/src/inet_parse.erl +++ b/lib/kernel/src/inet_parse.erl @@ -714,7 +714,13 @@ ntoa({0,0,0,0,0,0,0,1}) -> "::1"; ntoa({0,0,0,0,0,0,A,B}) -> "::" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); %% IPV4 non ipv6 host address ntoa({0,0,0,0,0,16#ffff,A,B}) -> - "::FFFF:" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); + "::ffff:" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); +%% RFC 2765 IPv4-translated address +ntoa({0,0,0,0,16#ffff,0,A,B}) -> + "::ffff:0:" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); +%% RFC 6052 Well-known Prefix address +ntoa({16#64,16#ff9b,0,0,0,0,A,B}) -> + "64:ff9b::" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); ntoa({_,_,_,_,_,_,_,_}=T) -> %% Find longest sequence of zeros, at least 2, to replace with "::" ntoa(tuple_to_list(T), []); @@ -780,9 +786,19 @@ dig_to_dec(X) -> integer_to_list((X bsr 8) band 16#ff) ++ "." ++ integer_to_list(X band 16#ff). -%% Convert a integer to hex string -dig_to_hex(X) -> - erlang:integer_to_list(X, 16). +%% Convert a integer to hex string (lowercase) +dig_to_hex(0) -> "0"; +dig_to_hex(X) when is_integer(X), 0 < X -> + dig_to_hex(X, ""). +%% +dig_to_hex(0, Acc) -> Acc; +dig_to_hex(X, Acc) -> + dig_to_hex( + X bsr 4, + [case X band 15 of + D when D < 10 -> D + $0; + D -> D - 10 + $a + end|Acc]). %% %% Count number of '.' in a name diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index 97f789b61c..1d4efe17a5 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -447,91 +447,126 @@ parse_hosts(Config) when is_list(Config) -> inet_parse:resolv(ResolvErr1). parse_address(Config) when is_list(Config) -> - V4Strict = + V4Reversable = [{{0,0,0,0},"0.0.0.0"}, - {{1,2,3,4},"1.2.3.4"}, + {{1,2,3,4},"1.2.3.4"}, {{253,252,251,250},"253.252.251.250"}, {{1,2,255,254},"1.2.255.254"}], - V6Strict = + V6Reversable = [{{0,0,0,0,0,0,0,0},"::"}, + {{0,0,0,0,0,0,0,1},"::1"}, + {{0,0,0,0,0,0,0,2},"::0.0.0.2"}, {{15,0,0,0,0,0,0,2},"f::2"}, - {{15,16#f11,0,0,0,0,256,2},"f:f11::0100:2"}, - {{0,0,0,0,0,0,0,16#17},"::17"}, - {{16#700,0,0,0,0,0,0,0},"0700::"}, - {{0,0,0,0,0,0,2,1},"::2:1"}, + {{15,16#f11,0,0,0,0,256,2},"f:f11::100:2"}, + {{16#700,0,0,0,0,0,0,0},"700::"}, + {{0,0,0,0,0,0,2,1},"::0.2.0.1"}, {{0,0,0,0,0,3,2,1},"::3:2:1"}, {{0,0,0,0,4,3,2,1},"::4:3:2:1"}, {{0,0,0,5,4,3,2,1},"::5:4:3:2:1"}, {{0,0,6,5,4,3,2,1},"::6:5:4:3:2:1"}, - {{0,7,6,5,4,3,2,1},"::7:6:5:4:3:2:1"}, + {{0,7,6,5,4,3,2,1},"0:7:6:5:4:3:2:1"}, {{7,0,0,0,0,0,0,0},"7::"}, {{7,6,0,0,0,0,0,0},"7:6::"}, {{7,6,5,0,0,0,0,0},"7:6:5::"}, {{7,6,5,4,0,0,0,0},"7:6:5:4::"}, {{7,6,5,4,3,0,0,0},"7:6:5:4:3::"}, {{7,6,5,4,3,2,0,0},"7:6:5:4:3:2::"}, - {{7,6,5,4,3,2,1,0},"7:6:5:4:3:2:1::"}, + {{7,6,5,4,3,2,1,0},"7:6:5:4:3:2:1:0"}, + {{0,0,6,5,4,3,0,0},"::6:5:4:3:0:0"}, + {{0,0,6,5,4,0,0,0},"0:0:6:5:4::"}, + {{8,0,0,5,4,0,0,1},"8::5:4:0:0:1"}, + {{8,0,0,5,0,0,0,1},"8:0:0:5::1"}, + {{0,7,6,5,4,3,2,0},"0:7:6:5:4:3:2:0"}, + {{0,0,6,5,4,3,0,0},"::6:5:4:3:0:0"}, + {{0,0,0,5,4,0,0,0},"::5:4:0:0:0"}, + {{0,0,0,0,4,0,0,0},"::4:0:0:0"}, + {{0,0,0,5,0,0,0,0},"0:0:0:5::"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22:5c33:c440:55c0:c66c:77:0088"}, + "c11:c22:5c33:c440:55c0:c66c:77:88"}, + {{0,16#c22,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, + "0:c22:5c33:c440:55c0:c66c:77:88"}, {{16#c11,0,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11::5c33:c440:55c0:c66c:77:0088"}, + "c11:0:5c33:c440:55c0:c66c:77:88"}, {{16#c11,16#c22,0,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22::c440:55c0:c66c:77:0088"}, + "c11:c22:0:c440:55c0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,0,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22:5c33::55c0:c66c:77:0088"}, + "c11:c22:5c33:0:55c0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,0,16#c66c,16#77,16#88}, - "c11:0c22:5c33:c440::c66c:77:0088"}, + "c11:c22:5c33:c440:0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,0,16#77,16#88}, - "c11:0c22:5c33:c440:55c0::77:0088"}, + "c11:c22:5c33:c440:55c0:0:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,0,16#88}, - "c11:0c22:5c33:c440:55c0:c66c::0088"}, + "c11:c22:5c33:c440:55c0:c66c:0:88"}, + {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,16#77,0}, + "c11:c22:5c33:c440:55c0:c66c:77:0"}, + {{0,0,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, + "::5c33:c440:55c0:c66c:77:88"}, {{16#c11,0,0,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11::c440:55c0:c66c:77:0088"}, + "c11::c440:55c0:c66c:77:88"}, {{16#c11,16#c22,0,0,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22::55c0:c66c:77:0088"}, + "c11:c22::55c0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,0,0,16#c66c,16#77,16#88}, - "c11:0c22:5c33::c66c:77:0088"}, + "c11:c22:5c33::c66c:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,0,0,16#77,16#88}, - "c11:0c22:5c33:c440::77:0088"}, + "c11:c22:5c33:c440::77:88"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,0,0,16#88}, - "c11:0c22:5c33:c440:55c0::0088"}, + "c11:c22:5c33:c440:55c0::88"}, + {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,0,0}, + "c11:c22:5c33:c440:55c0:c66c::"}, + {{0,0,0,16#c440,16#55c0,16#c66c,16#77,16#88}, + "::c440:55c0:c66c:77:88"}, {{16#c11,0,0,0,16#55c0,16#c66c,16#77,16#88}, - "c11::55c0:c66c:77:0088"}, + "c11::55c0:c66c:77:88"}, {{16#c11,16#c22,0,0,0,16#c66c,16#77,16#88}, - "c11:0c22::c66c:77:0088"}, + "c11:c22::c66c:77:88"}, {{16#c11,16#c22,16#5c33,0,0,0,16#77,16#88}, - "c11:0c22:5c33::77:0088"}, + "c11:c22:5c33::77:88"}, {{16#c11,16#c22,16#5c33,16#c440,0,0,0,16#88}, - "c11:0c22:5c33:c440::0088"}, + "c11:c22:5c33:c440::88"}, + {{16#c11,16#c22,16#5c33,16#c440,16#55c0,0,0,0}, + "c11:c22:5c33:c440:55c0::"}, + {{0,0,0,0,16#55c0,16#c66c,16#77,16#88}, + "::55c0:c66c:77:88"}, {{16#c11,0,0,0,0,16#c66c,16#77,16#88}, - "c11::c66c:77:0088"}, + "c11::c66c:77:88"}, {{16#c11,16#c22,0,0,0,0,16#77,16#88}, - "c11:0c22::77:0088"}, + "c11:c22::77:88"}, {{16#c11,16#c22,16#5c33,0,0,0,0,16#88}, - "c11:0c22:5c33::0088"}, + "c11:c22:5c33::88"}, + {{16#c11,16#c22,16#5c33,16#c440,0,0,0,0}, + "c11:c22:5c33:c440::"}, + {{0,0,0,0,0,16#c66c,16#77,16#88}, + "::c66c:77:88"}, {{16#c11,0,0,0,0,0,16#77,16#88}, - "c11::77:0088"}, + "c11::77:88"}, {{16#c11,16#c22,0,0,0,0,0,16#88}, - "c11:0c22::0088"}, - {{0,0,0,0,0,65535,258,65534},"::FFFF:1.2.255.254"}, + "c11:c22::88"}, + {{16#c11,16#c22,16#5c33,0,0,0,0,0}, + "c11:c22:5c33::"}, + {{0,0,0,0,0,65535,258,65534},"::ffff:1.2.255.254"}, {{16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff}, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"} - |[{{D2,0,0,0,0,P,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4}, - erlang:integer_to_list(D2, 16)++"::"++Q++S} - || {{D1,D2,D3,D4},S} <- V4Strict, - {P,Q} <- [{0,""},{16#17,"17:"},{16#ff0,"0ff0:"}]]], + |[{list_to_tuple(P++[(D1 bsl 8) bor D2,(D3 bsl 8) bor D4]), + Q++S} + || {{D1,D2,D3,D4},S} <- + tl(V4Reversable), + {P,Q} <- + [{[0,0,0,0,0,16#ffff],"::ffff:"}, + {[0,0,0,0,16#ffff,0],"::ffff:0:"}, + {[16#64,16#ff9b,0,0,0,0],"64:ff9b::"}, + {[0,0,0,0,0,0],"::"}]]], V4Sloppy = [{{10,1,16#98,16#76},"10.0x019876"}, {{8#12,1,8#130,8#321},"012.01.054321"}, - {{255,255,255,255},"255.255.255.0377"}, - {{255,255,255,255},"0Xff.000000000377.0x0000ff.255"}, - {{255,255,255,255},"255.255.65535"}, - {{255,255,255,255},"255.0xFF.0177777"}, - {{255,255,255,255},"255.16777215"}, - {{255,255,255,255},"00377.0XFFFFFF"}, - {{255,255,255,255},"4294967295"}, - {{255,255,255,255},"0xffffffff"}, - {{255,255,255,255},"00000000000037777777777"}, + {{252,253,254,255},"252.253.254.0377"}, + {{252,253,254,255},"0Xfc.000000000375.0x0000fe.255"}, + {{252,253,254,255},"252.253.65279"}, + {{252,253,254,255},"252.0xFD.0177377"}, + {{252,253,254,255},"252.16645887"}, + {{252,253,254,255},"00374.0XFDFEFF"}, + {{252,253,254,255},"4244504319"}, + {{252,253,254,255},"0xfcfdfeff"}, + {{252,253,254,255},"00000000000037477377377"}, {{16#12,16#34,16#56,16#78},"0x12345678"}, {{16#12,16#34,16#56,16#78},"0x12.0x345678"}, {{16#12,16#34,16#56,16#78},"0x12.0X34.0x5678"}, @@ -543,8 +578,13 @@ parse_address(Config) when is_list(Config) -> {{0,0,0,0},"0.00.0.0"}, {{0,0,0,0},"0.0.000000000000.0"}], V6Sloppy = - [{{0,0,0,0,0,65535,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4},S} - || {{D1,D2,D3,D4},S} <- V4Strict++V4Sloppy], + [{{16#a,16#b,16#c,16#0,16#0,16#d,16#e,16#f},"A:B:C::d:e:f"}] + ++ + [{{P,0,0,0,0,D2,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4}, + Q++erlang:integer_to_list(D2, 16)++":"++S} + || {{D1,D2,D3,D4},S} <- V4Reversable, + {P,Q} <- + [{16#2001,"2001::"},{16#177,"177::"},{16#ff0,"Ff0::"}]], V4Err = ["0.256.0.1", "1.2.3.4.5", @@ -588,28 +628,36 @@ parse_address(Config) when is_list(Config) -> "fec0::fFfF:127.0.0.1."], t_parse_address (parse_ipv6_address, - V6Strict++V6Sloppy++V6Err++V4Err), + false, + V6Reversable++V6Sloppy++V6Err++V4Err), t_parse_address (parse_ipv6strict_address, - V6Strict++V6Err++V4Err++[S || {_,S} <- V6Sloppy]), + true, + V6Reversable++V6Err++V4Err), t_parse_address (parse_ipv4_address, - V4Strict++V4Sloppy++V4Err++V6Err++[S || {_,S} <- V6Strict]), + false, + V4Reversable++V4Sloppy++V4Err++V6Err++[S || {_,S} <- V6Reversable]), t_parse_address (parse_ipv4strict_address, - V4Strict++V4Err++V6Err++[S || {_,S} <- V4Sloppy++V6Strict]). + true, + V4Reversable++V4Err++V6Err++[S || {_,S} <- V4Sloppy++V6Reversable]). -t_parse_address(Func, []) -> +t_parse_address(Func, _Reversable, []) -> io:format("~p done.~n", [Func]), ok; -t_parse_address(Func, [{Addr,String}|L]) -> +t_parse_address(Func, Reversable, [{Addr,String}|L]) -> io:format("~p = ~p.~n", [Addr,String]), {ok,Addr} = inet:Func(String), - t_parse_address(Func, L); -t_parse_address(Func, [String|L]) -> + case Reversable of + true ->String = inet:ntoa(Addr); + false -> ok + end, + t_parse_address(Func, Reversable, L); +t_parse_address(Func, Reversable, [String|L]) -> io:format("~p.~n", [String]), {error,einval} = inet:Func(String), - t_parse_address(Func, L). + t_parse_address(Func, Reversable, L). parse_strict_address(Config) when is_list(Config) -> {ok, {127,0,0,1}} = -- cgit v1.2.3 From 923f9ac453af420eda69c4727b3b29ae7a91f2f1 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 22 May 2017 15:15:27 +0200 Subject: kernel: Iterate for correct time in os_SUITE:perf_counter --- lib/kernel/test/os_SUITE.erl | 47 +++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 3cbb75a633..1233e362f2 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -319,31 +319,38 @@ perf_counter_api(_Config) -> true = is_integer(os:perf_counter()), true = os:perf_counter() > 0, - T1 = os:perf_counter(), + Conv = fun(T1, T2) -> + erlang:convert_time_unit(T2 - T1, perf_counter, nanosecond) + end, + + do_perf_counter_test([], Conv, 120000000, 80000000), + do_perf_counter_test([1000], fun(T1, T2) -> T2 - T1 end, 120, 80). + +do_perf_counter_test(CntArgs, Conv, Upper, Lower) -> + %% We run the test multiple times to try to get a somewhat + %% stable value... what does this test? That the + %% calculate_perf_counter_unit in sys_time.c works somewhat ok. + do_perf_counter_test(CntArgs, Conv, Upper, Lower, 10). + +do_perf_counter_test(CntArgs, _Conv, Upper, Lower, 0) -> + ct:fail("perf_counter_test ~p ~p ~p",[CntArgs, Upper, Lower]); +do_perf_counter_test(CntArgs, Conv, Upper, Lower, Iters) -> + + T1 = apply(os, perf_counter, CntArgs), timer:sleep(100), - T2 = os:perf_counter(), - TsDiff = erlang:convert_time_unit(T2 - T1, perf_counter, nanosecond), - ct:pal("T1: ~p~n" + T2 = apply(os, perf_counter, CntArgs), + TsDiff = Conv(T1, T2), + ct:log("T1: ~p~n" "T2: ~p~n" "TsDiff: ~p~n", [T1,T2,TsDiff]), - %% We allow a 15% diff - true = TsDiff < 115000000, - true = TsDiff > 85000000, - - T1Ms = os:perf_counter(1000), - timer:sleep(100), - T2Ms = os:perf_counter(1000), - MsDiff = T2Ms - T1Ms, - ct:pal("T1Ms: ~p~n" - "T2Ms: ~p~n" - "MsDiff: ~p~n", - [T1Ms,T2Ms,MsDiff]), - - %% We allow a 15% diff - true = MsDiff < 115, - true = MsDiff > 85. + if + TsDiff < Upper, TsDiff > Lower -> + ok; + true -> + do_perf_counter_test(CntArgs, Conv, Upper, Lower, Iters-1) + end. %% Util functions -- cgit v1.2.3 From 4e38e959a1ecfaa5fa5f3571599a60ab0a88c712 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 22 May 2017 11:25:20 +0200 Subject: erts: Fix sendfile closeduring scenario on sunos On Solaris, giving a too long sfv_len results in an EINVAL error, but data is still transmitted and len is correctly. So we translate this to a success with that amount of data sent. This may hide some other errors that causes EINVAL, but it is the best we can do for now. --- lib/kernel/test/sendfile_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl index 2673c38494..e839959623 100644 --- a/lib/kernel/test/sendfile_SUITE.erl +++ b/lib/kernel/test/sendfile_SUITE.erl @@ -100,13 +100,13 @@ init_per_testcase(TC,Config) when TC == t_sendfile_recvduring; %% Check if sendfile is supported on this platform case catch sendfile_send(Send) of ok -> - Config; + init_per_testcase(t_sendfile, Config); Error -> ct:log("Error: ~p",[Error]), {skip,"Not supported"} end; init_per_testcase(_Tc,Config) -> - Config. + Config ++ [{sendfile_opts,[{use_threads,false}]}]. t_sendfile_small(Config) when is_list(Config) -> -- cgit v1.2.3 From 33ed2e24a516e1024fa984a96ddab90a01a97475 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Wed, 7 Jun 2017 10:10:39 +0200 Subject: Adjust inet:ntoa/1 to RFC5952, but not deeper There are a multitude of RFC:s that point to each other and some of them suggest different addresses with IPv4 suffixes. Use the IPv4 suffix text representation only for the old well known ::a.b.c.d and ::ffff:a.b.c.d prefixes. The others seems to be moving targets. --- lib/kernel/src/inet_parse.erl | 6 ------ lib/kernel/test/inet_SUITE.erl | 2 -- 2 files changed, 8 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl index f150521e92..06e1048afe 100644 --- a/lib/kernel/src/inet_parse.erl +++ b/lib/kernel/src/inet_parse.erl @@ -715,12 +715,6 @@ ntoa({0,0,0,0,0,0,A,B}) -> "::" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); %% IPV4 non ipv6 host address ntoa({0,0,0,0,0,16#ffff,A,B}) -> "::ffff:" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); -%% RFC 2765 IPv4-translated address -ntoa({0,0,0,0,16#ffff,0,A,B}) -> - "::ffff:0:" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); -%% RFC 6052 Well-known Prefix address -ntoa({16#64,16#ff9b,0,0,0,0,A,B}) -> - "64:ff9b::" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); ntoa({_,_,_,_,_,_,_,_}=T) -> %% Find longest sequence of zeros, at least 2, to replace with "::" ntoa(tuple_to_list(T), []); diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index 1d4efe17a5..bd842da4b3 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -552,8 +552,6 @@ parse_address(Config) when is_list(Config) -> tl(V4Reversable), {P,Q} <- [{[0,0,0,0,0,16#ffff],"::ffff:"}, - {[0,0,0,0,16#ffff,0],"::ffff:0:"}, - {[16#64,16#ff9b,0,0,0,0],"64:ff9b::"}, {[0,0,0,0,0,0],"::"}]]], V4Sloppy = [{{10,1,16#98,16#76},"10.0x019876"}, -- cgit v1.2.3 From 06e679b3652f6757c7d033d97ec9fb4dfc3f532c Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 9 Jun 2017 12:15:00 +0200 Subject: kernel: Improve handling of Unicode filenames --- lib/kernel/src/group_history.erl | 4 ++-- lib/kernel/src/inet_tcp_dist.erl | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/group_history.erl b/lib/kernel/src/group_history.erl index 5ca5e2d1dd..91f3663cc5 100644 --- a/lib/kernel/src/group_history.erl +++ b/lib/kernel/src/group_history.erl @@ -218,7 +218,7 @@ handle_open_error({invalid_header, Term}) -> [Term]); handle_open_error({file_error, FileName, Reason}) -> show('$#erlang-history-file-error', - "Error handling File ~s. Reason: ~p~n" + "Error handling File ~ts. Reason: ~p~n" "History logging will be disabled.~n", [FileName, Reason]); handle_open_error(Err) -> @@ -309,7 +309,7 @@ show_rename_warning() -> show_invalid_file_warning(FileName) -> show('$#erlang-history-invalid-file', - "Shell history expects to be able to use the file ~s " + "Shell history expects to be able to use the file ~ts " "which currently exists and is not a file usable for " "history logging purposes. History logging will be " "disabled.~n", [FileName]). diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl index 8c8fe86811..e3fdb1bb22 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-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -390,14 +390,14 @@ splitnode(Driver, Node, LongOrShortNames) -> error_msg("** System running to use " "fully qualified " "hostnames **~n" - "** Hostname ~s is illegal **~n", + "** Hostname ~ts is illegal **~n", [Host]), ?shutdown(Node) end; L when length(L) > 1, LongOrShortNames =:= shortnames -> error_msg("** System NOT running to use fully qualified " "hostnames **~n" - "** Hostname ~s is illegal **~n", + "** Hostname ~ts is illegal **~n", [Host]), ?shutdown(Node); _ -> -- cgit v1.2.3 From 052863543868b442fa649ee99ea8e3e454c838b1 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Wed, 7 Jun 2017 15:36:49 +0200 Subject: Accept IPv6 address %suffixes when parsing This only implements decimal suffixes, and furthermore only with a leading "0". A complete implementation would probably allow one and probably two digit suffixes without. But what primarily is missing is translating interface names to and from interface indexes. This also only implements the parsing, and uses the FreeBSD trick of squeezing in the Scope Id in the second 16-bit word of the fe80::/64 or ff02:/64 address prefix. But inet_drv is not prepared to handle this word, so it might only work on FreeBSD, not being supported even there... So inet_drv needs to handle this too. --- lib/kernel/src/inet_parse.erl | 80 ++++++++++++++++++++++++++++++++++++++---- lib/kernel/test/inet_SUITE.erl | 4 ++- 2 files changed, 77 insertions(+), 7 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl index 06e1048afe..29804dc50b 100644 --- a/lib/kernel/src/inet_parse.erl +++ b/lib/kernel/src/inet_parse.erl @@ -644,8 +644,12 @@ ipv6_addr(Cs) -> ipv6_addr(hex(Cs), [], 0). %% Before "::" +ipv6_addr({Cs0,"%"++Cs1}, A, N) when N == 7 -> + ipv6_addr_scope(Cs1, [hex_to_int(Cs0)|A], [], N+1, []); ipv6_addr({Cs0,[]}, A, N) when N == 7 -> ipv6_addr_done([hex_to_int(Cs0)|A]); +ipv6_addr({Cs0,"::%"++Cs1}, A, N) when N =< 6 -> + ipv6_addr_scope(Cs1, [hex_to_int(Cs0)|A], [], N+1, []); ipv6_addr({Cs0,"::"}, A, N) when N =< 6 -> ipv6_addr_done([hex_to_int(Cs0)|A], [], N+1); ipv6_addr({Cs0,"::"++Cs1}, A, N) when N =< 5 -> @@ -658,6 +662,8 @@ ipv6_addr(_, _, _) -> erlang:error(badarg). %% After "::" +ipv6_addr({Cs0,"%"++Cs1}, A, B, N) when N =< 6 -> + ipv6_addr_scope(Cs1, A, [hex_to_int(Cs0)|B], N+1, []); ipv6_addr({Cs0,[]}, A, B, N) when N =< 6 -> ipv6_addr_done(A, [hex_to_int(Cs0)|B], N+1); ipv6_addr({Cs0,":"++Cs1}, A, B, N) when N =< 5 -> @@ -667,6 +673,43 @@ ipv6_addr({Cs0,"."++_=Cs1}, A, B, N) when N =< 5 -> ipv6_addr(_, _, _, _) -> erlang:error(badarg). +%% After "%" +ipv6_addr_scope([], Ar, Br, N, Sr) -> + ScopeId = + case lists:reverse(Sr) of + %% Empty scope id + "" -> 0; + %% Scope id starts with 0 + "0"++S -> dec16(S); + _ -> 0 + end, + %% Suggested formats for scope id parsing: + %% "" -> "0" + %% "0" -> Scope id 0 + %% "1" - "9", "10" - "99" -> "0"++S + %% "0"++DecimalScopeId -> decimal scope id + %% "25"++PercentEncoded -> Percent encoded interface name + %% S -> Interface name (Unicode?) + %% Missing: translation from interface name into integer scope id. + %% XXX: scope id is actually 32 bit, but we only have room for + %% 16 bit in the second address word - ignore or fix (how)? + ipv6_addr_scope(ScopeId, Ar, Br, N); +ipv6_addr_scope([C|Cs], Ar, Br, N, Sr) -> + ipv6_addr_scope(Cs, Ar, Br, N, [C|Sr]). +%% +ipv6_addr_scope(ScopeId, [P], Br, N) + when N =< 7, P =:= 16#fe80; + N =< 7, P =:= 16#ff02 -> + %% Optimized special case + ipv6_addr_done([ScopeId,P], Br, N+1); +ipv6_addr_scope(ScopeId, Ar, Br, N) -> + case lists:reverse(Br++dup(8-N, 0, Ar)) of + [P,0|Xs] when P =:= 16#fe80; P =:= 16#ff02 -> + list_to_tuple([P,ScopeId|Xs]); + _ -> + erlang:error(badarg) + end. + ipv6_addr_done(Ar, Br, N, {D1,D2,D3,D4}) -> ipv6_addr_done(Ar, [((D3 bsl 8) bor D4),((D1 bsl 8) bor D2)|Br], N+2). @@ -690,6 +733,19 @@ hex(Cs, [_|_]=R, _) when is_list(Cs) -> hex(_, _, _) -> erlang:error(badarg). +%% Parse a reverse decimal integer string, empty is 0 +dec16(Cs) -> dec16(Cs, 0). +%% +dec16([], I) -> I; +dec16([C|Cs], I) when C >= $0, C =< $9 -> + case 10*I + (C - $0) of + J when 16#ffff < J -> + erlang:error(badarg); + J -> + dec16(Cs, J) + end; +dec16(_, _) -> erlang:error(badarg). + %% Hex string to integer hex_to_int(Cs) -> erlang:list_to_integer(Cs, 16). @@ -703,7 +759,7 @@ dup(N, E, L) when is_integer(N), N >= 1 -> %% Convert IPv4 address to ascii %% Convert IPv6 / IPV4 address to ascii (plain format) -ntoa({A,B,C,D}) -> +ntoa({A,B,C,D}) when (A band B band C band D band (bnot 16#ff)) =:= 0 -> integer_to_list(A) ++ "." ++ integer_to_list(B) ++ "." ++ integer_to_list(C) ++ "." ++ integer_to_list(D); %% ANY @@ -711,13 +767,25 @@ ntoa({0,0,0,0,0,0,0,0}) -> "::"; %% LOOPBACK ntoa({0,0,0,0,0,0,0,1}) -> "::1"; %% IPV4 ipv6 host address -ntoa({0,0,0,0,0,0,A,B}) -> "::" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); +ntoa({0,0,0,0,0,0,A,B}) when (A band B band (bnot 16#ffff)) =:= 0 -> + "::" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); %% IPV4 non ipv6 host address -ntoa({0,0,0,0,0,16#ffff,A,B}) -> +ntoa({0,0,0,0,0,16#ffff,A,B}) when (A band B band (bnot 16#ffff)) =:= 0 -> "::ffff:" ++ dig_to_dec(A) ++ "." ++ dig_to_dec(B); -ntoa({_,_,_,_,_,_,_,_}=T) -> - %% Find longest sequence of zeros, at least 2, to replace with "::" - ntoa(tuple_to_list(T), []); +ntoa({A,B,C,D,E,F,G,H}) + when (A band B band C band D band E band F band G band H band + (bnot 16#ffff)) =:= 0 -> + if + A =:= 16#fe80, B =/= 0; + A =:= 16#ff02, B =/= 0 -> + %% Find longest sequence of zeros, at least 2, + %% to replace with "::" + ntoa([A,0,C,D,E,F,G,H], []) ++ "%0" ++ integer_to_list(B); + true -> + %% Find longest sequence of zeros, at least 2, + %% to replace with "::" + ntoa([A,B,C,D,E,F,G,H], []) + end; ntoa(_) -> {error, einval}. diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index bd842da4b3..3b502be8b8 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -544,6 +544,7 @@ parse_address(Config) when is_list(Config) -> {{16#c11,16#c22,16#5c33,0,0,0,0,0}, "c11:c22:5c33::"}, {{0,0,0,0,0,65535,258,65534},"::ffff:1.2.255.254"}, + {{16#fe80,12345,0,0,0,0,0,16#12},"fe80::12%012345"}, {{16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff}, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"} |[{list_to_tuple(P++[(D1 bsl 8) bor D2,(D3 bsl 8) bor D4]), @@ -576,7 +577,8 @@ parse_address(Config) when is_list(Config) -> {{0,0,0,0},"0.00.0.0"}, {{0,0,0,0},"0.0.000000000000.0"}], V6Sloppy = - [{{16#a,16#b,16#c,16#0,16#0,16#d,16#e,16#f},"A:B:C::d:e:f"}] + [{{16#a,16#b,16#c,16#0,16#0,16#d,16#e,16#f},"A:B:C::d:e:f"}, + {{16#fe80,0,0,0,0,0,0,16#12},"fe80::12%XXXXXXX"}] ++ [{{P,0,0,0,0,D2,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4}, Q++erlang:integer_to_list(D2, 16)++":"++S} -- cgit v1.2.3 From b3a234b9f22990cbd1fd7add092a631b461ee7a4 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 13 Jun 2017 15:52:42 +0200 Subject: Revert "kernel: Try mend disk_log whitebox tests" This reverts commit 5d9bb41114544c9205a8b8f26642bad8231e8d4e. --- lib/kernel/test/disk_log_SUITE.erl | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index 2b11a0381f..fe2fc778f2 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -481,7 +481,7 @@ halt_ro_crash(Conf) when is_list(Conf) -> %% This is how it was before R6B: %% {C1,T1,15} = disk_log:chunk(a,start), %% {C2,T2} = disk_log:chunk(a,C1), - {C1,_OneItem,7476} = disk_log:chunk(a,start), + {C1,_OneItem,7478} = disk_log:chunk(a,start), {C2, [], 7} = disk_log:chunk(a,C1), eof = disk_log:chunk(a,C2), ok = disk_log:close(a), @@ -2503,8 +2503,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), BadFile = add_ext(File, 2), % current file set_opened(BadFile), - crash(BadFile, 26), % the binary is now invalid - {repaired,n,{recovered,0},{badbytes,24}} = + crash(BadFile, 28), % the binary is now invalid + {repaired,n,{recovered,0},{badbytes,26}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {40,No}}]), ok = disk_log:close(n), @@ -2521,8 +2521,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), BadFile2 = add_ext(File, 1), % current file set_opened(BadFile2), - crash(BadFile2, 47), % the second binary is now invalid - {repaired,n,{recovered,1},{badbytes,24}} = + crash(BadFile2, 51), % the second binary is now invalid + {repaired,n,{recovered,1},{badbytes,26}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {4000,No}}]), ok = disk_log:close(n), @@ -2580,7 +2580,7 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), set_opened(File), crash(File, 30), - {repaired,n,{recovered,3},{badbytes,15}} = + {repaired,n,{recovered,3},{badbytes,16}} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal},{repair,true}, {quiet, true}, {head_func, {?MODULE, head_fun, [{ok,"head"}]}}]), @@ -2807,7 +2807,7 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:log_terms(n, [{some,terms}]), % second file full 2 = curf(n), BadFile = add_ext(File, 1), - crash(BadFile, 26), % the _binary_ is now invalid + crash(BadFile, 28), % the _binary_ is now invalid {error, {corrupt_log_file, BFile}} = disk_log:chunk(n, start, 1), BadFile = BFile, ok = disk_log:close(n), @@ -2817,7 +2817,7 @@ chunk(Conf) when is_list(Conf) -> {format, internal}]), ok = disk_log:log_terms(n, [{this,is}]), ok = disk_log:sync(n), - crash(File, 26), % the _binary_ is now invalid + crash(File, 28), % the _binary_ is now invalid {error, {corrupt_log_file, File2}} = disk_log:chunk(n, start, 1), crash(File, 10), {error,{corrupt_log_file,_}} = disk_log:bchunk(n, start, 1), @@ -2911,8 +2911,8 @@ chunk(Conf) when is_list(Conf) -> {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {mode, read_only}]), CrashFile = add_ext(File, 1), - crash(CrashFile, 46), % the binary term {some,terms} is now bad - {H1, [{this,is}], 16} = disk_log:chunk(n, start, 10), + crash(CrashFile, 51), % the binary term {some,terms} is now bad + {H1, [{this,is}], 18} = disk_log:chunk(n, start, 10), {H2, [{on,a},{wrap,file}]} = disk_log:chunk(n, H1), eof = disk_log:chunk(n, H2), ok = disk_log:close(n), @@ -2926,8 +2926,8 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal}, {mode, read_only}]), - crash(File, 46), % the binary term {some,terms} is now bad - {J1, [{this,is}], 16} = disk_log:chunk(n, start, 10), + crash(File, 51), % the binary term {some,terms} is now bad + {J1, [{this,is}], 18} = disk_log:chunk(n, start, 10), {J2, [{on,a},{halt,file}]} = disk_log:chunk(n, J1), eof = disk_log:chunk(n, J2), ok = disk_log:close(n), @@ -2942,8 +2942,8 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal}, {mode, read_only}]), - crash(File, 40), % the binary term {s} is now bad - {J11, [{this,is}], 6} = disk_log:chunk(n, start, 10), + crash(File, 44), % the binary term {s} is now bad + {J11, [{this,is}], 7} = disk_log:chunk(n, start, 10), {J21, [{on,a},{halt,file}]} = disk_log:chunk(n, J11), eof = disk_log:chunk(n, J21), ok = disk_log:close(n), @@ -3062,7 +3062,7 @@ truncate(Conf) when is_list(Conf) -> ok = disk_log:truncate(n, apa), rec(1, {disk_log, node(), n, {truncated, 6}}), {0, 0} = no_overflows(n), - 22 = curb(n), + 23 = curb(n), 1 = curf(n), 1 = cur_cnt(n), true = (Size == sz(n)), @@ -3082,7 +3082,7 @@ truncate(Conf) when is_list(Conf) -> ok = disk_log:truncate(n, apa), rec(1, {disk_log, node(), n, {truncated, 3}}), {0, 0} = no_overflows(n), - 22 = curb(n), + 23 = curb(n), 1 = curf(n), 1 = cur_cnt(n), true = (Size == sz(n)), @@ -3191,45 +3191,45 @@ info_current(Conf) when is_list(Conf) -> %% Internal with header. {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {head, header}, {size, {100,No}}]), - {25, 1} = {curb(n), cur_cnt(n)}, + {26, 1} = {curb(n), cur_cnt(n)}, {1, 1} = {no_written_items(n), no_items(n)}, ok = disk_log:log(n, B), - {93, 2} = {curb(n), cur_cnt(n)}, + {94, 2} = {curb(n), cur_cnt(n)}, {2, 2} = {no_written_items(n), no_items(n)}, ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {notify, true}, {head, header}, {size, {100,No}}]), - {93, 2} = {curb(n), cur_cnt(n)}, + {94, 2} = {curb(n), cur_cnt(n)}, {0, 2} = {no_written_items(n), no_items(n)}, ok = disk_log:log(n, B), rec(1, {disk_log, node(), n, {wrap, 0}}), - {93, 2} = {curb(n), cur_cnt(n)}, + {94, 2} = {curb(n), cur_cnt(n)}, {2, 4} = {no_written_items(n), no_items(n)}, disk_log:inc_wrap_file(n), rec(1, {disk_log, node(), n, {wrap, 0}}), - {25, 1} = {curb(n), cur_cnt(n)}, + {26, 1} = {curb(n), cur_cnt(n)}, {3, 4} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. rec(1, {disk_log, node(), n, {wrap, 0}}), rec(1, {disk_log, node(), n, {wrap, 2}}), - {93, 2} = {curb(n), cur_cnt(n)}, + {94, 2} = {curb(n), cur_cnt(n)}, {8, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [B]), rec(1, {disk_log, node(), n, {wrap, 2}}), ok = disk_log:log_terms(n, [B]), rec(1, {disk_log, node(), n, {wrap, 2}}), - {93, 2} = {curb(n), cur_cnt(n)}, + {94, 2} = {curb(n), cur_cnt(n)}, {12, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [BB,BB]), %% Used to be one message, but now one per wrapped file. rec(2, {disk_log, node(), n, {wrap, 2}}), - {193, 2} = {curb(n), cur_cnt(n)}, + {194, 2} = {curb(n), cur_cnt(n)}, {16, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [SB,SB,SB]), rec(1, {disk_log, node(), n, {wrap, 2}}), - {79, 4} = {curb(n), cur_cnt(n)}, + {80, 4} = {curb(n), cur_cnt(n)}, {20, 9} = {no_written_items(n), no_items(n)}, ok = disk_log:close(n), del(File, No), -- cgit v1.2.3 From 43718d3b81d7f3d08e25047e22d579801bbe5044 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 14 Jun 2017 15:36:21 +0200 Subject: Update copyright year --- lib/kernel/doc/src/disk_log.xml | 2 +- lib/kernel/doc/src/net_kernel.xml | 2 +- lib/kernel/src/Makefile | 2 +- lib/kernel/src/disk_log_1.erl | 2 +- lib/kernel/src/group.erl | 2 +- lib/kernel/src/kernel.app.src | 2 +- lib/kernel/test/gen_tcp_api_SUITE.erl | 2 +- lib/kernel/test/gen_udp_SUITE.erl | 2 +- lib/kernel/test/inet_sockopt_SUITE.erl | 2 +- lib/kernel/test/os_SUITE.erl | 2 +- lib/kernel/test/sendfile_SUITE.erl | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index 570d3ef9bd..1be28adfb8 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -5,7 +5,7 @@
    1997 - 2016 + 2017 Ericsson AB, All Rights Reserved diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml index 7ddb849824..0b94fc0fa6 100644 --- a/lib/kernel/doc/src/net_kernel.xml +++ b/lib/kernel/doc/src/net_kernel.xml @@ -4,7 +4,7 @@
    - 19962016 + 19962017 Ericsson AB. All Rights Reserved. diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile index 78aa6192a9..5946620f0f 100644 --- a/lib/kernel/src/Makefile +++ b/lib/kernel/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1996-2016. All Rights Reserved. +# Copyright Ericsson AB 1996-2017. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl index 10c22e1ad6..93856aa7b3 100644 --- a/lib/kernel/src/disk_log_1.erl +++ b/lib/kernel/src/disk_log_1.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl index 0eeaaad8d2..bf785959ff 100644 --- a/lib/kernel/src/group.erl +++ b/lib/kernel/src/group.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 1128ee3ec5..e150938487 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index 3f11e25b93..12d22519ce 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2016. All Rights Reserved. +%% Copyright Ericsson AB 1998-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl index 836e0c5a05..aa616d43d6 100644 --- a/lib/kernel/test/gen_udp_SUITE.erl +++ b/lib/kernel/test/gen_udp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2016. All Rights Reserved. +%% Copyright Ericsson AB 1998-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl index 9413cbd976..ada9c2689c 100644 --- a/lib/kernel/test/inet_sockopt_SUITE.erl +++ b/lib/kernel/test/inet_sockopt_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. +%% Copyright Ericsson AB 2007-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index 1233e362f2..53a9e168ef 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl index e839959623..bfa564c32c 100644 --- a/lib/kernel/test/sendfile_SUITE.erl +++ b/lib/kernel/test/sendfile_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2016. All Rights Reserved. +%% Copyright Ericsson AB 2011-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. -- cgit v1.2.3 From 98e0ccb4a56b3b2b6a552463f78e699ec7490669 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 9 Jun 2017 17:45:09 +0200 Subject: [stdlib] Open error log file as utf8 This allows the use of ~ts/~tp/~tw in calls to error_logger:format/2, error_logger:error_msg/2 and error_logger:info_msg/2. --- lib/kernel/doc/src/error_logger.xml | 20 +++++++++++++++++++- lib/kernel/doc/src/kernel_app.xml | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index 27db00819f..91bf57cb91 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -126,6 +126,12 @@ ok error_report/1 instead.

    + +

    If the Unicode translation modifier (t) is used in + the format string, all error handlers must ensure that the + formatted output is correctly encoded for the I/O + device.

    +
    @@ -197,6 +203,12 @@ ok the standard event handler, meaning no further events are logged. When in doubt, use info_report/1 instead.

    + +

    If the Unicode translation modifier (t) is used in + the format string, all error handlers must ensure that the + formatted output is correctly encoded for the I/O + device.

    +
    @@ -262,7 +274,7 @@ ok successful, or {error, allready_have_logfile} if logging to file is already enabled, or an error tuple if another error occurred (for example, if Filename - cannot be opened).

    + cannot be opened). The file is opened with encoding UTF-8.

    close @@ -345,6 +357,12 @@ ok the standard event handler, meaning no further events are logged. When in doubt, use warning_report/1 instead.

    + +

    If the Unicode translation modifier (t) is used in + the format string, all error handlers must ensure that the + formatted output is correctly encoded for the I/O + device.

    +
    diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 75e1e18d86..e5ac031539 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -186,7 +186,7 @@ {file, FileName}

    Installs the standard event handler, which prints error reports to file FileName, where FileName - is a string.

    + is a string. The file is opened with encoding UTF-8.

    false

    No standard event handler is installed, but -- cgit v1.2.3 From c18b13d4c8aa31b145703bbbf228fb07d6b2a0a5 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 21 Jun 2017 10:53:19 +0200 Subject: Prepare release --- lib/kernel/doc/src/notes.xml | 155 +++++++++++++++++++++++++++++++++++++++++++ lib/kernel/vsn.mk | 2 +- 2 files changed, 156 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 7127a59a0c..e1cf45109d 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,161 @@

    This document describes the changes made to the Kernel application.

    +
    Kernel 5.3 + +
    Fixed Bugs and Malfunctions + + +

    Function inet:ntoa/1 has been fixed to return + lowercase letters according to RFC 5935 that has been + approved after this function was written. Previously + uppercase letters were returned so this may be a + backwards incompatible change depending on how the + returned address string is used.

    +

    Function inet:parse_address/1 has been fixed to + accept %-suffixes on scoped addresses. The addresses does + not work yet, but gives no parse errors.

    +

    + *** POTENTIAL INCOMPATIBILITY ***

    +

    + Own Id: OTP-13006 Aux Id: ERIERL-20, ERL-429

    +
    + +

    + Fix bug where gethostname would incorrectly fail with + enametoolong on Linux.

    +

    + Own Id: OTP-14310

    +
    + +

    + Fix bug causing code:is_module_native to falsely + return true when local call trace is enabled for + the module.

    +

    + Own Id: OTP-14390

    +
    + +

    + Add early reject of invalid node names from distributed + nodes.

    +

    + Own Id: OTP-14426

    +
    +
    +
    + + +
    Improvements and New Features + + +

    + Since Unicode is now allowed in atoms an extra check is + needed for node names, which are restricted to Latin-1.

    +

    + Own Id: OTP-13805

    +
    + +

    Replaced usage of deprecated symbolic time + unit representations.

    +

    + Own Id: OTP-13831 Aux Id: OTP-13735

    +
    + +

    file:write_file(Name, Data, [raw]) would turn + Data into a single binary before writing. This + meant it could not take advantage of the writev() + system call if it was given a list of binaries and told + to write with raw mode.

    +

    + Own Id: OTP-13909

    +
    + +

    The performance of the disk_log has been + somewhat improved in some corner cases (big items), and + the documentation has been clarified.

    +

    + Own Id: OTP-14057 Aux Id: PR-1245

    +
    + +

    Functions for detecting changed code has been added. + code:modified_modules/0 returns all currently + loaded modules that have changed on disk. + code:module_status/1 returns the status for a + module. In the shell and in c module, mm/0 + is short for code:modified_modules/0, and + lm/0 reloads all currently loaded modules that + have changed on disk.

    +

    + Own Id: OTP-14059

    +
    + +

    + Introduce an event manager in Erlang to handle OS + signals. A subset of OS signals may be subscribed to and + those are described in the Kernel application.

    +

    + Own Id: OTP-14186

    +
    + +

    Sockets can now be bound to device (SO_BINDTODEVICE) + on platforms where it is supported.

    This has + been implemented e.g to support VRF-Lite under Linux; see + + VRF , and GitHub pull request #1326. +

    +

    + Own Id: OTP-14357 Aux Id: PR-1326

    +
    + +

    + Added option to store shell_history on disk so that the + history can be reused between sessions.

    +

    + Own Id: OTP-14409 Aux Id: PR-1420

    +
    + +

    The size of crash reports created by + gen_server, gen_statem and proc_lib + is limited with aid of the Kernel application variable + error_logger_format_depth. The purpose is to limit + the size of the messages sent to the error_logger + process when processes with huge message queues or states + crash.

    The crash report generated by + proc_lib includes the new tag + message_queue_len. The neighbour report also + includes the new tag current_stacktrace. Finally, + the neighbour report no longer includes the tags + messages and dictionary.

    The new + function error_logger:get_format_depth/0 can be + used to retrieve the value of the Kernel application + variable error_logger_format_depth.

    +

    + Own Id: OTP-14417

    +
    + +

    One of the ETS tables used by the global + module is created with {read_concurrency, true} in + order to reduce contention.

    +

    + Own Id: OTP-14419

    +
    + +

    + Warnings have been added to the relevant documentation + about not using un-secure distributed nodes in exposed + environments.

    +

    + Own Id: OTP-14425

    +
    +
    +
    + +
    +
    Kernel 5.2
    Fixed Bugs and Malfunctions diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 76b020e8ed..4edecd8969 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.2 +KERNEL_VSN = 5.3 -- cgit v1.2.3