From f1be30c44044e7bb0167a34d234b6b2322328def Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 1 Dec 2015 13:14:43 +0100 Subject: Clarify limitation on halt/2 slogan string --- erts/doc/src/erlang.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 9287b32fec..1e251d33f3 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -1802,6 +1802,8 @@ os_prompt% string() An Erlang crash dump is produced with Status as slogan. Then the runtime system exits with status code 1. + Note that the string may not be longer than 200 characters and only + code points in the range 0-255 may be used. abort -- cgit v1.2.3 From be353901879b3cccda7cd01947936cf1550dea04 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Tue, 1 Dec 2015 11:25:12 +0100 Subject: Check exit status in init:stop/1 and simplify documentation --- erts/doc/src/init.xml | 10 ++-------- erts/preloaded/src/init.erl | 36 ++++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml index 84a5aea335..3546099fad 100644 --- a/erts/doc/src/init.xml +++ b/erts/doc/src/init.xml @@ -178,14 +178,8 @@ Take down an Erlang node smoothly -

All applications are taken down smoothly, all code is - unloaded, and all ports are closed before the system - terminates. If the -heart command line flag was given, - the heart program is terminated before the Erlang node - terminates. Refer to heart(3) for more information.

-

To limit the shutdown time, the time init is allowed - to spend taking down applications, the -shutdown_time - command line flag should be used.

+

The same as + stop(0).

diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 618b53f6bb..04c5210aa3 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -90,6 +90,8 @@ -define(ON_LOAD_HANDLER, init__boot__on_load_handler). +-define(MAX_HALT_STRING_SIZE, 199). + debug(false, _) -> ok; debug(_, T) -> erlang:display(T). @@ -173,7 +175,25 @@ stop() -> init ! {stop,stop}, ok. -spec stop(Status) -> 'ok' when Status :: non_neg_integer() | string(). -stop(Status) -> init ! {stop,{stop,Status}}, ok. +stop(Status) when is_integer(Status), Status >= 0 -> + stop_1(Status); +stop(Status) when is_list(Status) -> + case is_bytelist(Status) of + true -> + stop_1(limit_halt_string(Status)); + false -> + erlang:error(badarg) + end; +stop(_) -> + erlang:error(badarg). + +is_bytelist([B|Bs]) when is_integer(B), B >= 0, B < 256 -> is_bytelist(Bs); +is_bytelist([]) -> true; +is_bytelist(_) -> false. + +%% Note that we check the type of Status beforehand to ensure that +%% the call to halt(Status) by the init process cannot fail +stop_1(Status) -> init ! {stop,{stop,Status}}, ok. -spec boot(BootArgs) -> no_return() when BootArgs :: [binary()]. @@ -285,16 +305,12 @@ things_to_string([]) -> "". halt_string(String, List) -> - HaltString = String ++ things_to_string(List), - if - length(HaltString)<199 -> HaltString; - true -> first198(HaltString, 198) - end. + limit_halt_string(String ++ things_to_string(List)). -first198([H|T], N) when N>0 -> - [H|first198(T, N-1)]; -first198(_, 0) -> - []. +limit_halt_string(String) when length(String) < ?MAX_HALT_STRING_SIZE -> + String; +limit_halt_string(String) -> + lists:sublist(String, ?MAX_HALT_STRING_SIZE-1). %% String = string() %% List = [string() | atom() | pid() | number()] -- cgit v1.2.3 From ab7bcce2778d04daec2276e568deba954c6f9b57 Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Wed, 2 Dec 2015 17:27:11 +0100 Subject: Add testcase for init:stop/1 status --- lib/kernel/test/init_SUITE.erl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl index e7b44a714c..a332e7966b 100644 --- a/lib/kernel/test/init_SUITE.erl +++ b/lib/kernel/test/init_SUITE.erl @@ -27,7 +27,7 @@ -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/1, get_status/1, script_id/1]). + reboot/1, stop_status/1, stop/1, get_status/1, script_id/1]). -export([boot1/1, boot2/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -48,7 +48,7 @@ suite() -> all() -> [get_arguments, get_argument, boot_var, many_restarts, - get_plain_arguments, restart, get_status, script_id, + get_plain_arguments, restart, stop_status, get_status, script_id, {group, boot}]. groups() -> @@ -462,6 +462,20 @@ reboot(Config) when is_list(Config) -> end, ok. +%% ------------------------------------------------ +%% +%% ------------------------------------------------ +stop_status(Config) when is_list(Config) -> + badarg = catch_stop([65,[66],67]), % flat strings only + badarg = catch_stop([65, 666, 67]), % only bytes in string + badarg = catch_stop(abort), % 'abort' not allowed + badarg = catch_stop(true), % other atoms not allowed + badarg = catch_stop(-1), % no negative statuses + ok. + +catch_stop(Status) -> + try init:stop(Status) catch error:badarg -> badarg end. + %% ------------------------------------------------ %% %% ------------------------------------------------ -- cgit v1.2.3 From f9cb80861f169743a96099a06d68149a91f18dfa Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 20 May 2016 15:58:04 +0200 Subject: erts: Implement halt/0 and halt/1 in Erlang just to make things simpler. --- erts/emulator/beam/bif.c | 50 +---------------------------------------- erts/emulator/beam/bif.tab | 2 -- erts/preloaded/src/erlang.erl | 8 +++---- erts/preloaded/src/init.erl | 1 + lib/hipe/cerl/erl_bif_types.erl | 6 ----- lib/stdlib/src/erl_compile.erl | 1 + lib/stdlib/src/escript.erl | 1 + 7 files changed, 7 insertions(+), 62 deletions(-) diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 2a3bd4afe5..81477422ff 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -3836,59 +3836,11 @@ BIF_RETTYPE display_nl_0(BIF_ALIST_0) /**********************************************************************/ -/* stop the system */ -/* ARGSUSED */ -BIF_RETTYPE halt_0(BIF_ALIST_0) -{ - VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt()\n")); - erts_halt(0); - ERTS_BIF_YIELD1(bif_export[BIF_halt_1], BIF_P, am_undefined); -} - -/**********************************************************************/ #define HALT_MSG_SIZE 200 static char halt_msg[HALT_MSG_SIZE]; -/* stop the system with exit code */ -/* ARGSUSED */ -BIF_RETTYPE halt_1(BIF_ALIST_1) -{ - Uint code; - - if (term_to_Uint_mask(BIF_ARG_1, &code)) { - int pos_int_code = (int) (code & INT_MAX); - VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%T)\n", BIF_ARG_1)); - erts_halt(pos_int_code); - ERTS_BIF_YIELD1(bif_export[BIF_halt_1], BIF_P, am_undefined); - } - else if (ERTS_IS_ATOM_STR("abort", BIF_ARG_1)) { - VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%T)\n", BIF_ARG_1)); - erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); - erts_exit(ERTS_ABORT_EXIT, ""); - } - else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) { - Sint i; - - if ((i = intlist_to_buf(BIF_ARG_1, halt_msg, HALT_MSG_SIZE-1)) < 0) { - goto error; - } - halt_msg[i] = '\0'; - VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%T)\n", BIF_ARG_1)); - erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); - erts_exit(ERTS_DUMP_EXIT, "%s\n", halt_msg); - } - else - goto error; - return NIL; /* Pedantic (lint does not know about erts_exit) */ - error: - BIF_ERROR(BIF_P, BADARG); -} - -/**********************************************************************/ - /* stop the system with exit code and flags */ -/* ARGSUSED */ BIF_RETTYPE halt_2(BIF_ALIST_2) { Uint code; @@ -3924,7 +3876,7 @@ BIF_RETTYPE halt_2(BIF_ALIST_2) ("System halted by BIF halt(%T, %T)\n", BIF_ARG_1, BIF_ARG_2)); if (flush) { erts_halt(pos_int_code); - ERTS_BIF_YIELD1(bif_export[BIF_halt_1], BIF_P, am_undefined); + ERTS_BIF_YIELD2(bif_export[BIF_halt_2], BIF_P, am_undefined, am_undefined); } else { erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index 872f0f9b2a..065018514a 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -72,8 +72,6 @@ bif erlang:get/1 bif erlang:get_keys/1 bif erlang:group_leader/0 bif erlang:group_leader/2 -bif erlang:halt/0 -bif erlang:halt/1 bif erlang:halt/2 bif erlang:phash/2 bif erlang:phash2/1 diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 3d152c4e92..4c456bbed4 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -977,17 +977,15 @@ group_leader(_GroupLeader, _Pid) -> erlang:nif_error(undefined). %% halt/0 -%% Shadowed by erl_bif_types: erlang:halt/0 -spec halt() -> no_return(). halt() -> - erlang:nif_error(undefined). + erlang:halt(0, []). %% halt/1 -%% Shadowed by erl_bif_types: erlang:halt/1 -spec halt(Status) -> no_return() when Status :: non_neg_integer() | 'abort' | string(). -halt(_Status) -> - erlang:nif_error(undefined). +halt(Status) -> + erlang:halt(Status, []). %% halt/2 %% Shadowed by erl_bif_types: erlang:halt/2 diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 04c5210aa3..e8f02f5056 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -316,6 +316,7 @@ limit_halt_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. +-spec crash(_, _) -> no_return(). crash(String, List) -> halt(halt_string(String, List)). diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 9453ca6c6f..f649c6e599 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -154,8 +154,6 @@ type(M, F, A, Xs) -> erl_types:erl_type(). %%-- erlang ------------------------------------------------------------------- -type(erlang, halt, 0, _, _) -> t_none(); -type(erlang, halt, 1, _, _) -> t_none(); type(erlang, halt, 2, _, _) -> t_none(); type(erlang, exit, 1, _, _) -> t_none(); type(erlang, error, 1, _, _) -> t_none(); @@ -2341,10 +2339,6 @@ arg_types(erlang, bit_size, 1) -> %% Guard bif, needs to be here. arg_types(erlang, byte_size, 1) -> [t_bitstr()]; -arg_types(erlang, halt, 0) -> - []; -arg_types(erlang, halt, 1) -> - [t_sup([t_non_neg_fixnum(), t_atom('abort'), t_string()])]; arg_types(erlang, halt, 2) -> [t_sup([t_non_neg_fixnum(), t_atom('abort'), t_string()]), t_list(t_tuple([t_atom('flush'), t_boolean()]))]; diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl index ef54076ee3..a6ae398d03 100644 --- a/lib/stdlib/src/erl_compile.erl +++ b/lib/stdlib/src/erl_compile.erl @@ -60,6 +60,7 @@ compile_cmdline() -> _ -> my_halt(2) end. +-spec my_halt(_) -> no_return(). my_halt(Reason) -> erlang:halt(Reason). diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index b8ce311c35..f53b0e2246 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -906,6 +906,7 @@ anno(L) -> fatal(Str) -> throw(Str). +-spec my_halt(_) -> no_return(). my_halt(Reason) -> erlang:halt(Reason). -- cgit v1.2.3 From dcaa52d75e3bcbc808696597a34f2fca5677fff9 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 20 May 2016 15:56:56 +0200 Subject: erts: Make erlang:halt/2 truncate string arg if too long. --- erts/doc/src/erlang.xml | 4 ++-- erts/emulator/beam/bif.c | 11 +++++++---- erts/emulator/beam/utils.c | 8 +++++--- erts/emulator/test/bif_SUITE.erl | 2 ++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 1e251d33f3..665429d290 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -1802,8 +1802,8 @@ os_prompt% string() An Erlang crash dump is produced with Status as slogan. Then the runtime system exits with status code 1. - Note that the string may not be longer than 200 characters and only - code points in the range 0-255 may be used. + Note that only code points in the range 0-255 may be used + and the string will be truncated if longer than 200 characters. abort diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 81477422ff..21763edc5b 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -3838,7 +3838,7 @@ BIF_RETTYPE display_nl_0(BIF_ALIST_0) #define HALT_MSG_SIZE 200 -static char halt_msg[HALT_MSG_SIZE]; +static char halt_msg[HALT_MSG_SIZE+1]; /* stop the system with exit code and flags */ BIF_RETTYPE halt_2(BIF_ALIST_2) @@ -3892,9 +3892,12 @@ BIF_RETTYPE halt_2(BIF_ALIST_2) else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) { Sint i; - if ((i = intlist_to_buf(BIF_ARG_1, halt_msg, HALT_MSG_SIZE-1)) < 0) { - goto error; - } + if ((i = intlist_to_buf(BIF_ARG_1, halt_msg, HALT_MSG_SIZE)) == -1) { + goto error; + } + if (i == -2) /* truncated string */ + i = HALT_MSG_SIZE; + ASSERT(i >= 0 && i <= HALT_MSG_SIZE); halt_msg[i] = '\0'; VERBOSE(DEBUG_SYSTEM, ("System halted by BIF halt(%T, %T)\n", BIF_ARG_1, BIF_ARG_2)); diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index cedc88e5fe..f0418446a8 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -3893,8 +3893,10 @@ void bin_write(int to, void *to_arg, byte* buf, size_t sz) } /* Fill buf with the contents of bytelist list - return number of chars in list or -1 for error */ - + * return number of chars in list + * or -1 for type error + * or -2 for not enough buffer space (buffer contains truncated result) + */ Sint intlist_to_buf(Eterm list, char *buf, Sint len) { @@ -3917,7 +3919,7 @@ intlist_to_buf(Eterm list, char *buf, Sint len) return -1; listptr = list_val(*(listptr + 1)); } - return -1; /* not enough space */ + return -2; /* not enough space */ } /* diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index 26bb416bf0..ec6cb6ab72 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -646,6 +646,8 @@ erlang_halt(Config) when is_list(Config) -> {badrpc,nodedown} = rpc:call(N2, erlang, halt, [0]), {ok,N3} = slave:start(H, halt_node3), {badrpc,nodedown} = rpc:call(N3, erlang, halt, [0,[]]), + {ok,N4} = slave:start(H, halt_node4), + {badrpc,nodedown} = rpc:call(N4, erlang, halt, [lists:duplicate(300,$x)]), % This test triggers a segfault when dumping a crash dump % to make sure that we can handle it properly. -- cgit v1.2.3 From e5b7f259be44efa45ec8ee3355577e691754cc63 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 20 May 2016 18:10:25 +0200 Subject: erts: Remove unnecessary halt string truncation as erlang:halt does it for us now --- erts/preloaded/src/init.erl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index e8f02f5056..45468b3b9c 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -90,7 +90,6 @@ -define(ON_LOAD_HANDLER, init__boot__on_load_handler). --define(MAX_HALT_STRING_SIZE, 199). debug(false, _) -> ok; debug(_, T) -> erlang:display(T). @@ -180,7 +179,7 @@ stop(Status) when is_integer(Status), Status >= 0 -> stop(Status) when is_list(Status) -> case is_bytelist(Status) of true -> - stop_1(limit_halt_string(Status)); + stop_1(Status); false -> erlang:error(badarg) end; @@ -305,12 +304,7 @@ things_to_string([]) -> "". halt_string(String, List) -> - limit_halt_string(String ++ things_to_string(List)). - -limit_halt_string(String) when length(String) < ?MAX_HALT_STRING_SIZE -> - String; -limit_halt_string(String) -> - lists:sublist(String, ?MAX_HALT_STRING_SIZE-1). + String ++ things_to_string(List). %% String = string() %% List = [string() | atom() | pid() | number()] -- cgit v1.2.3 From ab7d8c83a047c2d4c46f1b5f5a7e231af3268e74 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 20 May 2016 16:37:01 +0200 Subject: hipe: Add halt/2 to functions that always fail Seems like halt/2 should be a member of this club. --- lib/hipe/icode/hipe_icode_type.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/hipe/icode/hipe_icode_type.erl b/lib/hipe/icode/hipe_icode_type.erl index e3ba00c5e9..5eae8d440a 100644 --- a/lib/hipe/icode/hipe_icode_type.erl +++ b/lib/hipe/icode/hipe_icode_type.erl @@ -363,6 +363,7 @@ call_always_fails(#icode_call{} = I, Info) -> %% These can actually be calls too. {erlang, halt, 0} -> false; {erlang, halt, 1} -> false; + {erlang, halt, 2} -> false; {erlang, exit, 1} -> false; {erlang, error, 1} -> false; {erlang, error, 2} -> false; -- cgit v1.2.3 From 0f8fab10dad03273b75f205bd9fae746d2077829 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 20 May 2016 19:08:10 +0200 Subject: erts: Update preloaded --- erts/preloaded/ebin/erlang.beam | Bin 104620 -> 104656 bytes erts/preloaded/ebin/init.beam | Bin 49924 -> 50052 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam index 8379bf1768..581ab511d8 100644 Binary files a/erts/preloaded/ebin/erlang.beam and b/erts/preloaded/ebin/erlang.beam differ diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam index 7b5797e90a..6fc95b914e 100644 Binary files a/erts/preloaded/ebin/init.beam and b/erts/preloaded/ebin/init.beam differ -- cgit v1.2.3