diff options
Diffstat (limited to 'erts')
25 files changed, 631 insertions, 281 deletions
diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile index 444adf4a6e..9e68373af8 100644 --- a/erts/doc/src/Makefile +++ b/erts/doc/src/Makefile @@ -1,7 +1,7 @@ -# +# # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2016. All Rights Reserved. +# Copyright Ericsson AB 1997-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. @@ -16,7 +16,7 @@ # limitations under the License. # # %CopyrightEnd% -# +# SPECS_ESRC = ../../preloaded/src/ @@ -66,9 +66,7 @@ XML_REF3_FILES = \ zlib.xml XML_PART_FILES = \ - part.xml \ - part_notes.xml \ - part_notes_history.xml + part.xml XML_CHAPTER_FILES = \ tty.xml \ @@ -116,9 +114,9 @@ SPECS_FILES = $(XML_REF3_EFILES:%.xml=$(SPECDIR)/specs_%.xml) TOP_SPECS_FILE = specs.xml # ---------------------------------------------------- -# FLAGS +# FLAGS # ---------------------------------------------------- -XML_FLAGS += +XML_FLAGS += KERNEL_SRC=$(ERL_TOP)/lib/kernel/src KERNEL_INCLUDE=$(ERL_TOP)/lib/kernel/include @@ -146,7 +144,7 @@ $(INFO_FILE): $(INFO_FILE_SRC) $(ERL_TOP)/make/$(TARGET)/otp.mk sed -e 's;%RELEASE%;$(SYSTEM_VSN);' $(INFO_FILE_SRC) > $(INFO_FILE) -debug opt: +debug opt: clean: rm -rf $(HTMLDIR)/* @@ -154,7 +152,7 @@ clean: rm -f $(MAN3DIR)/* rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) rm -f $(SPECDIR)/* - rm -f errs core *~ + rm -f errs core *~ $(SPECDIR)/specs_%.xml: escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ @@ -162,7 +160,7 @@ $(SPECDIR)/specs_%.xml: # ---------------------------------------------------- # Release Target -# ---------------------------------------------------- +# ---------------------------------------------------- include $(ERL_TOP)/make/otp_release_targets.mk release_docs_spec: docs diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 8dbebe880d..b40aae5d28 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -3826,6 +3826,12 @@ RealSystem = system + MissedSystem</code> </item> <tag><c>{env, <anno>Env</anno>}</c></tag> <item> + <p> + Types:<br/> + <c><anno>Name</anno> = </c><seealso marker="kernel:os#type-env_var_name"><c>os:env_var_name()</c></seealso><br/> + <c><anno>Val</anno> = </c><seealso marker="kernel:os#type-env_var_value"><c>os:env_var_value()</c></seealso><c> | false</c><br/> + <c>Env = [{<anno>Name</anno>, <anno>Val</anno>}]</c> + </p> <p>Only valid for <c>{spawn, <anno>Command</anno>}</c>, and <c>{spawn_executable, <anno>FileName</anno>}</c>. The environment of the started process is extended using @@ -3840,7 +3846,13 @@ RealSystem = system + MissedSystem</code> exception is <c><anno>Val</anno></c> being the atom <c>false</c> (in analogy with <seealso marker="kernel:os#getenv/1"><c>os:getenv/1</c></seealso>, - which removes the environment variable.</p> + which removes the environment variable. + </p> + <p> + For information about encoding requirements, see documentation + of the types for <c><anno>Name</anno></c> and + <c><anno>Val</anno></c>. + </p> </item> <tag><c>{args, [ string() | binary() ]}</c></tag> <item> diff --git a/erts/doc/src/fascicules.xml b/erts/doc/src/fascicules.xml deleted file mode 100644 index 1c371bd9c8..0000000000 --- a/erts/doc/src/fascicules.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE fascicules SYSTEM "fascicules.dtd"> - -<fascicules> - <fascicule file="part" href="part_frame.html" entry="no"> - ERTS User's Guide - </fascicule> - <fascicule file="ref_man" href="ref_man_frame.html" entry="yes"> - ERTS Reference Manual - </fascicule> - <fascicule file="part_notes" href="part_notes_frame.html" entry="no"> - Release Notes - </fascicule> - <fascicule file="" href="../../../doc/print.html" entry="no"> - Off-Print - </fascicule> -</fascicules> - diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index ecbc36e26f..ff3c798179 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,6 +31,23 @@ </header> <p>This document describes the changes made to the ERTS application.</p> +<section><title>Erts 9.1.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed bug that could cause a VM crash when a corrupt + message is received on distribution channel from other + node.</p> + <p> + Own Id: OTP-14661 Aux Id: ERIERL-80 </p> + </item> + </list> + </section> + +</section> + <section><title>Erts 9.1.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/erts/doc/src/part_notes.xml b/erts/doc/src/part_notes.xml deleted file mode 100644 index e579b7635d..0000000000 --- a/erts/doc/src/part_notes.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2004</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - 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. - - </legalnotice> - - <title>ERTS Release Notes</title> - <prepared></prepared> - <docno></docno> - <date>2004-09-07</date> - <rev>1.0</rev> - </header> - <description> - <p>The Erlang Runtime System application <em>ERTS</em>.</p> - <p>For information about older versions, see - <url href="part_notes_history_frame.html">Release Notes History</url>.</p> - </description> - <xi:include href="notes.xml"/> -</part> - diff --git a/erts/doc/src/part_notes_history.xml b/erts/doc/src/part_notes_history.xml deleted file mode 100644 index 277683a2b5..0000000000 --- a/erts/doc/src/part_notes_history.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2006</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - 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. - - </legalnotice> - - <title>ERTS Release Notes History</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <description> - <p>The Erlang Runtime System application <em>ERTS</em>.</p> - </description> - <xi:include href="notes_history.xml"/> -</part> - diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index 297c64de49..3117b24bcc 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -743,6 +743,25 @@ $(OBJDIR)/%_pu.gcda: $(OBJDIR)/PROFILE $(OBJDIR)/default.profdata: $(OBJDIR)/PROFILE $(V_LLVM_PROFDATA) merge -output $@ $(OBJDIR)/*.profraw +ifeq ($(ERTS_BUILD_FALLBACK_POLL),yes) +# Have to treat erl_poll differently as the same .c file is used +# twice for kernel poll builds. +$(OBJDIR)/erl_poll.o: sys/common/erl_poll.c + $(V_CC) -DERTS_KERNEL_POLL_VERSION $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@ + +# Do a copy in order to make debuggers less confused +$(TTF_DIR)/erl_poll.flbk.c: sys/common/erl_poll.c + $(V_at) cp $< $@ + @touch $@ + +$(OBJDIR)/erl_poll.flbk.o: $(TTF_DIR)/erl_poll.flbk.c + $(V_CC) -DERTS_NO_KERNEL_POLL_VERSION $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@ +endif + + +# ---------------------------------------------------------------------- +# General targets +# $(OBJDIR)/%.o: beam/%.c $(V_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@ @@ -776,12 +795,6 @@ $(BINDIR)/$(CS_EXECUTABLE): $(TTF_DIR)/GENERATED $(PRELOAD_SRC) $(CS_OBJ) $(ERTS $(ld_verbose)$(CS_PURIFY) $(LD) $(CS_LDFLAGS) -o $(BINDIR)/$(CS_EXECUTABLE) \ $(CS_CFLAGS) $(COMMON_INCLUDES) $(CS_OBJ) $(CS_LIBS) -$(OBJDIR)/%.kp.o: sys/common/%.c - $(V_CC) -DERTS_KERNEL_POLL_VERSION $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@ - -$(OBJDIR)/%.nkp.o: sys/common/%.c - $(V_CC) -DERTS_NO_KERNEL_POLL_VERSION $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@ - ifeq ($(GCC),yes) $(OBJDIR)/erl_goodfit_alloc.o: beam/erl_goodfit_alloc.c @@ -932,14 +945,8 @@ $(STATIC_NIF_LIBS) $(STATIC_DRIVER_LIBS): echo "=== Leaving lib after making static libs" endif -ifeq ($(ERTS_BUILD_FALLBACK_POLL),yes) -OS_OBJS += $(OBJDIR)/erl_poll.kp.o \ - $(OBJDIR)/erl_poll.nkp.o -else -OS_OBJS += $(OBJDIR)/erl_poll.o -endif - -OS_OBJS += $(OBJDIR)/erl_check_io.o \ +OS_OBJS += $(OBJDIR)/erl_poll.o \ + $(OBJDIR)/erl_check_io.o \ $(OBJDIR)/erl_mseg.o \ $(OBJDIR)/erl_mmap.o \ $(OBJDIR)/erl_$(ERLANG_OSTYPE)_sys_ddll.o \ @@ -947,6 +954,10 @@ OS_OBJS += $(OBJDIR)/erl_check_io.o \ $(OBJDIR)/erl_sys_common_misc.o \ $(OBJDIR)/erl_os_monotonic_time_extender.o +ifeq ($(ERTS_BUILD_FALLBACK_POLL),yes) +OS_OBJS += $(OBJDIR)/erl_poll.flbk.o +endif + HIPE_ARCH64_OBJS=$(OBJDIR)/hipe_bif64.o HIPE_x86_OS_OBJS=$(HIPE_x86_$(OPSYS)_OBJS) @@ -1103,8 +1114,7 @@ SED_REPL_O=s|^\([^:]*:\)|$$(OBJDIR)/\1|g SED_REPL_O_ZLIB=s|^\([^:]*:\)|$$(ZLIB_OBJDIR)/\1|g SED_REPL_TTF_DIR=s|$(TTF_DIR)/|$$(TTF_DIR)/|g SED_REPL_ERL_TOP=s|\([ ]\)$(ERL_TOP)/|\1$$(ERL_TOP)/|g;s|^$(ERL_TOP)/|$$(ERL_TOP)/|g -SED_REPL_POLL=s|$$(OBJDIR)/erl_poll.o|$$(OBJDIR)/erl_poll.kp.o $$(OBJDIR)/erl_poll.nkp.o|g -SED_REPL_CHK_IO=s|$$(OBJDIR)/erl_check_io.o|$$(OBJDIR)/erl_check_io.kp.o $$(OBJDIR)/erl_check_io.nkp.o|g +SED_REPL_POLL=s|$$(OBJDIR)/erl_poll.o|$$(OBJDIR)/erl_poll.o $$(OBJDIR)/erl_poll.flbk.o|g SED_REPL_TTF_COMP_FLAGS=s|\([^/]\)erl_compile_flags\.h|\1$$(TTF_DIR)/erl_compile_flags\.h|g ifeq ($(TARGET),win32) @@ -1115,7 +1125,7 @@ SED_PREFIX= endif ifeq ($(ERTS_BUILD_FALLBACK_POLL),yes) -SED_SUFFIX=;$(SED_REPL_POLL);$(SED_REPL_CHK_IO) +SED_SUFFIX=;$(SED_REPL_POLL) else SED_SUFFIX= endif diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 871670e8c3..fe1e15701b 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -641,6 +641,49 @@ erts_clear_export_break(Module* modp, ErtsCodeInfo *ci) ASSERT(ci->u.gen_bp == NULL); } +/* + * If c_p->cp is a trace return instruction, we set cp + * to be the place where we again start to execute code. + * + * cp is used by match spec {caller} to get the calling + * function, and if we don't do this fixup it will be + * 'undefined'. This has the odd side effect of {caller} + * not really being which function is the caller, but + * rather which function we are about to return to. + */ +static void fixup_cp_before_trace(Process *c_p, int *return_to_trace) +{ + Eterm *cpp, *E = c_p->stop; + BeamInstr w = *c_p->cp; + if (BeamIsOpCode(w, op_return_trace)) { + cpp = &E[2]; + } else if (BeamIsOpCode(w, op_i_return_to_trace)) { + *return_to_trace = 1; + cpp = &E[0]; + } else if (BeamIsOpCode(w, op_i_return_time_trace)) { + cpp = &E[0]; + } else { + cpp = NULL; + } + if (cpp) { + for (;;) { + BeamInstr w = *cp_val(*cpp); + if (BeamIsOpCode(w, op_return_trace)) { + cpp += 3; + } else if (BeamIsOpCode(w, op_i_return_to_trace)) { + *return_to_trace = 1; + cpp += 1; + } else if (BeamIsOpCode(w, op_i_return_time_trace)) { + cpp += 2; + } else { + break; + } + } + c_p->cp = (BeamInstr *) cp_val(*cpp); + ASSERT(is_CP(*cpp)); + } +} + BeamInstr erts_generic_breakpoint(Process* c_p, ErtsCodeInfo *info, Eterm* reg) { @@ -751,6 +794,7 @@ erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr* I) GenericBp* g; GenericBpData* bp = NULL; Uint bp_flags = 0; + int return_to_trace = 0; ERTS_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p); @@ -766,6 +810,8 @@ erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr* I) */ if (!applying) { p->cp = I; + } else { + fixup_cp_before_trace(p, &return_to_trace); } if (bp_flags & (ERTS_BPF_LOCAL_TRACE|ERTS_BPF_GLOBAL_TRACE) && IS_TRACED_FL(p, F_TRACE_CALLS)) { @@ -944,49 +990,18 @@ static ErtsTracer do_call_trace(Process* c_p, ErtsCodeInfo* info, Eterm* reg, int local, Binary* ms, ErtsTracer tracer) { - Eterm* cpp; int return_to_trace = 0; - BeamInstr w; BeamInstr *cp_save = c_p->cp; Uint32 flags; Uint need = 0; Eterm* E = c_p->stop; - w = *c_p->cp; - if (BeamIsOpCode(w, op_return_trace)) { - cpp = &E[2]; - } else if (BeamIsOpCode(w, op_i_return_to_trace)) { - return_to_trace = 1; - cpp = &E[0]; - } else if (BeamIsOpCode(w, op_i_return_time_trace)) { - cpp = &E[0]; - } else { - cpp = NULL; - } - if (cpp) { - for (;;) { - BeamInstr w = *cp_val(*cpp); - if (BeamIsOpCode(w, op_return_trace)) { - cpp += 3; - } else if (BeamIsOpCode(w, op_i_return_to_trace)) { - return_to_trace = 1; - cpp += 1; - } else if (BeamIsOpCode(w, op_i_return_time_trace)) { - cpp += 2; - } else { - break; - } - } - cp_save = c_p->cp; - c_p->cp = (BeamInstr *) cp_val(*cpp); - ASSERT(is_CP(*cpp)); - } - ERTS_UNREQ_PROC_MAIN_LOCK(c_p); + fixup_cp_before_trace(c_p, &return_to_trace); + flags = erts_call_trace(c_p, info, ms, reg, local, &tracer); - ERTS_REQ_PROC_MAIN_LOCK(c_p); - if (cpp) { - c_p->cp = cp_save; - } + + /* restore cp after potential fixup */ + c_p->cp = cp_save; ASSERT(!ERTS_PROC_IS_EXITING(c_p)); if ((flags & MATCH_SET_RETURN_TO_TRACE) && !return_to_trace) { diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types index bf5487d31e..878b971b07 100644 --- a/erts/emulator/beam/erl_alloc.types +++ b/erts/emulator/beam/erl_alloc.types @@ -259,6 +259,7 @@ type MREF_TAB_BKTS STANDARD SYSTEM magic_ref_table_buckets type MREF_TAB LONG_LIVED SYSTEM magic_ref_table type MINDIRECTION FIXED_SIZE SYSTEM magic_indirection type BINARY_FIND SHORT_LIVED PROCESSES binary_find +type OPEN_PORT_ENV TEMPORARY SYSTEM open_port_env type THR_Q_EL STANDARD SYSTEM thr_q_element type THR_Q_EL_SL FIXED_SIZE SYSTEM sl_thr_q_element diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 17c936f041..27bbf70c0b 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -3674,6 +3674,12 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1) Eterm *hp = HAlloc(BIF_P, hsz); BIF_RET(uword_to_big(size, hp)); } + } else if (ERTS_IS_ATOM_STR("scheduler_dump", BIF_ARG_1)) { +#if defined(ERTS_HAVE_TRY_CATCH) && defined(ERTS_SYS_SUSPEND_SIGNAL) + BIF_RET(am_true); +#else + BIF_RET(am_false); +#endif } } else if (is_tuple(BIF_ARG_1)) { diff --git a/erts/emulator/beam/erl_bif_os.c b/erts/emulator/beam/erl_bif_os.c index 5cd172c26f..910325a2f4 100644 --- a/erts/emulator/beam/erl_bif_os.c +++ b/erts/emulator/beam/erl_bif_os.c @@ -37,6 +37,8 @@ #include "dist.h" #include "erl_version.h" +static int check_env_name(char *name); + /* * Return the pid for the Erlang process in the host OS. */ @@ -101,8 +103,10 @@ BIF_RETTYPE os_getenv_1(BIF_ALIST_1) key_str = erts_convert_filename_to_native(BIF_ARG_1,buf,STATIC_BUF_SIZE, ERTS_ALC_T_TMP,1,0,&len); - if (!key_str) { - BIF_ERROR(p, BADARG); + if (!check_env_name(key_str)) { + if (key_str && key_str != &buf[0]) + erts_free(ERTS_ALC_T_TMP, key_str); + BIF_ERROR(p, BADARG); } if (key_str != &buf[0]) @@ -143,25 +147,20 @@ BIF_RETTYPE os_putenv_2(BIF_ALIST_2) { char def_buf_key[STATIC_BUF_SIZE]; char def_buf_value[STATIC_BUF_SIZE]; - char *key_buf, *value_buf; + char *key_buf = NULL, *value_buf = NULL; key_buf = erts_convert_filename_to_native(BIF_ARG_1,def_buf_key, STATIC_BUF_SIZE, ERTS_ALC_T_TMP,0,0,NULL); - if (!key_buf) { - BIF_ERROR(BIF_P, BADARG); - } + if (!check_env_name(key_buf)) + goto badarg; + value_buf = erts_convert_filename_to_native(BIF_ARG_2,def_buf_value, STATIC_BUF_SIZE, ERTS_ALC_T_TMP,1,0, NULL); - if (!value_buf) { - if (key_buf != def_buf_key) { - erts_free(ERTS_ALC_T_TMP, key_buf); - } - BIF_ERROR(BIF_P, BADARG); - } - + if (!value_buf) + goto badarg; if (erts_sys_putenv(key_buf, value_buf)) { if (key_buf != def_buf_key) { @@ -179,6 +178,13 @@ BIF_RETTYPE os_putenv_2(BIF_ALIST_2) erts_free(ERTS_ALC_T_TMP, value_buf); } BIF_RET(am_true); + +badarg: + if (key_buf && key_buf != def_buf_key) + erts_free(ERTS_ALC_T_TMP, key_buf); + if (value_buf && value_buf != def_buf_value) + erts_free(ERTS_ALC_T_TMP, value_buf); + BIF_ERROR(BIF_P, BADARG); } BIF_RETTYPE os_unsetenv_1(BIF_ALIST_1) @@ -188,20 +194,21 @@ BIF_RETTYPE os_unsetenv_1(BIF_ALIST_1) key_buf = erts_convert_filename_to_native(BIF_ARG_1,buf,STATIC_BUF_SIZE, ERTS_ALC_T_TMP,0,0,NULL); - if (!key_buf) { - BIF_ERROR(BIF_P, BADARG); - } + if (!check_env_name(key_buf)) + goto badarg; + + if (erts_sys_unsetenv(key_buf)) + goto badarg; - if (erts_sys_unsetenv(key_buf)) { - if (key_buf != buf) { - erts_free(ERTS_ALC_T_TMP, key_buf); - } - BIF_ERROR(BIF_P, BADARG); - } if (key_buf != buf) { erts_free(ERTS_ALC_T_TMP, key_buf); } BIF_RET(am_true); + +badarg: + if (key_buf && key_buf != buf) + erts_free(ERTS_ALC_T_TMP, key_buf); + BIF_ERROR(BIF_P, BADARG); } BIF_RETTYPE os_set_signal_2(BIF_ALIST_2) { @@ -217,3 +224,27 @@ BIF_RETTYPE os_set_signal_2(BIF_ALIST_2) { error: BIF_ERROR(BIF_P, BADARG); } + +static int +check_env_name(char *raw_name) +{ + byte *c = (byte *) raw_name; + int encoding; + + if (!c) + return 0; + + encoding = erts_get_native_filename_encoding(); + + if (erts_raw_env_char_is_7bit_ascii_char('\0', c, encoding)) + return 0; /* Do not allow empty name... */ + + /* Verify no '=' characters in variable name... */ + do { + if (erts_raw_env_char_is_7bit_ascii_char('=', c, encoding)) + return 0; + c = erts_raw_env_next_char(c, encoding); + } while (!erts_raw_env_char_is_7bit_ascii_char('\0', c, encoding)); + + return 1; /* Seems ok... */ +} diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 3b8e70d44a..c4a4dd5863 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -45,7 +45,7 @@ #include "dtrace-wrapper.h" static Port *open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump); -static byte* convert_environment(Process* p, Eterm env); +static char* convert_environment(Eterm env); static char **convert_args(Eterm); static void free_args(char **); @@ -718,11 +718,11 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump) goto badarg; } } else if (option == am_env) { - byte* bytes; - if ((bytes = convert_environment(p, *tp)) == NULL) { + if (opts.envir) /* ignore previous env option... */ + erts_free(ERTS_ALC_T_OPEN_PORT_ENV, opts.envir); + opts.envir = convert_environment(*tp); + if (!opts.envir) goto badarg; - } - opts.envir = (char *) bytes; } else if (option == am_args) { char **av; char **oav = opts.argv; @@ -956,6 +956,8 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump) erts_atomic32_read_bor_relb(&port->state, sflgs); do_return: + if (opts.envir) + erts_free(ERTS_ALC_T_OPEN_PORT_ENV, opts.envir); if (name_buf) erts_free(ERTS_ALC_T_TMP, (void *) name_buf); if (opts.argv) { @@ -1021,74 +1023,129 @@ static void free_args(char **av) } erts_free(ERTS_ALC_T_TMP, av); } - -static byte* convert_environment(Process* p, Eterm env) +#ifdef DEBUG +#define ERTS_CONV_ENV_BUF_EXTRA 2 +#else +#define ERTS_CONV_ENV_BUF_EXTRA 1024 +#endif + +static char* convert_environment(Eterm env) { - Eterm all; - Eterm* temp_heap; - Eterm* hp; - Uint heap_size; - Sint n; - Sint size; + /* + * Returns environment buffer in memory allocated + * as ERTS_ALC_T_OPEN_PORT_ENV. Caller *needs* + * to deallocate... + */ + + Sint size, alloc_size; byte* bytes; int encoding = erts_get_native_filename_encoding(); - if ((n = erts_list_length(env)) < 0) { - return NULL; - } - heap_size = 2*(5*n+1); - temp_heap = hp = (Eterm *) erts_alloc(ERTS_ALC_T_TMP, heap_size*sizeof(Eterm)); - bytes = NULL; /* Indicating error */ + alloc_size = ERTS_CONV_ENV_BUF_EXTRA; + bytes = erts_alloc(ERTS_ALC_T_OPEN_PORT_ENV, + alloc_size); + size = 0; - /* - * All errors below are handled by jumping to 'done', to ensure that the memory - * gets deallocated. Do NOT return directly from this function. - */ + /* ERTS_CONV_ENV_BUF_EXTRA >= for end delimiter... */ + ERTS_CT_ASSERT(ERTS_CONV_ENV_BUF_EXTRA >= 2); - all = CONS(hp, make_small(0), NIL); - hp += 2; + while (is_list(env)) { + Sint var_sz, val_sz, need; + byte *str, *limit; + Eterm tmp, *tp, *consp; - while(is_list(env)) { - Eterm tmp; - Eterm* tp; + consp = list_val(env); + tmp = CAR(consp); + if (is_not_tuple_arity(tmp, 2)) + goto error; - tmp = CAR(list_val(env)); - if (is_not_tuple_arity(tmp, 2)) { - goto done; - } tp = tuple_val(tmp); - tmp = CONS(hp, make_small(0), NIL); - hp += 2; - if (tp[2] != am_false) { - tmp = CONS(hp, tp[2], tmp); - hp += 2; - } - tmp = CONS(hp, make_small('='), tmp); - hp += 2; - tmp = CONS(hp, tp[1], tmp); - hp += 2; - all = CONS(hp, tmp, all); - hp += 2; - env = CDR(list_val(env)); - } - if (is_not_nil(env)) { - goto done; - } - if ((size = erts_native_filename_need(all, encoding, 1)) < 0) { - goto done; + /* Check encoding of env variable... */ + if (is_not_list(tp[1])) + goto error; + var_sz = erts_native_filename_need(tp[1], encoding); + if (var_sz <= 0) + goto error; + /* Check encoding of value... */ + if (tp[2] == am_false || is_nil(tp[2])) + val_sz = 0; + else if (is_not_list(tp[2])) + goto error; + else { + val_sz = erts_native_filename_need(tp[2], encoding); + if (val_sz < 0) + goto error; + } + + /* Ensure enough memory... */ + need = size; + need += var_sz + val_sz; + /* '=' and '\0' */ + need += 2 * erts_raw_env_7bit_ascii_char_need(encoding); + if (need > alloc_size) { + alloc_size = (need - alloc_size) + alloc_size; + alloc_size += ERTS_CONV_ENV_BUF_EXTRA; + bytes = erts_realloc(ERTS_ALC_T_OPEN_PORT_ENV, + bytes, alloc_size); + } + + /* Write environment variable name... */ + str = bytes + size; + erts_native_filename_put(tp[1], encoding, str); + /* empty variable name is not allowed... */ + if (erts_raw_env_char_is_7bit_ascii_char('\0', str, encoding)) + goto error; + + /* + * Drop null characters at the end and verify that we do + * not have any '=' characters in the name... + */ + limit = str + var_sz; + while (str < limit) { + if (erts_raw_env_char_is_7bit_ascii_char('\0', str, encoding)) + break; + if (erts_raw_env_char_is_7bit_ascii_char('=', str, encoding)) + goto error; + str = erts_raw_env_next_char(str, encoding); + } + + /* Write the equals sign... */ + str = erts_raw_env_7bit_ascii_char_put('=', str, encoding); + + /* Write the value... */ + if (val_sz > 0) { + limit = str + val_sz; + erts_native_filename_put(tp[2], encoding, str); + while (str < limit) { + if (erts_raw_env_char_is_7bit_ascii_char('\0', str, encoding)) + break; + str = erts_raw_env_next_char(str, encoding); + } + } + + /* Delimit... */ + str = erts_raw_env_7bit_ascii_char_put('\0', str, encoding); + + size = str - bytes; + ASSERT(size <= alloc_size); + + env = CDR(consp); } - /* - * Put the result in a binary (no risk for a memory leak that way). - */ - (void) erts_new_heap_binary(p, NULL, size, &bytes); - erts_native_filename_put(all,encoding,bytes); + /* End delimit... */ + (void) erts_raw_env_7bit_ascii_char_put('\0', &bytes[size], encoding); + + if (is_nil(env)) + return (char *) bytes; + +error: + + if (bytes) + erts_free(ERTS_ALC_T_OPEN_PORT_ENV, bytes); - done: - erts_free(ERTS_ALC_T_TMP, temp_heap); - return bytes; + return (char *) NULL; /* error... */ } /* ------------ decode_packet() and friends: */ diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 61fdf86a56..3d12b3bc21 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -12476,9 +12476,9 @@ send_exit_signal(Process *c_p, /* current process if and only if ((state & ERTS_PSFLG_TRAP_EXIT) && (reason != am_kill || (flags & ERTS_XSIG_FLG_IGN_KILL))) { - /* have to release the status lock in order to send the exit message */ - erts_proc_unlock(rp, *rp_locks & ERTS_PROC_LOCKS_XSIG_SEND); - *rp_locks &= ~ERTS_PROC_LOCKS_XSIG_SEND; + /* have to release the status and trace lock in order to send the exit message */ + erts_proc_unlock(rp, *rp_locks & (ERTS_PROC_LOCKS_XSIG_SEND|ERTS_PROC_LOCK_TRACE)); + *rp_locks &= ~(ERTS_PROC_LOCKS_XSIG_SEND|ERTS_PROC_LOCK_TRACE); if (have_seqtrace(token) && token_update) seq_trace_update_send(token_update); if (is_value(exit_tuple)) diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c index efd2ca3db2..b7a5c45fea 100644 --- a/erts/emulator/beam/erl_unicode.c +++ b/erts/emulator/beam/erl_unicode.c @@ -1988,7 +1988,7 @@ char *erts_convert_filename_to_encoding(Eterm name, char *statbuf, size_t statbu is_list(name) || (allow_empty && is_nil(name))) { Sint need; - if ((need = erts_native_filename_need(name, encoding, 0)) < 0) { + if ((need = erts_native_filename_need(name, encoding)) < 0) { return NULL; } if (encoding == ERL_FILENAME_WIN_WCHAR) { @@ -2152,7 +2152,7 @@ Eterm erts_convert_native_to_filename(Process *p, byte *bytes) } -Sint erts_native_filename_need(Eterm ioterm, int encoding, int allow_null) +Sint erts_native_filename_need(Eterm ioterm, int encoding) { Eterm *objp; Eterm obj; @@ -2195,21 +2195,19 @@ Sint erts_native_filename_need(Eterm ioterm, int encoding, int allow_null) default: need = -1; } - if (!allow_null) { - /* - * Do not allow null in - * the middle of filenames - */ - if (need > 0) { - byte *name = ap->name; - int len = ap->len; - for (i = 0; i < len; i++) { - if (name[i] == 0) - seen_null = 1; - else if (seen_null) { - need = -1; - break; - } + /* + * Do not allow null in + * the middle of filenames + */ + if (need > 0) { + byte *name = ap->name; + int len = ap->len; + for (i = 0; i < len; i++) { + if (name[i] == 0) + seen_null = 1; + else if (seen_null) { + need = -1; + break; } } } @@ -2243,17 +2241,15 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */ if (is_small(obj)) { /* Always small */ for(;;) { Uint x = unsigned_val(obj); - if (!allow_null) { - /* - * Do not allow null in - * the middle of filenames - */ - if (x == 0) - seen_null = 1; - else if (seen_null) { - DESTROY_ESTACK(stack); - return ((Sint) -1); - } + /* + * Do not allow null in + * the middle of filenames + */ + if (x == 0) + seen_null = 1; + else if (seen_null) { + DESTROY_ESTACK(stack); + return ((Sint) -1); } switch (encoding) { case ERL_FILENAME_LATIN1: @@ -2528,6 +2524,38 @@ void erts_copy_utf8_to_utf16_little(byte *target, byte *bytes, int num_chars) } /* + * *** Requirements on Raw Filename Format *** + * + * These requirements are due to the 'filename' module + * in stdlib. This since it is documented that it + * should be able to operate on raw filenames as well + * as ordinary filenames. + * + * A raw filename *must* be a byte sequence where: + * 1. Codepoints 0-127 (7-bit ascii) *must* be encoded + * as a byte with the corresponding value. That is, + * the most significant bit in the byte encoding the + * codepoint is never set. + * 2. Codepoints greater than 127 *must* be encoded + * with the most significant bit set in *every* byte + * encoding it. + * + * Latin1 and UTF-8 meet these requirements while + * UTF-16 and UTF-32 don't. + * + * On Windows filenames are natively stored as malformed + * UTF-16LE (lonely surrogates may appear). A more correct + * description than UTF-16 would be an array of 16-bit + * words... In order to meet the requirements of the + * raw file format we convert the malformed UTF-16LE to + * malformed UTF-8 which meet the requirements. + * + * Note that these requirements are today only OTP + * internal (erts-stdlib internal) requirements that + * could be changed. + */ + +/* * This internal bif converts a filename to whatever format is suitable for the file driver * It also adds zero termination so that prim_file needn't bother with the character encoding * of the file driver @@ -2538,6 +2566,12 @@ BIF_RETTYPE prim_file_internal_name2native_1(BIF_ALIST_1) Sint need; Eterm bin_term; byte* bin_p; + + /* + * See comment on "Requirements on Raw Filename Format" + * above. + */ + /* Prim file explicitly does not allow atoms, although we could very well cope with it. Instead of letting 'file' handle them, it would probably be more efficient to handle them here. Subject to @@ -2609,7 +2643,7 @@ BIF_RETTYPE prim_file_internal_name2native_1(BIF_ALIST_1) } /* binary */ - if ((need = erts_native_filename_need(BIF_ARG_1, encoding, 0)) < 0) { + if ((need = erts_native_filename_need(BIF_ARG_1, encoding)) < 0) { BIF_ERROR(BIF_P,BADARG); } if (encoding == ERL_FILENAME_WIN_WCHAR) { @@ -2644,6 +2678,11 @@ BIF_RETTYPE prim_file_internal_native2name_1(BIF_ALIST_1) Eterm ret; int mac = 0; + /* + * See comment on "Requirements on Raw Filename Format" + * above. + */ + if (is_not_binary(BIF_ARG_1)) { BIF_ERROR(BIF_P,BADARG); } diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 604172857a..09aeba00fa 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1238,7 +1238,7 @@ void erts_init_unicode(void); Sint erts_unicode_set_loop_limit(Sint limit); void erts_native_filename_put(Eterm ioterm, int encoding, byte *p) ; -Sint erts_native_filename_need(Eterm ioterm, int encoding, int allow_null); +Sint erts_native_filename_need(Eterm ioterm, int encoding); void erts_copy_utf8_to_utf16_little(byte *target, byte *bytes, int num_chars); int erts_analyze_utf8(byte *source, Uint size, byte **err_pos, Uint *num_chars, int *left); diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 9106091ca6..bf7d310568 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -824,11 +824,16 @@ int erts_sys_unsetenv(char *key); char *erts_read_env(char *key); void erts_free_read_env(void *value); -#if defined(ERTS_THR_HAVE_SIG_FUNCS) && !defined(ETHR_UNUSABLE_SIGUSRX) +#if defined(ERTS_THR_HAVE_SIG_FUNCS) && \ + (!defined(ETHR_UNUSABLE_SIGUSRX) || defined(SIGRTMIN)) extern void sys_thr_resume(erts_tid_t tid); extern void sys_thr_suspend(erts_tid_t tid); -#define ERTS_SYS_SUSPEND_SIGNAL SIGUSR2 -#endif +#ifdef SIGRTMIN +#define ERTS_SYS_SUSPEND_SIGNAL (SIGRTMIN+1) +#else +#define ERTS_SYS_SUSPEND_SIGNAL (SIGUSR2) +#endif /* SIGRTMIN */ +#endif /* HAVE_SIG_FUNCS */ /* utils.c */ @@ -1170,4 +1175,52 @@ int erts_get_printable_characters(void); void erts_init_sys_common_misc(void); +ERTS_GLB_INLINE Sint erts_raw_env_7bit_ascii_char_need(int encoding); +ERTS_GLB_INLINE byte *erts_raw_env_7bit_ascii_char_put(byte c, byte *p, + int encoding); +ERTS_GLB_INLINE int erts_raw_env_char_is_7bit_ascii_char(byte c, byte *p, + int encoding); +ERTS_GLB_INLINE byte *erts_raw_env_next_char(byte *p, int encoding); + +#if ERTS_GLB_INLINE_INCL_FUNC_DEF + +ERTS_GLB_INLINE Sint +erts_raw_env_7bit_ascii_char_need(int encoding) +{ + return (encoding == ERL_FILENAME_WIN_WCHAR) ? 2 : 1; +} + +ERTS_GLB_INLINE byte * +erts_raw_env_7bit_ascii_char_put(byte c, + byte *p, + int encoding) +{ + *(p++) = c; + if (encoding == ERL_FILENAME_WIN_WCHAR) + *(p++) = 0; + return p; +} + +ERTS_GLB_INLINE int +erts_raw_env_char_is_7bit_ascii_char(byte c, + byte *p, + int encoding) +{ + if (encoding == ERL_FILENAME_WIN_WCHAR) + return (p[0] == c) & (p[1] == 0); + else + return p[0] == c; +} + +ERTS_GLB_INLINE byte * +erts_raw_env_next_char(byte *p, int encoding) +{ + if (encoding == ERL_FILENAME_WIN_WCHAR) + return p + 2; + else + return p + 1; +} + +#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */ + #endif diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index b17170c8b8..bf00de2204 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -57,6 +57,7 @@ MODULES= \ dirty_nif_SUITE \ distribution_SUITE \ driver_SUITE \ + dump_SUITE \ efile_SUITE \ erts_debug_SUITE \ estone_SUITE \ diff --git a/erts/emulator/test/dump_SUITE.erl b/erts/emulator/test/dump_SUITE.erl new file mode 100644 index 0000000000..38fa198ea6 --- /dev/null +++ b/erts/emulator/test/dump_SUITE.erl @@ -0,0 +1,125 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-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. +%% 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(dump_SUITE). + +-include_lib("common_test/include/ct.hrl"). + +-export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2]). + +-export([signal_abort/1]). + +-export([load/0]). + +-include_lib("kernel/include/file.hrl"). + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {minutes, 2}}]. + +all() -> + [signal_abort]. + +init_per_testcase(signal_abort, Config) -> + SO = erlang:system_info(schedulers_online), + erts_debug:set_internal_state(available_internal_state, true), + Dump = erts_debug:get_internal_state(scheduler_dump), + erts_debug:set_internal_state(available_internal_state, false), + if SO < 3 -> + {skip, "not enough schedulers"}; + not Dump -> + {skip, "the platform does not support scheduler dump"}; + Dump -> + Config + end. + +end_per_testcase(_, Config) -> + Config. + +%%% +%%% The test cases ------------------------------------------------------------- +%%% + +%% Test that a snapshot is taken of other schedulers using a signal +%% when a crash dump is generated. +signal_abort(Config) -> + + Dump = filename:join(proplists:get_value(priv_dir, Config),"signal_abort.dump"), + + {ok, Node} = start_node(Config), + + _P1 = spawn(Node, ?MODULE, load, []), + _P2 = spawn(Node, ?MODULE, load, []), + _P3 = spawn(Node, ?MODULE, load, []), + _P4 = spawn(Node, ?MODULE, load, []), + _P5 = spawn(Node, ?MODULE, load, []), + _P6 = spawn(Node, ?MODULE, load, []), + + timer:sleep(500), + + true = rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP",Dump]), + rpc:call(Node, erlang, halt, ["dump"]), + + {ok, Bin} = get_dump_when_done(Dump), + + ct:log("~s",[Bin]), + + {match, Matches} = re:run(Bin,"Current Process: <",[global]), + + ct:log("Found ~p",[Matches]), + + true = length(Matches) > 1, + + file:delete(Dump), + + ok. + +get_dump_when_done(Dump) -> + case file:read_file_info(Dump) of + {ok, #file_info{ size = Sz }} -> + get_dump_when_done(Dump, Sz); + {error, enoent} -> + timer:sleep(100), + get_dump_when_done(Dump) + end. + +get_dump_when_done(Dump, Sz) -> + timer:sleep(100), + case file:read_file_info(Dump) of + {ok, #file_info{ size = Sz }} -> + file:read_file(Dump); + {ok, #file_info{ size = NewSz }} -> + get_dump_when_done(Dump, NewSz) + end. + +load() -> + lists:seq(1,10000), + load(). + +start_node(Config) when is_list(Config) -> + Pa = filename:dirname(code:which(?MODULE)), + Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(proplists:get_value(testcase, Config)) + ++ "-" + ++ integer_to_list(erlang:system_time(second)) + ++ "-" + ++ integer_to_list(erlang:unique_integer([positive]))), + test_server:start_node(Name, slave, [{args, "-pa "++Pa}]). diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl index 0f27251fcb..be9b63d534 100644 --- a/erts/emulator/test/exception_SUITE.erl +++ b/erts/emulator/test/exception_SUITE.erl @@ -31,6 +31,10 @@ -include_lib("common_test/include/ct.hrl"). -import(lists, [foreach/2]). +%% The range analysis of the HiPE compiler results in a system limit error +%% during compilation instead of at runtime, so do not perform this analysis. +-compile([{hipe, [no_icode_range]}]). + suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {minutes, 1}}]. diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl index 92ddc23592..08a7b4560c 100644 --- a/erts/emulator/test/match_spec_SUITE.erl +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -21,7 +21,7 @@ -module(match_spec_SUITE). -export([all/0, suite/0, not_run/1]). --export([test_1/1, test_2/1, test_3/1, bad_match_spec_bin/1, +-export([test_1/1, test_2/1, test_3/1, caller_and_return_to/1, bad_match_spec_bin/1, trace_control_word/1, silent/1, silent_no_ms/1, silent_test/1, ms_trace2/1, ms_trace3/1, ms_trace_dead/1, boxed_and_small/1, destructive_in_test_bif/1, guard_exceptions/1, @@ -47,7 +47,7 @@ suite() -> all() -> case test_server:is_native(match_spec_SUITE) of false -> - [test_1, test_2, test_3, bad_match_spec_bin, + [test_1, test_2, test_3, caller_and_return_to, bad_match_spec_bin, trace_control_word, silent, silent_no_ms, silent_test, ms_trace2, ms_trace3, ms_trace_dead, boxed_and_small, destructive_in_test_bif, guard_exceptions, unary_plus, unary_minus, fpe, @@ -180,6 +180,50 @@ test_3(Config) when is_list(Config) -> collect(P1, [{trace, P1, call, {?MODULE, f2, [a, b]}, [true]}]), ok. +%% Test that caller and return to work as they should +%% There was a bug where caller would be undefined when return_to was set +%% for r the bif erlang:put(). +caller_and_return_to(Config) -> + tr( + fun do_put_wrapper/0, + fun (Tracee) -> + MsgCaller = [{'_',[],[{message,{caller}}]}], + 1 = erlang:trace(Tracee, true, [call,return_to]), + 1 = erlang:trace_pattern( {?MODULE,do_put,1}, MsgCaller, [local]), + 1 = erlang:trace_pattern( {?MODULE,do_the_put,1}, MsgCaller, [local]), + 1 = erlang:trace_pattern( {erlang,integer_to_list,1}, MsgCaller, [local]), + 1 = erlang:trace_pattern( {erlang,put,2}, MsgCaller, [local]), + + [{trace,Tracee,call,{?MODULE,do_put,[test]},{?MODULE,do_put_wrapper,0}}, + {trace,Tracee,call,{?MODULE,do_the_put,[test]},{?MODULE,do_put,1}}, + {trace,Tracee,call,{erlang,integer_to_list,[1]},{?MODULE,do_the_put,1}}, + {trace,Tracee,return_to,{?MODULE,do_the_put,1}}, + {trace,Tracee,call,{erlang,put,[test,"1"]},{?MODULE,do_put,1}}, + {trace,Tracee,return_to,{?MODULE,do_put,1}}, + + %% These last trace messages are a bit strange... + %% if call tracing had been enabled for do_put_wrapper + %% then caller and return_to would have been {?MODULE,do_put_wrapper,1} + %% but since it is not, they are set to do_put instead, but we still + %% get the do_put_wrapper return_to message... + {trace,Tracee,call,{erlang,integer_to_list,[2]},{?MODULE,do_put,1}}, + {trace,Tracee,return_to,{?MODULE,do_put,1}}, + {trace,Tracee,return_to,{?MODULE,do_put_wrapper,0}} + ] + end), + ok. + +do_put_wrapper() -> + do_put(test), + ok. + +do_put(Var) -> + do_the_put(Var), + erlang:integer_to_list(id(2)). +do_the_put(Var) -> + Lst = erlang:integer_to_list(id(1)), + erlang:put(Var, Lst). + otp_9422(Config) when is_list(Config) -> Laps = 10000, Fun1 = fun() -> otp_9422_tracee() end, diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index 72acd33033..a81aa64057 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -38,7 +38,7 @@ system_monitor_long_gc_1/1, system_monitor_long_gc_2/1, system_monitor_large_heap_1/1, system_monitor_large_heap_2/1, system_monitor_long_schedule/1, - bad_flag/1, trace_delivered/1]). + bad_flag/1, trace_delivered/1, trap_exit_self_receive/1]). -include_lib("common_test/include/ct.hrl"). @@ -61,7 +61,8 @@ all() -> more_system_monitor_args, system_monitor_long_gc_1, system_monitor_long_gc_2, system_monitor_large_heap_1, system_monitor_long_schedule, - system_monitor_large_heap_2, bad_flag, trace_delivered]. + system_monitor_large_heap_2, bad_flag, trace_delivered, + trap_exit_self_receive]. init_per_testcase(_Case, Config) -> [{receiver,spawn(fun receiver/0)}|Config]. @@ -1709,6 +1710,31 @@ trace_delivered(Config) when is_list(Config) -> ok end. +%% This testcase checks that receive trace works on exit signal messages +%% when the sender of the exit signal is the process itself. +trap_exit_self_receive(Config) -> + Parent = self(), + Proc = spawn_link(fun() -> process(Parent) end), + + 1 = erlang:trace(Proc, true, ['receive']), + Proc ! {trap_exit_please, true}, + {trace, Proc, 'receive', {trap_exit_please, true}} = receive_first_trace(), + + %% Make the process call exit(self(), signal) + Reason1 = make_ref(), + Proc ! {exit_signal_please, Reason1}, + {trace, Proc, 'receive', {exit_signal_please, Reason1}} = receive_first_trace(), + {trace, Proc, 'receive', {'EXIT', Proc, Reason1}} = receive_first_trace(), + receive {Proc, {'EXIT', Proc, Reason1}} -> ok end, + receive_nothing(), + + unlink(Proc), + Reason2 = make_ref(), + Proc ! {exit_please, Reason2}, + {trace, Proc, 'receive', {exit_please, Reason2}} = receive_first_trace(), + receive_nothing(), + ok. + drop_trace_until_down(Proc, Mon) -> drop_trace_until_down(Proc, Mon, false, 0, 0). @@ -1791,6 +1817,9 @@ process(Dest) -> process(Dest); {exit_please, Reason} -> exit(Reason); + {exit_signal_please, Reason} -> + exit(self(), Reason), + process(Dest); {trap_exit_please, State} -> process_flag(trap_exit, State), process(Dest); diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex 452f3dcc07..181a718287 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index c6c105d36a..f743b7d26b 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -2110,7 +2110,7 @@ nodes(_Arg) -> | stream | {line, L :: non_neg_integer()} | {cd, Dir :: string() | binary()} - | {env, Env :: [{Name :: string(), Val :: string() | false}]} + | {env, Env :: [{Name :: os:env_var_name(), Val :: os:env_var_value() | false}]} | {args, [string() | binary()]} | {arg0, string() | binary()} | exit_status diff --git a/erts/preloaded/src/erts.app.src b/erts/preloaded/src/erts.app.src index beb29a7c89..e2ab8686d2 100644 --- a/erts/preloaded/src/erts.app.src +++ b/erts/preloaded/src/erts.app.src @@ -37,7 +37,7 @@ {registered, []}, {applications, []}, {env, []}, - {runtime_dependencies, ["stdlib-3.4.3", "kernel-5.4.1", "sasl-3.0.1"]} + {runtime_dependencies, ["stdlib-3.5", "kernel-6.0", "sasl-3.0.1"]} ]}. %% vim: ft=erlang diff --git a/erts/vsn.mk b/erts/vsn.mk index 1c6472a0ab..3d7ff2db66 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% # -VSN = 9.1.1 +VSN = 9.1.2 # Port number 4365 in 4.2 # Port number 4366 in 4.3 |