aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded/src
diff options
context:
space:
mode:
Diffstat (limited to 'erts/preloaded/src')
-rw-r--r--erts/preloaded/src/Makefile4
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl10
-rw-r--r--erts/preloaded/src/erlang.erl154
-rw-r--r--erts/preloaded/src/erts_dirty_process_code_checker.erl81
-rw-r--r--erts/preloaded/src/erts_dirty_process_signal_handler.erl97
-rw-r--r--erts/preloaded/src/erts_internal.erl84
-rw-r--r--erts/preloaded/src/init.erl71
-rw-r--r--erts/preloaded/src/prim_file.erl15
-rw-r--r--erts/preloaded/src/prim_zip.erl12
9 files changed, 305 insertions, 223 deletions
diff --git a/erts/preloaded/src/Makefile b/erts/preloaded/src/Makefile
index a2872082f2..4333f6643a 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2016. All Rights Reserved.
+# Copyright Ericsson AB 2008-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.
@@ -47,7 +47,7 @@ PRE_LOADED_ERL_MODULES = \
erts_internal \
erl_tracer \
erts_literal_area_collector \
- erts_dirty_process_code_checker
+ erts_dirty_process_signal_handler
PRE_LOADED_BEAM_MODULES = \
prim_eval
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index d16fe5a0bc..42c1f32a8e 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -56,7 +56,7 @@
-export([purge_archive_cache/0]).
%% Used by init and the code server.
--export([get_modules/2,get_modules/3]).
+-export([get_modules/2,get_modules/3, is_basename/1]).
-include_lib("kernel/include/file.hrl").
@@ -299,8 +299,12 @@ check_file_result(Func, Target, {error,Reason}) ->
end,
%% this is equal to calling error_logger:error_report/1 which
%% we don't want to do from code_server during system boot
- error_logger ! {notify,{error_report,group_leader(),
- {self(),std_error,Report}}},
+ logger ! {log,error,#{label=>{?MODULE,file_error},report=>Report},
+ #{pid=>self(),
+ gl=>group_leader(),
+ time=>erlang:monotonic_time(microsecond),
+ error_logger=>#{tag=>error_report,
+ type=>std_error}}},
error
end;
check_file_result(_, _, Other) ->
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index f3c83b9949..53e90a4f2d 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.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.
@@ -31,7 +31,7 @@
-export([localtime_to_universaltime/1]).
-export([suspend_process/1]).
-export([min/2, max/2]).
--export([dmonitor_node/3, dmonitor_p/2]).
+-export([dmonitor_node/3]).
-export([delay_trap/2]).
-export([set_cookie/2, get_cookie/0]).
-export([nodes/0]).
@@ -39,7 +39,6 @@
-export([integer_to_list/2]).
-export([integer_to_binary/2]).
-export([set_cpu_topology/1, format_cpu_topology/1]).
--export([await_proc_exit/3]).
-export([memory/0, memory/1]).
-export([alloc_info/1, alloc_sizes/1]).
@@ -51,7 +50,7 @@
dist_ctrl_get_data_notification/1,
dist_get_stat/1]).
--deprecated([now/0]).
+-deprecated([get_stacktrace/0,now/0]).
%% Get rid of autoimports of spawn to avoid clashes with ourselves.
-compile({no_auto_import,[spawn_link/1]}).
@@ -122,7 +121,7 @@
-export([delete_element/2]).
-export([delete_module/1, demonitor/1, demonitor/2, display/1]).
-export([display_nl/0, display_string/1, erase/0, erase/1]).
--export([error/1, error/2, exit/1, exit/2, external_size/1]).
+-export([error/1, error/2, exit/1, exit/2, exit_signal/2, external_size/1]).
-export([external_size/2, finish_after_on_load/2, finish_loading/1, float/1]).
-export([float_to_binary/1, float_to_binary/2,
float_to_list/1, float_to_list/2, floor/1]).
@@ -142,7 +141,7 @@
-export([list_to_integer/1, list_to_integer/2]).
-export([list_to_pid/1, list_to_port/1, list_to_ref/1, list_to_tuple/1, loaded/0]).
-export([localtime/0, make_ref/0]).
--export([map_size/1, match_spec_test/3, md5/1, md5_final/1]).
+-export([map_size/1, map_get/2, match_spec_test/3, md5/1, md5_final/1]).
-export([md5_init/0, md5_update/2, module_loaded/1, monitor/2]).
-export([monitor_node/2, monitor_node/3, nif_error/1, nif_error/2]).
-export([node/0, node/1, now/0, phash/2, phash2/1, phash2/2]).
@@ -786,6 +785,13 @@ exit(_Reason) ->
exit(_Pid, _Reason) ->
erlang:nif_error(undefined).
+%% exit_signal/2
+-spec erlang:exit_signal(Pid, Reason) -> true when
+ Pid :: pid() | port(),
+ Reason :: term().
+exit_signal(_Pid, _Reason) ->
+ erlang:nif_error(undefined).
+
%% external_size/1
-spec erlang:external_size(Term) -> non_neg_integer() when
Term :: term().
@@ -1012,8 +1018,20 @@ group_leader() ->
-spec group_leader(GroupLeader, Pid) -> true when
GroupLeader :: pid(),
Pid :: pid().
-group_leader(_GroupLeader, _Pid) ->
- erlang:nif_error(undefined).
+group_leader(GroupLeader, Pid) ->
+ case case erts_internal:group_leader(GroupLeader, Pid) of
+ false ->
+ Ref = erlang:make_ref(),
+ erts_internal:group_leader(GroupLeader,
+ Pid,
+ Ref),
+ receive {Ref, MsgRes} -> MsgRes end;
+ Res ->
+ Res
+ end of
+ true -> true;
+ Error -> erlang:error(Error, [GroupLeader, Pid])
+ end.
%% halt/0
%% Shadowed by erl_bif_types: erlang:halt/0
@@ -1212,6 +1230,14 @@ make_ref() ->
map_size(_Map) ->
erlang:nif_error(undefined).
+%% Shadowed by erl_bif_types: erlang:map_get/2
+-spec map_get(Key, Map) -> Value when
+ Map :: map(),
+ Key :: any(),
+ Value :: any().
+map_get(_Key, _Map) ->
+ erlang:nif_error(undefined).
+
%% match_spec_test/3
-spec erlang:match_spec_test(MatchAgainst, MatchSpec, Type) -> TestResult when
MatchAgainst :: [term()] | tuple(),
@@ -1904,7 +1930,7 @@ element(_N, _Tuple) ->
%% Not documented
-type module_info_key() :: attributes | compile | exports | functions | md5
- | module | native | native_addresses.
+ | module | native | native_addresses | nifs.
-spec erlang:get_module_info(Module, Item) -> ModuleInfo when
Module :: atom(),
Item :: module_info_key(),
@@ -2403,6 +2429,10 @@ subtract(_,_) ->
OldDirtyCPUSchedulersOnline when
DirtyCPUSchedulersOnline :: pos_integer(),
OldDirtyCPUSchedulersOnline :: pos_integer();
+ (erts_alloc, {Alloc, F, V}) -> ok | notsup when
+ Alloc :: atom(),
+ F :: atom(),
+ V :: integer();
(fullsweep_after, Number) -> OldNumber when
Number :: non_neg_integer(),
OldNumber :: non_neg_integer();
@@ -2454,7 +2484,7 @@ term_to_binary(_Term) ->
Term :: term(),
Options :: [compressed |
{compressed, Level :: 0..9} |
- {minor_version, Version :: 0..1} ].
+ {minor_version, Version :: 0..2} ].
term_to_binary(_Term, _Options) ->
erlang:nif_error(undefined).
@@ -2559,10 +2589,10 @@ tuple_to_list(_Tuple) ->
Settings :: [{Subsystem :: atom(),
[{Parameter :: atom(),
Value :: term()}]}];
- (alloc_util_allocators) -> [Alloc] when
- Alloc :: atom();
({allocator, Alloc}) -> [_] when %% More or less anything
Alloc :: atom();
+ (alloc_util_allocators) -> [Alloc] when
+ Alloc :: atom();
({allocator_sizes, Alloc}) -> [_] when %% More or less anything
Alloc :: atom();
(atom_count) -> pos_integer();
@@ -2589,6 +2619,7 @@ tuple_to_list(_Tuple) ->
(driver_version) -> string();
(dynamic_trace) -> none | dtrace | systemtap;
(dynamic_trace_probes) -> boolean();
+ (end_time) -> non_neg_integer();
(elib_malloc) -> false;
(eager_check_io) -> boolean();
(ets_limit) -> pos_integer();
@@ -2616,6 +2647,7 @@ tuple_to_list(_Tuple) ->
(otp_release) -> string();
(os_monotonic_time_source) -> [{atom(),term()}];
(os_system_time_source) -> [{atom(),term()}];
+ (port_parallelism) -> boolean();
(port_count) -> non_neg_integer();
(port_limit) -> pos_integer();
(process_count) -> pos_integer();
@@ -2645,7 +2677,8 @@ tuple_to_list(_Tuple) ->
(trace_control_word) -> non_neg_integer();
(update_cpu_info) -> changed | unchanged;
(version) -> string();
- (wordsize | {wordsize, internal} | {wordsize, external}) -> 4 | 8.
+ (wordsize | {wordsize, internal} | {wordsize, external}) -> 4 | 8;
+ (overview) -> boolean().
system_info(_Item) ->
erlang:nif_error(undefined).
@@ -3272,13 +3305,6 @@ dmonitor_node(Node, Flag, Opts) ->
dmonitor_node(Node,Flag,[])
end.
--spec erlang:dmonitor_p('process', pid() | {atom(),atom()}) -> reference().
-dmonitor_p(process, ProcSpec) ->
- %% Only called when auto-connect attempt failed early in VM
- Ref = erlang:make_ref(),
- erlang:self() ! {'DOWN', Ref, process, ProcSpec, noconnection},
- Ref.
-
%%
%% Trap function used when modified timing has been enabled.
%%
@@ -3511,33 +3537,6 @@ rvrs(Xs) -> rvrs(Xs, []).
rvrs([],Ys) -> Ys;
rvrs([X|Xs],Ys) -> rvrs(Xs, [X|Ys]).
-%% erlang:await_proc_exit/3 is for internal use only!
-%%
-%% BIFs that need to await a specific process exit before
-%% returning traps to erlang:await_proc_exit/3.
-%%
-%% NOTE: This function is tightly coupled to
-%% the implementation of the
-%% erts_bif_prep_await_proc_exit_*()
-%% functions in bif.c. Do not make
-%% any changes to it without reading
-%% the comment about them in bif.c!
--spec erlang:await_proc_exit(dst(), 'apply' | 'data' | 'reason', term()) -> term().
-await_proc_exit(Proc, Op, Data) ->
- Mon = erlang:monitor(process, Proc),
- receive
- {'DOWN', Mon, process, _Proc, Reason} ->
- case Op of
- apply ->
- {M, F, A} = Data,
- erlang:apply(M, F, A);
- data ->
- Data;
- reason ->
- Reason
- end
- end.
-
-spec min(Term1, Term2) -> Minimum when
Term1 :: term(),
Term2 :: term(),
@@ -3561,11 +3560,9 @@ max(A, _) -> A.
%%
-type memory_type() :: 'total' | 'processes' | 'processes_used' | 'system'
- | 'atom' | 'atom_used' | 'binary' | 'code' | 'ets'
- | 'low' | 'maximum'.
+ | 'atom' | 'atom_used' | 'binary' | 'code' | 'ets'.
-define(CARRIER_ALLOCS, [mseg_alloc]).
--define(LOW_ALLOCS, [ll_low_alloc, std_low_alloc]).
-define(ALL_NEEDED_ALLOCS, (erlang:system_info(alloc_util_allocators)
-- ?CARRIER_ALLOCS)).
@@ -3577,9 +3574,7 @@ max(A, _) -> A.
atom_used = 0,
binary = 0,
code = 0,
- ets = 0,
- low = 0,
- maximum = 0}).
+ ets = 0}).
-spec erlang:memory() -> [{Type, Size}] when
Type :: memory_type(),
@@ -3589,14 +3584,6 @@ memory() ->
notsup ->
erlang:error(notsup);
Mem ->
- InstrTail = case Mem#memory.maximum of
- 0 -> [];
- _ -> [{maximum, Mem#memory.maximum}]
- end,
- Tail = case Mem#memory.low of
- 0 -> InstrTail;
- _ -> [{low, Mem#memory.low} | InstrTail]
- end,
[{total, Mem#memory.total},
{processes, Mem#memory.processes},
{processes_used, Mem#memory.processes_used},
@@ -3605,7 +3592,7 @@ memory() ->
{atom_used, Mem#memory.atom_used},
{binary, Mem#memory.binary},
{code, Mem#memory.code},
- {ets, Mem#memory.ets} | Tail]
+ {ets, Mem#memory.ets}]
end.
-spec erlang:memory(Type :: memory_type()) -> non_neg_integer();
@@ -3693,16 +3680,6 @@ need_mem_info(binary) ->
{false, [binary_alloc], true, false};
need_mem_info(ets) ->
{true, [ets_alloc], true, false};
-need_mem_info(low) ->
- LowAllocs = ?LOW_ALLOCS -- ?CARRIER_ALLOCS,
- {_, _, FeatureList, _} = erlang:system_info(allocator),
- AlcUAllocs = case LowAllocs -- FeatureList of
- [] -> LowAllocs;
- _ -> []
- end,
- {false, AlcUAllocs, true, true};
-need_mem_info(maximum) ->
- {true, [], true, true};
need_mem_info(_) ->
{false, [], false, true}.
@@ -3715,8 +3692,6 @@ get_memval(atom_used, #memory{atom_used = V}) -> V;
get_memval(binary, #memory{binary = V}) -> V;
get_memval(code, #memory{code = V}) -> V;
get_memval(ets, #memory{ets = V}) -> V;
-get_memval(low, #memory{low = V}) -> V;
-get_memval(maximum, #memory{maximum = V}) -> V;
get_memval(_, #memory{}) -> 0.
memory_is_supported() ->
@@ -3730,15 +3705,14 @@ memory_is_supported() ->
get_blocks_size([{blocks_size, Sz, _, _} | Rest], Acc) ->
get_blocks_size(Rest, Acc+Sz);
-get_blocks_size([{_, _, _, _} | Rest], Acc) ->
- get_blocks_size(Rest, Acc);
get_blocks_size([{blocks_size, Sz} | Rest], Acc) ->
get_blocks_size(Rest, Acc+Sz);
-get_blocks_size([{_, _} | Rest], Acc) ->
+get_blocks_size([_ | Rest], Acc) ->
get_blocks_size(Rest, Acc);
get_blocks_size([], Acc) ->
Acc.
+
blocks_size([{Carriers, SizeList} | Rest], Acc) when Carriers == mbcs;
Carriers == mbcs_pool;
Carriers == sbcs ->
@@ -3772,16 +3746,6 @@ fix_proc([_ | Rest], Acc) ->
fix_proc([], Acc) ->
Acc.
-is_low_alloc(_A, []) ->
- false;
-is_low_alloc(A, [A|_As]) ->
- true;
-is_low_alloc(A, [_A|As]) ->
- is_low_alloc(A, As).
-
-is_low_alloc(A) ->
- is_low_alloc(A, ?LOW_ALLOCS).
-
au_mem_data(notsup, _) ->
notsup;
au_mem_data(_, [{_, false} | _]) ->
@@ -3834,16 +3798,11 @@ au_mem_data(#memory{total = Tot,
Rest)
end;
au_mem_data(#memory{total = Tot,
- system = Sys,
- low = Low} = Mem,
- [{A, _, Data} | Rest]) ->
+ system = Sys} = Mem,
+ [{_, _, Data} | Rest]) ->
Sz = blocks_size(Data, 0),
au_mem_data(Mem#memory{total = Tot+Sz,
- system = Sys+Sz,
- low = case is_low_alloc(A) of
- true -> Low+Sz;
- false -> Low
- end},
+ system = Sys+Sz},
Rest);
au_mem_data(EMD, []) ->
EMD.
@@ -3865,10 +3824,6 @@ receive_emd(Ref) ->
receive_emd(Ref, #memory{}, erlang:system_info(schedulers)).
aa_mem_data(#memory{} = Mem,
- [{maximum, Max} | Rest]) ->
- aa_mem_data(Mem#memory{maximum = Max},
- Rest);
-aa_mem_data(#memory{} = Mem,
[{total, Tot} | Rest]) ->
aa_mem_data(Mem#memory{total = Tot,
system = 0}, % system will be adjusted later
@@ -3991,4 +3946,3 @@ gc_info(Ref, N, {OrigColls,OrigRecl}) ->
{Ref, {_,Colls, Recl}} ->
gc_info(Ref, N-1, {Colls+OrigColls,Recl+OrigRecl})
end.
-
diff --git a/erts/preloaded/src/erts_dirty_process_code_checker.erl b/erts/preloaded/src/erts_dirty_process_code_checker.erl
deleted file mode 100644
index 7d3fa264be..0000000000
--- a/erts/preloaded/src/erts_dirty_process_code_checker.erl
+++ /dev/null
@@ -1,81 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 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.
-%% 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(erts_dirty_process_code_checker).
-
--export([start/0]).
-
-%%
-%% The erts_dirty_process_code_checker is started at
-%% VM boot by the VM. It is a spawned as a system
-%% process, i.e, the whole VM will terminate if
-%% this process terminates.
-%%
-start() ->
- process_flag(trap_exit, true),
- msg_loop().
-
-msg_loop() ->
- _ = receive
- Request ->
- handle_request(Request)
- end,
- msg_loop().
-
-check_process(Requester, Target, ReqId, Module) ->
- Result = erts_internal:check_dirty_process_code(Target, Module),
- Requester ! {check_process_code, ReqId, Result}.
-
-handle_request({Requester,
- Target,
- Prio,
- {check_process_code,
- ReqId,
- Module} = Op}) ->
- %%
- %% Target may have stopped executing dirty since the
- %% initial request was made. Check its current state
- %% and try to send the request if possible; otherwise,
- %% check the dirty executing process and send the result...
- %%
- try
- case erts_internal:is_process_executing_dirty(Target) of
- true ->
- check_process(Requester, Target, ReqId, Module);
- false ->
- case erts_internal:request_system_task(Requester,
- Target,
- Prio,
- Op) of
- ok ->
- ok;
- dirty_execution ->
- check_process(Requester, Target, ReqId, Module)
- end
- end
- catch
- _ : _ ->
- ok %% Ignore all failures; someone passed us garbage...
- end;
-handle_request(_Garbage) ->
- ignore.
-
-
-
diff --git a/erts/preloaded/src/erts_dirty_process_signal_handler.erl b/erts/preloaded/src/erts_dirty_process_signal_handler.erl
new file mode 100644
index 0000000000..ab71790b9d
--- /dev/null
+++ b/erts/preloaded/src/erts_dirty_process_signal_handler.erl
@@ -0,0 +1,97 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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.
+%% 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(erts_dirty_process_signal_handler).
+
+-export([start/0]).
+
+%%
+%% The erts_dirty_process_signal_handler is started at
+%% VM boot by the VM. It is a spawned as a system
+%% process, i.e, the whole VM will terminate if
+%% this process terminates.
+%%
+start() ->
+ process_flag(trap_exit, true),
+ msg_loop().
+
+msg_loop() ->
+ _ = receive
+ Request ->
+ try
+ handle_request(Request)
+ catch
+ _ : _ ->
+ %% Ignore all failures;
+ %% someone passed us garbage...
+ ok
+ end
+ end,
+ msg_loop().
+
+handle_request(Pid) when is_pid(Pid) ->
+ handle_incoming_signals(Pid, 0);
+handle_request({Requester, Target, Prio,
+ {SysTaskOp, ReqId, Arg} = Op} = Request) ->
+ case handle_sys_task(Requester, Target, SysTaskOp, ReqId, Arg) of
+ true ->
+ ok;
+ false ->
+ %% Target has stopped executing dirty since the
+ %% initial request was made. Dispatch the
+ %% request to target and let it handle it itself...
+ case erts_internal:request_system_task(Requester,
+ Target,
+ Prio,
+ Op) of
+ ok ->
+ ok;
+ dirty_execution ->
+ %% Ahh... It began executing dirty again...
+ handle_request(Request)
+ end
+ end;
+handle_request(_Garbage) ->
+ ignore.
+
+%%
+%% ----------------------------------------------------------------------------
+%%
+
+handle_incoming_signals(Pid, 5) ->
+ self() ! Pid; %% Work with other requests for a while...
+handle_incoming_signals(Pid, N) ->
+ case erts_internal:dirty_process_handle_signals(Pid) of
+ more -> handle_incoming_signals(Pid, N+1);
+ _Res -> ok
+ end.
+
+handle_sys_task(Requester, Target, check_process_code, ReqId, Module) ->
+ case erts_internal:is_process_executing_dirty(Target) of
+ false ->
+ false;
+ true ->
+ _ = check_process(Requester, Target, ReqId, Module),
+ true
+ end.
+
+check_process(Requester, Target, ReqId, Module) ->
+ Result = erts_internal:check_dirty_process_code(Target, Module),
+ Requester ! {check_process_code, ReqId, Result}.
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index a083e9ac2f..79169b7d23 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -45,6 +45,8 @@
-export([check_process_code/3]).
-export([check_dirty_process_code/2]).
-export([is_process_executing_dirty/1]).
+-export([dirty_process_handle_signals/1]).
+
-export([release_literal_area_switch/0]).
-export([purge_module/2]).
@@ -63,6 +65,7 @@
-export([dist_ctrl_put_data/2]).
+-export([get_dflags/0]).
-export([new_connection/1]).
-export([abort_connection/2]).
@@ -70,9 +73,15 @@
gather_sched_wall_time_result/1,
await_sched_wall_time_modifications/2]).
+-export([group_leader/2, group_leader/3]).
+
%% Auto import name clash
-export([check_process_code/1]).
+-export([is_process_alive/1, is_process_alive/2]).
+
+-export([gather_alloc_histograms/1, gather_carrier_info/1]).
+
%%
%% Await result of send to port
%%
@@ -305,6 +314,13 @@ check_dirty_process_code(_Pid,_Module) ->
is_process_executing_dirty(_Pid) ->
erlang:nif_error(undefined).
+-spec dirty_process_handle_signals(Pid) -> Res when
+ Pid :: pid(),
+ Res :: 'false' | 'true' | 'noproc' | 'normal' | 'more' | 'ok'.
+
+dirty_process_handle_signals(_Pid) ->
+ erlang:nif_error(undefined).
+
-spec release_literal_area_switch() -> 'true' | 'false'.
release_literal_area_switch() ->
@@ -497,10 +513,10 @@ dist_ctrl_put_data(DHandle, IoList) ->
%% erlang:dist_ctrl_put_data/2 ...
RootST = try erlang:error(Reason)
catch
- error:Reason ->
- case erlang:get_stacktrace() of
+ error:Reason:ST ->
+ case ST of
[] -> [];
- ST -> tl(ST)
+ [_|T] -> T
end
end,
StackTrace = [{erlang, dist_ctrl_put_data,
@@ -510,6 +526,11 @@ dist_ctrl_put_data(DHandle, IoList) ->
end.
+-spec erts_internal:get_dflags() -> {erts_dflags, integer(), integer(),
+ integer(), integer(), integer()}.
+get_dflags() ->
+ erlang:nif_error(undefined).
+
-spec erts_internal:new_connection(Node) -> ConnId when
Node :: atom(),
ConnId :: {integer(), erlang:dist_handle()}.
@@ -568,3 +589,58 @@ sched_wall_time(Ref, N, Acc) ->
{Ref, SWTL} when erlang:is_list(SWTL) -> sched_wall_time(Ref, N-1, Acc ++ SWTL);
{Ref, SWT} -> sched_wall_time(Ref, N-1, [SWT|Acc])
end.
+
+-spec erts_internal:group_leader(GL, Pid) -> true | false | badarg when
+ GL :: pid(),
+ Pid :: pid().
+
+group_leader(_GL, _Pid) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:group_leader(GL, Pid, Ref) -> ok when
+ GL :: pid(),
+ Pid :: pid(),
+ Ref :: reference().
+
+group_leader(_GL, _Pid, _Ref) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:is_process_alive(Pid, Ref) -> 'ok' when
+ Pid :: pid(),
+ Ref :: reference().
+
+is_process_alive(_Pid, _Ref) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:is_process_alive(Pid) -> boolean() when
+ Pid :: pid().
+
+is_process_alive(Pid) ->
+ Ref = make_ref(),
+ erts_internal:is_process_alive(Pid, Ref),
+ receive
+ {Ref, Res} ->
+ Res
+ end.
+
+-spec gather_alloc_histograms({Type, SchedId, HistWidth, HistStart, Ref}) -> MsgCount when
+ Type :: atom(),
+ SchedId :: non_neg_integer(),
+ HistWidth :: non_neg_integer(),
+ HistStart :: non_neg_integer(),
+ Ref :: reference(),
+ MsgCount :: non_neg_integer().
+
+gather_alloc_histograms(_) ->
+ erlang:nif_error(undef).
+
+-spec gather_carrier_info({Type, SchedId, HistWidth, HistStart, Ref}) -> MsgCount when
+ Type :: atom(),
+ SchedId :: non_neg_integer(),
+ HistWidth :: non_neg_integer(),
+ HistStart :: non_neg_integer(),
+ Ref :: reference(),
+ MsgCount :: non_neg_integer().
+
+gather_carrier_info(_) ->
+ erlang:nif_error(undef).
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index 679a2241d2..9e3de87e08 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.
@@ -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
@@ -545,6 +550,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();
@@ -557,8 +564,18 @@ 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
+ _M -> flush()
+ after 0 ->
+ ok
+ end.
stop_heart(State) ->
case get_heart(State#state.kernel) of
@@ -571,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).
+
+get_kernelpid(Name,[{Name,Pid}|_Kernel]) -> Pid;
+get_kernelpid(Name,[_|Kernel]) -> get_kernelpid(Name,Kernel);
+get_kernelpid(_,_) -> false.
-shutdown([{heart,_Pid}|Kernel],BootPid,Timer,State) ->
+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),
@@ -635,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),
@@ -682,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),
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 35042a7c72..558a0f883f 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -557,8 +557,13 @@ list_dir_convert([RawName | Rest], SkipInvalid, Result) ->
{error, ignore} ->
list_dir_convert(Rest, SkipInvalid, Result);
{error, warning} ->
- error_logger:warning_msg(
- "Non-unicode filename ~p ignored\n", [RawName]),
+ %% this is equal to calling error_logger:warning_msg/2 which
+ %% we don't want to do from code_server during system boot
+ logger ! {log,warning,"Non-unicode filename ~p ignored\n", [RawName],
+ #{pid=>self(),
+ gl=>group_leader(),
+ time=>erlang:monotonic_time(microsecond),
+ error_logger=>#{tag=>warning_msg}}},
list_dir_convert(Rest, SkipInvalid, Result);
{error, _} ->
{error, {no_translation, RawName}}
@@ -618,8 +623,10 @@ write_file_info_1(Filename, Info, TimeType) ->
error:_ -> {error, badarg}
end.
-set_owner(_EncodedName, undefined, undefined) ->
- ok;
+set_owner(EncodedName, Uid, undefined) ->
+ set_owner(EncodedName, Uid, -1);
+set_owner(EncodedName, undefined, Gid) ->
+ set_owner(EncodedName, -1, Gid);
set_owner(EncodedName, Uid, Gid) ->
set_owner_nif(EncodedName, Uid, Gid).
set_owner_nif(_Path, _Uid, _Gid) ->
diff --git a/erts/preloaded/src/prim_zip.erl b/erts/preloaded/src/prim_zip.erl
index b1ddbbe173..5cc15b7acd 100644
--- a/erts/preloaded/src/prim_zip.erl
+++ b/erts/preloaded/src/prim_zip.erl
@@ -74,8 +74,8 @@ open(FilterFun, FilterAcc, F) when is_function(FilterFun, 2) ->
throw(Reason);
throw:InternalReason ->
{error, InternalReason};
- Class:Reason ->
- erlang:error(erlang:raise(Class, Reason, erlang:get_stacktrace()))
+ Class:Reason:Stk ->
+ erlang:error(erlang:raise(Class, Reason, Stk))
end;
open(_, _, _) ->
{error, einval}.
@@ -89,9 +89,9 @@ do_open(FilterFun, FilterAcc, F) ->
{PrimZip2, FilterAcc2} = get_central_dir(PrimZip, FilterFun, FilterAcc),
{ok, PrimZip2, FilterAcc2}
catch
- Class:Reason ->
+ Class:Reason:Stk ->
_ = close(PrimZip),
- erlang:error(erlang:raise(Class, Reason, erlang:get_stacktrace()))
+ erlang:error(erlang:raise(Class, Reason, Stk))
end.
%% iterate over all files in a zip archive
@@ -106,8 +106,8 @@ foldl(FilterFun, FilterAcc, #primzip{files = Files} = PrimZip)
throw(Reason);
throw:InternalReason ->
{error, InternalReason};
- Class:Reason ->
- erlang:error(erlang:raise(Class, Reason, erlang:get_stacktrace()))
+ Class:Reason:Stk ->
+ erlang:error(erlang:raise(Class, Reason, Stk))
end;
foldl(_, _, _) ->
{error, einval}.