Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:25
erlang
1921-erts-Implement-erlang-display_string-2-use...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1921-erts-Implement-erlang-display_string-2-used-for-test.patch of Package erlang
From 3e4baaee6543befa35e604b9d40391c719d0d752 Mon Sep 17 00:00:00 2001 From: Lukas Larsson <lukas@erlang.org> Date: Thu, 12 May 2022 13:55:12 +0200 Subject: [PATCH 01/34] erts: Implement erlang:display_string/2 used for testing --- erts/emulator/beam/bif.c | 83 ++++++++++++++++++++----- erts/emulator/beam/bif.tab | 2 +- erts/emulator/beam/erl_dirty_bif.tab | 1 + erts/emulator/beam/sys.h | 2 +- erts/emulator/test/exception_SUITE.erl | 2 + erts/preloaded/ebin/erlang.beam | Bin 132536 -> 132836 bytes erts/preloaded/src/erlang.erl | 15 ++++- lib/kernel/src/erl_erts_errors.erl | 30 ++++++++- 8 files changed, 116 insertions(+), 19 deletions(-) diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 1d0a145f3f..c8e7caac15 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -23,6 +23,10 @@ #endif #include <stddef.h> /* offsetof() */ +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif +#define WANT_NONBLOCKING #include "sys.h" #include "erl_vm.h" #include "erl_sys_driver.h" @@ -4180,27 +4184,78 @@ BIF_RETTYPE erts_debug_display_1(BIF_ALIST_1) BIF_RET(res); } - -BIF_RETTYPE display_string_1(BIF_ALIST_1) +BIF_RETTYPE display_string_2(BIF_ALIST_2) { Process* p = BIF_P; - Eterm string = BIF_ARG_1; - Sint len = erts_unicode_list_to_buf_len(string); + Eterm string = BIF_ARG_2; + Sint len; Sint written; byte *str; - int res; + int res, fd; + byte *temp_alloc = NULL; + + if (ERTS_IS_ATOM_STR("stdout", BIF_ARG_1)) { + fd = fileno(stdout); + } else if (ERTS_IS_ATOM_STR("stderr", BIF_ARG_1)) { + fd = fileno(stderr); +#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCSTI) + } else if (ERTS_IS_ATOM_STR("stdin", BIF_ARG_1)) { + fd = open("/proc/self/fd/0",0); +#endif + } else { + BIF_ERROR(p, BADARG); + } + if (is_list(string) || is_nil(string)) { + len = erts_unicode_list_to_buf_len(string); + if (len < 0) BIF_ERROR(p, BADARG); + str = temp_alloc = (byte *) erts_alloc(ERTS_ALC_T_TMP, sizeof(char)*len); + res = erts_unicode_list_to_buf(string, str, len, &written); + if (res != 0 || written != len) + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error (%d)\n", __FILE__, __LINE__, res); + } else if (is_binary(string)) { + Uint bitoffs, bitsize; + ERTS_GET_BINARY_BYTES(string, str, bitoffs, bitsize); + if (bitsize % 8 != 0) BIF_ERROR(p, BADARG); + len = binary_size(string); + if (bitoffs != 0) { + str = erts_get_aligned_binary_bytes(string, &temp_alloc); + } + } else { + BIF_ERROR(p, BADARG); + } - if (len < 0) { - BIF_ERROR(p, BADARG); +#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCSTI) + if (ERTS_IS_ATOM_STR("stdin", BIF_ARG_1)) { + for (int i = 0; i < len; i++) { + if (ioctl(fd, TIOCSTI, str+i) < 0) { + fprintf(stderr,"failed to write to %s (%s)\r\n", "/proc/self/fd/0", + strerror(errno)); + close(fd); + goto error; + } + } + close(fd); + } else +#endif + { + written = 0; + do { + res = write(fd, str+written, len-written); + if (res < 0 && errno != ERRNO_BLOCK && errno != EINTR) + goto error; + written += res; + } while (written < len); } - str = (byte *) erts_alloc(ERTS_ALC_T_TMP, sizeof(char)*(len + 1)); - res = erts_unicode_list_to_buf(string, str, len, &written); - if (res != 0 || written != len) - erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error (%d)\n", __FILE__, __LINE__, res); - str[len] = '\0'; - erts_fprintf(stderr, "%s", str); - erts_free(ERTS_ALC_T_TMP, (void *) str); + if (temp_alloc) + erts_free(ERTS_ALC_T_TMP, (void *) temp_alloc); BIF_RET(am_true); + +error: { + char *errnostr = erl_errno_id(errno); + BIF_P->fvalue = am_atom_put(errnostr, strlen(errnostr)); + erts_free(ERTS_ALC_T_TMP, (void *) str); + BIF_ERROR(p, BADARG | EXF_HAS_EXT_INFO); + } } BIF_RETTYPE display_nl_0(BIF_ALIST_0) diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index dffe3963b5..17f35a1bc7 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -56,7 +56,7 @@ bif erlang:crc32_combine/3 bif erlang:date/0 bif erlang:delete_module/1 bif erlang:display/1 -bif erlang:display_string/1 +bif erlang:display_string/2 bif erlang:display_nl/0 ubif erlang:element/2 bif erlang:erase/0 diff --git a/erts/emulator/beam/erl_dirty_bif.tab b/erts/emulator/beam/erl_dirty_bif.tab index 3f16f3e0f3..9245a19be6 100644 --- a/erts/emulator/beam/erl_dirty_bif.tab +++ b/erts/emulator/beam/erl_dirty_bif.tab @@ -50,6 +50,7 @@ dirty-io erts_debug:dirty_io/2 dirty-cpu erts_debug:lcnt_control/2 dirty-cpu erts_debug:lcnt_collect/0 dirty-cpu erts_debug:lcnt_clear/0 +dirty-cpu erlang:display_string/2 # --- TEST of Dirty BIF functionality --- # Functions below will execute on dirty schedulers when emulator has diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 20b0571e43..b57cfd6952 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -608,7 +608,7 @@ extern erts_tsd_key_t erts_is_crash_dumping_key; static unsigned long zero_value = 0, one_value = 1; # define SET_BLOCKING(fd) { if (ioctlsocket((fd), FIONBIO, &zero_value) != 0) fprintf(stderr, "Error setting socket to non-blocking: %d\n", WSAGetLastError()); } # define SET_NONBLOCKING(fd) ioctlsocket((fd), FIONBIO, &one_value) - +# define ERRNO_BLOCK EAGAIN /* We use the posix way for windows */ # else # ifdef NB_FIONBIO /* Old BSD */ # include <sys/ioctl.h> diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl index 5cce5d1491..dfec2a28dc 100644 --- a/erts/emulator/test/exception_SUITE.erl +++ b/erts/emulator/test/exception_SUITE.erl @@ -851,6 +851,8 @@ error_info(_Config) -> {display, ["test erlang:display/1"], [no_fail]}, {display_string, [{a,b,c}]}, + {display_string, [standard_out,"test erlang:display/2"]}, + {display_string, [stdout,{a,b,c}]}, %% Internal undcoumented BIFs. {dist_ctrl_get_data, 1}, diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 8afcfd37ad..7c6d2376f4 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -216,7 +216,7 @@ -export([crc32/2, crc32_combine/3, date/0, decode_packet/3]). -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([display_nl/0, display_string/1, display_string/2, erase/0, erase/1]). -export([error/1, error/2, error/3, 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, @@ -850,8 +850,19 @@ display_nl() -> %% display_string/1 -spec erlang:display_string(P1) -> true when + P1 :: string() | binary(). +display_string(String) -> + try erlang:display_string(stderr, String) + catch error:badarg:ST -> + [{erlang, display_string, _, [ErrorInfo]}|_] = ST, + erlang:error(badarg, [String], [ErrorInfo]) + end. + +%% display_string/2 +-spec erlang:display_string(Device, P1) -> true when + Device :: stdin | stdout | stderr, P1 :: string(). -display_string(_P1) -> +display_string(_Stream,_P1) -> erlang:nif_error(undefined). %% dt_append_vm_tag_data/1 diff --git a/lib/kernel/src/erl_erts_errors.erl b/lib/kernel/src/erl_erts_errors.erl index 4d23112b83..fe7758dae0 100644 --- a/lib/kernel/src/erl_erts_errors.erl +++ b/lib/kernel/src/erl_erts_errors.erl @@ -352,8 +352,19 @@ format_erlang_error(demonitor, [_], _) -> format_erlang_error(demonitor, [Ref,Options], _) -> Arg1 = must_be_ref(Ref), [Arg1,maybe_option_list_error(Options, Arg1)]; -format_erlang_error(display_string, [_], _) -> +format_erlang_error(display_string, [_], none) -> [not_string]; +format_erlang_error(display_string, [_], Cause) -> + maybe_posix_message(Cause, false); +format_erlang_error(display_string, [Device, _], none) -> + case lists:member(Device,[stdin,stdout,stderr]) of + true -> + [[],not_string]; + false -> + [not_device,[]] + end; +format_erlang_error(display_string, [_, _], Cause) -> + maybe_posix_message(Cause, true); format_erlang_error(element, [Index, Tuple], _) -> [if not is_integer(Index) -> @@ -1430,8 +1441,23 @@ is_flat_char_list([H|T]) -> is_flat_char_list([]) -> true; is_flat_char_list(_) -> false. +maybe_posix_message(Cause, HasDevice) -> + case erl_posix_msg:message(Cause) of + "unknown POSIX error" -> + unknown; + PosixStr when HasDevice -> + [unicode:characters_to_binary( + io_lib:format("~ts (~tp)",[PosixStr, Cause]))]; + PosixStr when not HasDevice -> + [{general, + unicode:characters_to_binary( + io_lib:format("~ts (~tp)",[PosixStr, Cause]))}] + end. + format_error_map([""|Es], ArgNum, Map) -> format_error_map(Es, ArgNum + 1, Map); +format_error_map([{general, E}|Es], ArgNum, Map) -> + format_error_map(Es, ArgNum, Map#{ general => expand_error(E)}); format_error_map([E|Es], ArgNum, Map) -> format_error_map(Es, ArgNum + 1, Map#{ArgNum => expand_error(E)}); format_error_map([], _, Map) -> @@ -1519,6 +1545,8 @@ expand_error(not_ref) -> <<"not a reference">>; expand_error(not_string) -> <<"not a list of characters">>; +expand_error(not_device) -> + <<"not a valid device type">>; expand_error(not_tuple) -> <<"not a tuple">>; expand_error(range) -> -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor