Skip to content

Commit

Permalink
erts: Make erlang:halt() accept bignums as Status
Browse files Browse the repository at this point in the history
Just mask away the high bits to get a more tolerant erlang:halt
that behaves the same on 32 and 64 bit architectures.
  • Loading branch information
sverker committed Feb 24, 2016
1 parent 56090db commit 1b094d7
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 7 deletions.
3 changes: 2 additions & 1 deletion erts/doc/src/erlang.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,8 @@ os_prompt% </pre>
</item>
</taglist>
<note><p>On many platforms, the OS supports only status
codes 0-255.</p></note>
codes 0-255. A too large status code will be truncated by clearing
the high bits.</p></note>
<p>For integer <c><anno>Status</anno></c>, the Erlang runtime system
closes all ports and allows async threads to finish their
operations before exiting. To exit without such flushing, use
Expand Down
12 changes: 6 additions & 6 deletions erts/emulator/beam/bif.c
Original file line number Diff line number Diff line change
Expand Up @@ -3938,10 +3938,10 @@ static char halt_msg[HALT_MSG_SIZE];
/* ARGSUSED */
BIF_RETTYPE halt_1(BIF_ALIST_1)
{
Sint code;
Uint code;

if (is_small(BIF_ARG_1) && (code = signed_val(BIF_ARG_1)) >= 0) {
int pos_int_code = (int)code & INT_MAX;
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);
Expand Down Expand Up @@ -3975,7 +3975,7 @@ BIF_RETTYPE halt_1(BIF_ALIST_1)
/* ARGSUSED */
BIF_RETTYPE halt_2(BIF_ALIST_2)
{
Sint code;
Uint code;
Eterm optlist = BIF_ARG_2;
int flush = 1;

Expand All @@ -4002,8 +4002,8 @@ BIF_RETTYPE halt_2(BIF_ALIST_2)
if (is_not_nil(optlist))
goto error;

if (is_small(BIF_ARG_1) && (code = signed_val(BIF_ARG_1)) >= 0) {
int pos_int_code = (int)code & INT_MAX;
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, %T)\n", BIF_ARG_1, BIF_ARG_2));
if (flush) {
Expand Down
26 changes: 26 additions & 0 deletions erts/emulator/beam/big.c
Original file line number Diff line number Diff line change
Expand Up @@ -2028,6 +2028,32 @@ term_to_Uint(Eterm term, Uint *up)
}
}

/* same as term_to_Uint()
but also accept larger bignums by masking
*/
int
term_to_Uint_mask(Eterm term, Uint *up)
{
if (is_small(term)) {
Sint i = signed_val(term);
if (i < 0) {
*up = BADARG;
return 0;
}
*up = (Uint) i;
return 1;
} else if (is_big(term) && !big_sign(term)) {
ErtsDigit* xr = big_v(term);

ERTS_CT_ASSERT(sizeof(ErtsDigit) == sizeof(Uint));
*up = (Uint)*xr; /* just pick first word */
return 1;
} else {
*up = BADARG;
return 0;
}
}

int
term_to_UWord(Eterm term, UWord *up)
{
Expand Down
1 change: 1 addition & 0 deletions erts/emulator/beam/big.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ Eterm bytes_to_big(byte*, dsize_t, int, Eterm*);
byte* big_to_bytes(Eterm, byte*);

int term_to_Uint(Eterm, Uint*);
int term_to_Uint_mask(Eterm, Uint*);
int term_to_UWord(Eterm, UWord*);
int term_to_Sint(Eterm, Sint*);
#if HAVE_INT64
Expand Down

0 comments on commit 1b094d7

Please sign in to comment.