From 0b28761f8f4c41107bf94528b044e000fd1da166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 10 Oct 2016 15:37:34 +0200 Subject: erts: Fix -profile_boot 'true'|'false' parsing Strictly speaking 'true' and 'false' arguments is not necessary, but it should work if supplied. --- erts/preloaded/src/init.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 962528f7ab..551ca4ea40 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -205,7 +205,7 @@ boot(BootArgs) -> {Start0,Flags,Args} = parse_boot_args(BootArgs), %% We don't get to profile parsing of BootArgs - case get_flag(profile_boot, Flags, false) of + case b2a(get_flag(profile_boot, Flags, false)) of false -> ok; true -> debug_profile_start() end, @@ -782,7 +782,7 @@ do_boot(Init,Flags,Start) -> (catch erlang:system_info({purify, "Node: " ++ atom_to_list(node())})), start_em(Start), - case get_flag(profile_boot,Flags,false) of + case b2a(get_flag(profile_boot,Flags,false)) of false -> ok; true -> debug_profile_format_mfas(debug_profile_mfas()), -- 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 --- erts/preloaded/src/init.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 551ca4ea40..86dc9a2957 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -932,15 +932,15 @@ load_rest([], _) -> prepare_loading_fun() -> fun(Mod, FullName, Beam) -> case erlang:prepare_loading(Mod, Beam) of - Prepared when is_binary(Prepared) -> + {error,_}=Error -> + Error; + Prepared -> case erlang:has_prepared_code_on_load(Prepared) of true -> {ok,{on_load,Beam,FullName}}; false -> {ok,{prepared,Prepared,FullName}} - end; - {error,_}=Error -> - Error + end end end. -- cgit v1.2.3 From 97164e67aa45f099ca28213586f2aed781f48ae4 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 13 Feb 2017 15:48:23 +0100 Subject: erts: Fix handling of locations and annotations --- erts/preloaded/src/init.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 86dc9a2957..3dc6953b4c 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.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. @@ -1084,7 +1084,7 @@ start_it({eval,Bin}) -> {ok,Ts,_} = erl_scan:string(Str), Ts1 = case reverse(Ts) of [{dot,_}|_] -> Ts; - TsR -> reverse([{dot,1} | TsR]) + TsR -> reverse([{dot,erl_anno:new(1)} | TsR]) end, {ok,Expr} = erl_parse:parse_exprs(Ts1), {value, _Value, _Bs} = erl_eval:exprs(Expr, erl_eval:new_bindings()), -- cgit v1.2.3 From 63b0880e714bd305033a7b07644bc87f8c949b66 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 2 Mar 2017 10:04:17 +0100 Subject: erts: Print more complex terms in crash reason --- erts/preloaded/src/init.erl | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 86dc9a2957..5c7cae3ebf 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -263,21 +263,30 @@ boot(Start,Flags,Args) -> boot_loop(BootPid,State). %%% Convert a term to a printable string, if possible. -to_string(X) when is_list(X) -> % assume string +to_string(X, D) when is_list(X), D < 4 -> % assume string F = flatten(X, []), case printable_list(F) of - true -> F; - false -> "" + true when length(F) > 0 -> F; + _false -> + List = [to_string(E, D+1) || E <- X], + flatten(["[",join(List),"]"], []) end; -to_string(X) when is_atom(X) -> +to_string(X, _D) when is_list(X) -> + "[_]"; +to_string(X, _D) when is_atom(X) -> atom_to_list(X); -to_string(X) when is_pid(X) -> +to_string(X, _D) when is_pid(X) -> pid_to_list(X); -to_string(X) when is_float(X) -> +to_string(X, _D) when is_float(X) -> float_to_list(X); -to_string(X) when is_integer(X) -> +to_string(X, _D) when is_integer(X) -> integer_to_list(X); -to_string(_X) -> +to_string(X, D) when is_tuple(X), D < 4 -> + List = [to_string(E, D+1) || E <- tuple_to_list(X)], + flatten(["{",join(List),"}"], []); +to_string(X, _D) when is_tuple(X) -> + "{_}"; +to_string(_X, _D) -> "". % can't do anything with it %% This is an incorrect and narrow definition of printable characters. @@ -291,6 +300,13 @@ printable_list([$\t|T]) -> printable_list(T); printable_list([]) -> true; printable_list(_) -> false. +join([] = T) -> + T; +join([_Elem] = T) -> + T; +join([Elem|T]) -> + [Elem,","|join(T)]. + flatten([H|T], Tail) when is_list(H) -> flatten(H, flatten(T, Tail)); flatten([H|T], Tail) -> @@ -299,7 +315,7 @@ flatten([], Tail) -> Tail. things_to_string([X|Rest]) -> - " (" ++ to_string(X) ++ ")" ++ things_to_string(Rest); + " (" ++ to_string(X, 0) ++ ")" ++ things_to_string(Rest); things_to_string([]) -> "". @@ -307,9 +323,8 @@ halt_string(String, List) -> String ++ things_to_string(List). %% String = string() -%% List = [string() | atom() | pid() | number()] -%% Any other items in List, such as tuples, are ignored when creating -%% the string used as argument to erlang:halt/1. +%% List = [string() | atom() | pid() | number() | list() | tuple()] +%% Items in List are truncated if found to be too large -spec crash(_, _) -> no_return(). crash(String, List) -> halt(halt_string(String, List)). -- cgit v1.2.3 From 9c4a807cc1b83a6918c0ccf19cdc3837d746f53b Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 5 Apr 2017 14:11:56 +0200 Subject: erts: Remove hipe_bifs:remove_refs_from/1 which serves no purpose after all the hipe load&purge fixes merged at 32729cab75325de58bf127e6e8836348071b8682 --- erts/preloaded/src/init.erl | 8 -------- 1 file changed, 8 deletions(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 3dc6953b4c..14e3bf0c61 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -674,16 +674,8 @@ do_unload([M|Mods]) -> catch erlang:purge_module(M), do_unload(Mods); do_unload([]) -> - purge_all_hipe_refs(), ok. -purge_all_hipe_refs() -> - case erlang:system_info(hipe_architecture) of - undefined -> ok; - _ -> hipe_bifs:remove_refs_from(all) - end. - - sub([H|T],L) -> sub(T,del(H,L)); sub([],L) -> L. -- cgit v1.2.3 From 948ee9b34f34a55cb4b70b7077a849c7dc7a5f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Fri, 21 Jul 2017 14:20:16 +0200 Subject: Replace the zlib driver with a NIF All operations will now yield appropriately, allowing them to be used freely in concurrent applications. This commit also deprecates the functions listed below, although they won't raise deprecation warnings until OTP 21: zlib:adler32 zlib:crc32 zlib:inflateChunk zlib:getBufSize zlib:setBufSize The behavior of throwing an error when a dictionary is required for decompression has also been deprecated. --- erts/preloaded/src/init.erl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 1ccf8d599f..34a9f6b8b9 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -200,6 +200,8 @@ boot(BootArgs) -> register(init, self()), process_flag(trap_exit, true), + %% Load the zlib nif + zlib:on_load(), %% Load the tracer nif erl_tracer:on_load(), -- cgit v1.2.3 From ebbd26eeea4115c946d1254d94acd50f150b4455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Fri, 3 Nov 2017 11:49:27 +0100 Subject: Reimplement efile_drv as a dirty NIF This improves the latency of file operations as dirty schedulers are a bit more eager to run jobs than async threads, and use a single global queue rather than per-thread queues, eliminating the risk of a job stalling behind a long-running job on the same thread while other async threads sit idle. There's no such thing as a free lunch though; the lowered latency comes at the cost of increased busy-waiting which may have an adverse effect on some applications. This behavior can be tweaked with the +sbwt flag, but unfortunately it affects all types of schedulers and not just dirty ones. We plan to add type-specific flags at a later stage. sendfile has been moved to inet_drv to lessen the effect of a nasty race; the cooperation between inet_drv and efile has never been airtight and the socket dying at the wrong time (Regardless of reason) could result in fd aliasing. Moving it to the inet driver makes it impossible to trigger this by closing the socket in the middle of a sendfile operation, while still allowing it to be aborted -- something that can't be done if it stays in the file driver. The race still occurs if the controlling process dies in the short window between dispatching the sendfile operation and the dup(2) call in the driver, but it's much less likely to happen now. A proper fix is in the works. -- Notable functional differences: * The use_threads option for file:sendfile/5 no longer has any effect. * The file-specific DTrace probes have been removed. The same effect can be achieved with normal tracing together with the nif__entry/nif__return probes to track scheduling. -- OTP-14256 --- erts/preloaded/src/init.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 34a9f6b8b9..679a2241d2 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -200,10 +200,11 @@ boot(BootArgs) -> register(init, self()), process_flag(trap_exit, true), - %% Load the zlib nif + %% Load the static nifs zlib:on_load(), - %% Load the tracer nif erl_tracer:on_load(), + prim_buffer:on_load(), + prim_file:on_load(), {Start0,Flags,Args} = parse_boot_args(BootArgs), %% We don't get to profile parsing of BootArgs -- cgit v1.2.3 From 2ab931cec15917e1297aafce350439c8daa7a726 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 23 Jan 2018 11:47:58 +0100 Subject: Reword docs related to the runtime system mode The existing wording may be interpreted as saying that embedded mode eager loads all modules. This revision makes clear embedded mode only disables module auto loading. Since I was on it, I have reordered a couple of places to describe interactive first, and then embedded. It feels natural to cover first the default and positive mode (auto loads), and then its negation. --- erts/preloaded/src/init.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 679a2241d2..e0ae6b1656 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -32,8 +32,8 @@ %% (Optional - default efile) %% -hosts [Node] : List of hosts from which we can boot. %% (Mandatory if -loader inet) -%% -mode embedded : Load all modules at startup, no automatic loading -%% -mode interactive : Auto load modules (default system behaviour). +%% -mode interactive : Auto load modules not needed at startup (default system behaviour). +%% -mode embedded : Load all modules in the boot script, disable auto loading. %% -path : Override path in bootfile. %% -pa Path+ : Add my own paths first. %% -pz Path+ : Add my own paths last. -- cgit v1.2.3 From 994a1229418c34846c1e2b5d08e72aa30ac5fa5f Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 10 Apr 2018 10:17:30 +0200 Subject: erts: Flush messages before doing init restart If messages are not flushed they would cause problems when the system is booting. For instance module load requests would be issued before the prim loader has been launched. --- erts/preloaded/src/init.erl | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index e0ae6b1656..0c74169e97 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -545,6 +545,8 @@ stop(Reason,State) -> do_stop(Reason,State1). do_stop(restart,#state{start = Start, flags = Flags, args = Args}) -> + %% Make sure we don't have any outstanding messages before doing the restart. + flush(), boot(Start,Flags,Args); do_stop(reboot,_) -> halt(); @@ -560,6 +562,13 @@ clear_system(BootPid,State) -> shutdown_pids(Heart,BootPid,State), unload(Heart). +flush() -> + receive + _M -> flush() + after 0 -> + ok + end. + stop_heart(State) -> case get_heart(State#state.kernel) of false -> -- cgit v1.2.3 From 05e1548e5b452d4bfe3bc6837a1a1b51a6367f72 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 24 Apr 2018 14:55:29 +0200 Subject: Remove error_logger process and add logger process --- erts/preloaded/src/init.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 0c74169e97..245630c9de 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -485,7 +485,12 @@ do_handle_msg(Msg,State) -> X -> case whereis(user) of undefined -> - catch error_logger ! {info, self(), {self(), X, []}}; + Time = erlang:monotonic_time(microsecond), + catch logger ! {log, info, "init got unexpected: ~p", [X], + #{pid=>self(), + gl=>self(), + time=>Time, + error_logger=>#{tag=>info_msg}}}; User -> User ! X, ok -- cgit v1.2.3 From 9397275e33805826eccf75868083ac22374d6194 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Wed, 25 Apr 2018 18:31:06 +0200 Subject: Don't kill logger process until all other processes are dead --- erts/preloaded/src/init.erl | 51 +++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 20 deletions(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 245630c9de..9e3de87e08 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -564,8 +564,11 @@ do_stop({stop,Status},State) -> clear_system(BootPid,State) -> Heart = get_heart(State#state.kernel), - shutdown_pids(Heart,BootPid,State), - unload(Heart). + Logger = get_logger(State#state.kernel), + shutdown_pids(Heart,Logger,BootPid,State), + unload(Heart), + kill_em([Logger]), + do_unload([logger_server]). flush() -> receive @@ -585,19 +588,26 @@ stop_heart(State) -> shutdown_kernel_pid(Pid, BootPid, self(), State) end. -shutdown_pids(Heart,BootPid,State) -> +shutdown_pids(Heart,Logger,BootPid,State) -> Timer = shutdown_timer(State#state.flags), catch shutdown(State#state.kernel,BootPid,Timer,State), - kill_all_pids(Heart), % Even the shutdown timer. - kill_all_ports(Heart), + kill_all_pids(Heart,Logger), % Even the shutdown timer. + kill_all_ports(Heart), % Logger has no ports flush_timout(Timer). -get_heart([{heart,Pid}|_Kernel]) -> Pid; -get_heart([_|Kernel]) -> get_heart(Kernel); -get_heart(_) -> false. +get_heart(Kernel) -> + get_kernelpid(heart,Kernel). +get_logger(Kernel) -> + get_kernelpid(logger,Kernel). -shutdown([{heart,_Pid}|Kernel],BootPid,Timer,State) -> +get_kernelpid(Name,[{Name,Pid}|_Kernel]) -> Pid; +get_kernelpid(Name,[_|Kernel]) -> get_kernelpid(Name,Kernel); +get_kernelpid(_,_) -> false. + + +shutdown([{Except,_Pid}|Kernel],BootPid,Timer,State) + when Except==heart; Except==logger -> shutdown(Kernel, BootPid, Timer, State); shutdown([{_Name,Pid}|Kernel],BootPid,Timer,State) -> shutdown_kernel_pid(Pid, BootPid, Timer, State), @@ -649,24 +659,25 @@ resend(_) -> %% %% Kill all existing pids in the system (except init and heart). -kill_all_pids(Heart) -> - case get_pids(Heart) of +kill_all_pids(Heart,Logger) -> + case get_pids(Heart,Logger) of [] -> ok; Pids -> kill_em(Pids), - kill_all_pids(Heart) % Continue until all are really killed. + kill_all_pids(Heart,Logger) % Continue until all are really killed. end. %% All except system processes. -get_pids(Heart) -> +get_pids(Heart,Logger) -> Pids = [P || P <- processes(), not erts_internal:is_system_process(P)], - delete(Heart,self(),Pids). + delete(Heart,Logger,self(),Pids). -delete(Heart,Init,[Heart|Pids]) -> delete(Heart,Init,Pids); -delete(Heart,Init,[Init|Pids]) -> delete(Heart,Init,Pids); -delete(Heart,Init,[Pid|Pids]) -> [Pid|delete(Heart,Init,Pids)]; -delete(_,_,[]) -> []. +delete(Heart,Logger,Init,[Heart|Pids]) -> delete(Heart,Logger,Init,Pids); +delete(Heart,Logger,Init,[Logger|Pids]) -> delete(Heart,Logger,Init,Pids); +delete(Heart,Logger,Init,[Init|Pids]) -> delete(Heart,Logger,Init,Pids); +delete(Heart,Logger,Init,[Pid|Pids]) -> [Pid|delete(Heart,Logger,Init,Pids)]; +delete(_,_,_,[]) -> []. kill_em([Pid|Pids]) -> exit(Pid,kill), @@ -696,9 +707,9 @@ kill_all_ports(_,_) -> ok. unload(false) -> - do_unload(sub(erlang:pre_loaded(),erlang:loaded())); + do_unload(sub([logger_server|erlang:pre_loaded()],erlang:loaded())); unload(_) -> - do_unload(sub([heart|erlang:pre_loaded()],erlang:loaded())). + do_unload(sub([heart,logger_server|erlang:pre_loaded()],erlang:loaded())). do_unload([M|Mods]) -> catch erlang:purge_module(M), -- cgit v1.2.3 From 5ca92e2eac1e84fd22f60e7abc3aa2b0ff1cb42b Mon Sep 17 00:00:00 2001 From: Henrik Nord Date: Mon, 18 Jun 2018 14:51:18 +0200 Subject: Update copyright year --- erts/preloaded/src/init.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 9e3de87e08..253fcf7a1f 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2017. All Rights Reserved. +%% Copyright Ericsson AB 1996-2018. 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 805748eb668d5562fe17f3172cdae07a86166c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 4 Oct 2018 10:30:05 +0200 Subject: Add a persistent term storage Persistent terms are useful for storing Erlang terms that are never or infrequently updated. They have the following advantages: * Constant time access. A persistent term is not copied when it is looked up. The constant factor is lower than for ETS, and no locks are taken when looking up a term. * Persistent terms are not copied in garbage collections. * There is only ever one copy of a persistent term (until it is deleted). That makes them useful for storing configuration data that needs to be easily accessible by all processes. Persistent terms have the following drawbacks: * Updates are expensive. The hash table holding the keys for the persistent terms are updated whenever a persistent term is added, updated or deleted. * Updating or deleting a persistent term triggers a "global GC", which will schedule a heap scan of all processes to search the heap of all processes for the deleted term. If a process still holds a reference to the deleted term, the process will be garbage collected and the term copied to the heap of the process. This global GC can make the system less responsive for some time. Three BIFs (implemented in C in the emulator) is the entire interface to the persistent term functionality: * put(Key, Value) to store a persistent term. * get(Key) to look up a persistent term. * erase(Key) to delete a persistent term. There are also two additional BIFs to obtain information about persistent terms: * info() to return a map with information about persistent terms. * get() to return a list of a {Key,Value} tuples for all persistent terms. (The values are not copied.) --- erts/preloaded/src/init.erl | 1 + 1 file changed, 1 insertion(+) (limited to 'erts/preloaded/src/init.erl') diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 253fcf7a1f..b4b8b3bf9b 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -552,6 +552,7 @@ stop(Reason,State) -> do_stop(restart,#state{start = Start, flags = Flags, args = Args}) -> %% Make sure we don't have any outstanding messages before doing the restart. flush(), + erts_internal:erase_persistent_terms(), boot(Start,Flags,Args); do_stop(reboot,_) -> halt(); -- cgit v1.2.3