diff options
Diffstat (limited to 'erts')
25 files changed, 305 insertions, 79 deletions
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4 index 013bfe5652..6c0544da31 100644 --- a/erts/aclocal.m4 +++ b/erts/aclocal.m4 @@ -736,10 +736,23 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK, ;; esac + clock_gettime_lib="" + AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_lib="-lrt"]) + + save_LIBS="$LIBS" + LIBS="$LIBS $clock_gettime_lib" + + if test "$LD_MAY_BE_WEAK" != "no"; then + trust_test="#error May not be there due to weak linking" + else + trust_test="" + fi + AC_CACHE_CHECK([for clock_gettime(CLOCK_MONOTONIC_RAW, _)], erl_cv_clock_gettime_monotonic_raw, [ - AC_TRY_COMPILE([ + AC_TRY_LINK([ #include <time.h> +$trust_test ], [ struct timespec ts; @@ -755,8 +768,9 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK, AC_CACHE_CHECK([for clock_gettime() with ${check_msg}monotonic clock type], erl_cv_clock_gettime_monotonic_$1, [ for clock_type in $prefer_resolution_clock_gettime_monotonic $default_resolution_clock_gettime_monotonic $high_resolution_clock_gettime_monotonic $low_resolution_clock_gettime_monotonic; do - AC_TRY_COMPILE([ + AC_TRY_LINK([ #include <time.h> +$trust_test ], [ struct timespec ts; @@ -771,7 +785,15 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK, done ]) - AC_CHECK_FUNCS([clock_getres clock_get_attributes gethrtime]) + LIBS="$save_LIBS" + + if test "$LD_MAY_BE_WEAK" != "no"; then + check_for_clock_getres= + else + check_for_clock_getres=clock_getres + fi + + AC_CHECK_FUNCS([$check_for_clock_getres clock_get_attributes gethrtime]) AC_CACHE_CHECK([for mach clock_get_time() with monotonic clock type], erl_cv_mach_clock_get_time_monotonic, [ @@ -840,7 +862,7 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK, break fi done - AC_CHECK_LIB(rt, clock_gettime, [erl_monotonic_clock_lib="-lrt"]) + erl_monotonic_clock_lib=$clock_gettime_lib ;; mach_clock_get_time) erl_monotonic_clock_id=SYSTEM_CLOCK @@ -879,11 +901,24 @@ AC_DEFUN(ERL_WALL_CLOCK, ;; esac + clock_gettime_lib="" + AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_lib="-lrt"]) + + save_LIBS="$LIBS" + LIBS="$LIBS $clock_gettime_lib" + + if test "$LD_MAY_BE_WEAK" != "no"; then + trust_test="#error May not be there due to weak linking" + else + trust_test="" + fi + AC_CACHE_CHECK([for clock_gettime() with ${check_msg}wall clock type], erl_cv_clock_gettime_wall_$1, [ for clock_type in $prefer_resolution_clock_gettime_wall $default_resolution_clock_gettime_wall $high_resolution_clock_gettime_wall $low_resolution_clock_gettime_wall; do - AC_TRY_COMPILE([ + AC_TRY_LINK([ #include <time.h> +$trust_test ], [ struct timespec ts; @@ -898,7 +933,15 @@ AC_DEFUN(ERL_WALL_CLOCK, done ]) - AC_CHECK_FUNCS([clock_getres clock_get_attributes gettimeofday]) + LIBS="$save_LIBS" + + if test "$LD_MAY_BE_WEAK" != "no"; then + check_for_clock_getres= + else + check_for_clock_getres=clock_getres + fi + + AC_CHECK_FUNCS([$check_for_clock_getres clock_get_attributes gettimeofday]) AC_CACHE_CHECK([for mach clock_get_time() with wall clock type], erl_cv_mach_clock_get_time_wall, [ @@ -919,6 +962,7 @@ AC_DEFUN(ERL_WALL_CLOCK, erl_cv_mach_clock_get_time_wall=no) ]) + erl_wall_clock_lib= erl_wall_clock_low_resolution=no erl_wall_clock_id= case $1-$erl_cv_clock_gettime_wall_$1-$erl_cv_mach_clock_get_time_wall-$ac_cv_func_gettimeofday-$host_os in @@ -932,6 +976,7 @@ AC_DEFUN(ERL_WALL_CLOCK, ;; *-CLOCK_*-*-*-*) erl_wall_clock_func=clock_gettime + erl_wall_clock_lib=$clock_gettime_lib erl_wall_clock_id=$erl_cv_clock_gettime_wall_$1 for low_res_id in $low_resolution_clock_gettime_wall; do if test $erl_wall_clock_id = $low_res_id; then @@ -1680,7 +1725,7 @@ case "$THR_LIB_NAME" in AC_DEFINE(ETHR_HAVE_SCHED_YIELD, 1, [Define if you have the sched_yield() function.]) AC_MSG_CHECKING([whether sched_yield() returns an int]) sched_yield_ret_int=no - AC_TRY_COMPILE([ + AC_TRY_LINK([ #ifdef ETHR_HAVE_SCHED_H #include <sched.h> #endif @@ -1699,7 +1744,7 @@ case "$THR_LIB_NAME" in AC_DEFINE(ETHR_HAVE_PTHREAD_YIELD, 1, [Define if you have the pthread_yield() function.]) AC_MSG_CHECKING([whether pthread_yield() returns an int]) pthread_yield_ret_int=no - AC_TRY_COMPILE([ + AC_TRY_LINK([ #if defined(ETHR_NEED_NPTL_PTHREAD_H) #include <nptl/pthread.h> #elif defined(ETHR_HAVE_MIT_PTHREAD_H) @@ -2436,7 +2481,13 @@ if test $erl_monotonic_clock_low_resolution = yes; then AC_DEFINE(ERTS_HAVE_LOW_RESOLUTION_OS_MONOTONIC_LOW, [1], [Define if you have a low resolution OS monotonic clock]) fi -xrtlib="$erl_monotonic_clock_lib" +xrtlib= +if test "$erl_monotonic_clock_lib" != ""; then + xrtlib="$erl_monotonic_clock_lib" +fi +if test "$erl_wall_clock_lib" != ""; then + xrtlib="$erl_wall_clock_lib" +fi if test "x$erl_monotonic_clock_id" != "x"; then AC_DEFINE_UNQUOTED(MONOTONIC_CLOCK_ID_STR, ["$erl_monotonic_clock_id"], [Define as a string of monotonic clock id to use]) AC_DEFINE_UNQUOTED(MONOTONIC_CLOCK_ID, [$erl_monotonic_clock_id], [Define to monotonic clock id to use]) diff --git a/erts/configure.in b/erts/configure.in index 7455516def..4799178583 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -881,6 +881,22 @@ dnl for now that is the way we do it. USER_LD=$LD USER_LDFLAGS="$LDFLAGS" LD='$(CC)' +case $host_os in + darwin*) + saved_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,-no_weak_imports" + AC_TRY_LINK([],[], + [ + LD_MAY_BE_WEAK=no + ], + [ + LD_MAY_BE_WEAK=yes + LDFLAGS="$saved_LDFLAGS" + ]);; + *) + LD_MAY_BE_WEAK=no;; +esac + AC_SUBST(LD) LDFLAG_RUNTIME_LIBRARY_PATH="$CFLAG_RUNTIME_LIBRARY_PATH" @@ -1971,7 +1987,7 @@ getaddrinfo("","",NULL,NULL); if test $have_getaddrinfo = yes; then AC_MSG_RESULT([yes]) AC_MSG_CHECKING([whether getaddrinfo accepts enough flags]) - AC_TRY_COMPILE([ + AC_TRY_LINK([ #include <stdlib.h> #include <string.h> #ifdef HAVE_WINSOCK2_H @@ -2086,7 +2102,7 @@ int main(void) { fi]);; esac -if test $have_posix_memalign = yes; then +if test "$have_posix_memalign" = "yes"; then AC_DEFINE(HAVE_POSIX_MEMALIGN,[1], [Define to 1 if you have the `posix_memalign' function.]) fi @@ -2228,7 +2244,7 @@ dnl Checks for features/quirks in the system that affects Erlang. dnl ---------------------------------------------------------------------- AC_MSG_CHECKING([for sched_getaffinity/sched_setaffinity]) -AC_TRY_COMPILE([#include <sched.h>], +AC_TRY_LINK([#include <sched.h>], [ #ifndef CPU_SETSIZE #error no CPU_SETSIZE @@ -2251,7 +2267,7 @@ fi AC_MSG_CHECKING([for pset functionality]) -AC_TRY_COMPILE([#include <sys/pset.h>], +AC_TRY_LINK([#include <sys/pset.h>], [ int res; psetid_t id = PS_MYID; @@ -2269,7 +2285,7 @@ if test $pset_functionality = yes; then fi AC_MSG_CHECKING([for processor_bind functionality]) -AC_TRY_COMPILE([ +AC_TRY_LINK([ #include <sys/types.h> #include <sys/processor.h> #include <sys/procset.h> @@ -2285,7 +2301,7 @@ if test $processor_bind_functionality = yes; then fi AC_MSG_CHECKING([for cpuset_getaffinity/cpuset_setaffinity]) -AC_TRY_COMPILE([ +AC_TRY_LINK([ #include <sys/param.h> #include <sys/cpuset.h> ], @@ -2484,7 +2500,7 @@ if test "x$ac_cv_func_sbrk" = "xyes"; then for rtype in $ret_types; do for atype in $arg_types; do IFS=$save_ifs - AC_TRY_COMPILE([#include <sys/types.h> + AC_TRY_LINK([#include <sys/types.h> #include <unistd.h>], [$rtype sbrk($atype incr);], [erts_cv_sbrk_ret_arg_types="$rtype,$atype"]) @@ -2521,7 +2537,7 @@ if test $ac_cv_func_brk = yes; then for rtype in $ret_types; do for atype in $arg_types; do IFS=$save_ifs - AC_TRY_COMPILE([#include <sys/types.h> + AC_TRY_LINK([#include <sys/types.h> #include <unistd.h>], [$rtype brk($atype endds);], [erts_cv_brk_ret_arg_types="$rtype,$atype"]) @@ -2805,7 +2821,7 @@ if test X${enable_fp_exceptions} != Xyes ; then FPE=unreliable else - AC_MSG_CHECKING([for unreliable floating point execptions]) + AC_MSG_CHECKING([for unreliable floating point exceptions]) AC_TRY_RUN([ @@ -3543,7 +3559,7 @@ fi # if test $have_kernel_poll = epoll; then AC_MSG_CHECKING([whether epoll is level triggered]) - AC_TRY_COMPILE([#include <sys/epoll.h>],[ + AC_TRY_LINK([#include <sys/epoll.h>],[ #ifdef EPOLLET /* Edge triggered option exist, assume level triggered is default */ diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index f62d3fb170..f39b640c7e 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -250,6 +250,11 @@ environment variable <c><![CDATA[DISPLAY]]></c> set to <c><![CDATA[gin:0]]></c>.</p> </item> + <tag><c><![CDATA[-epmd_module Module]]></c> (init flag)</tag> + <item> + <p>Configures the module responsible to communicate to + <seealso marker="epmd">epmd</seealso>. Defaults to <c>erl_epmd</c>.</p> + </item> <tag><c><![CDATA[-eval Expr]]></c> (init flag)</tag> <item> <p>Makes <c><![CDATA[init]]></c> evaluate the expression @@ -393,9 +398,11 @@ <tag><c><![CDATA[-pa Dir1 Dir2 ...]]></c></tag> <item> <p>Adds the specified directories to the beginning of the code - path, similar to <c><![CDATA[code:add_pathsa/1]]></c>; see - <seealso marker="kernel:code"><c>code(3)</c></seealso>. - As an alternative to <c>-pa</c>, if several directories are + path, similar to <seealso marker="kernel:code#add_pathsa/1"> + <c><![CDATA[code:add_pathsa/1]]></c></seealso>. Note that the + order of the given directories will be reversed in the + resulting path.</p> + <p>As an alternative to <c>-pa</c>, if several directories are to be prepended to the code path and the directories have a common parent directory, that parent directory can be specified in environment variable <c>ERL_LIBS</c>; see diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index 836a58a676..d8bf45c523 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -1916,9 +1916,9 @@ r = driver_async(myPort, &myKey, myData, myFunc); ]]></code> returned. Another thread can still be using the event object internally. To safely close an event object, call <c>driver_select</c> with <c>ERL_DRV_USE</c> and <c>on==0</c>, which - clears all events. Then call - <seealso marker="driver_entry#stop_select"> - <c>stop_select</c></seealso> when it is safe to close the event + clears all events and then either calls + <seealso marker="driver_entry#stop_select"><c>stop_select</c></seealso> + or schedules it to be called when it is safe to close the event object. <c>ERL_DRV_USE</c> is to be set together with the first event for an event object. It is harmless to set <c>ERL_DRV_USE</c> even if it already has been done. Clearing all events but keeping @@ -2039,7 +2039,7 @@ r = driver_async(myPort, &myKey, myData, myFunc); ]]></code> <fsummary>Set and get limits for busy port message queue.</fsummary> <desc> <marker id="erl_drv_busy_msgq_limits"></marker> - <p>Sets and gets limits that will be used for controling the + <p>Sets and gets limits that will be used for controlling the busy state of the port message queue.</p> <p>The port message queue is set into a busy state when the amount of command data queued on the @@ -2112,7 +2112,7 @@ r = driver_async(myPort, &myKey, myData, myFunc); ]]></code> It is used to identify the condition variable in planned future debug functionality.</p> <p>Returns <c>NULL</c> on failure. The driver - creating the condition variable is responsibile for + creating the condition variable is responsible for destroying it before the driver is unloaded.</p> <p>This function is thread-safe.</p> </desc> diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 950a5fe189..9646953518 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -516,7 +516,14 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> <desc> <p>Returns an Erlang term that is the result of decoding binary object <c><anno>Binary</anno></c>, which must be encoded - according to the Erlang external term format.</p> + according to the <seealso marker="erts:erl_ext_dist"> + Erlang external term format</seealso>.</p> + <pre> +> <input>Bin = term_to_binary(hello).</input> +<<131,100,0,5,104,101,108,108,111>> +> <input>hello = binary_to_term(Bin).</input> +hello +</pre> <warning> <p>When decoding binaries from untrusted sources, consider using <c>binary_to_term/2</c> to prevent Denial @@ -555,6 +562,14 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> </taglist> <p>Failure: <c>badarg</c> if <c>safe</c> is specified and unsafe data is decoded.</p> + <pre> +> <input>binary_to_term(<<131,100,0,5,104,101,108,108,111>>, [safe]).</input> +** exception error: bad argument +> <input>hello.</input> +hello +> <input>binary_to_term(<<131,100,0,5,104,101,108,108,111>>, [safe]).</input> +hello +</pre> <p>See also <seealso marker="#term_to_binary/1"><c>term_to_binary/1</c></seealso>, <seealso marker="#binary_to_term/1"> @@ -8599,12 +8614,19 @@ ok </fsummary> <desc> <p>Returns a binary data object that is the result of encoding - <c><anno>Term</anno></c> according to the Erlang external - term format.</p> + <c><anno>Term</anno></c> according to the + <seealso marker="erts:erl_ext_dist">Erlang external + term format.</seealso></p> <p>This can be used for various purposes, for example, writing a term to a file in an efficient way, or sending an Erlang term to some type of communications channel not supported by distributed Erlang.</p> + <pre> +> <input>Bin = term_to_binary(hello).</input> +<<131,100,0,5,104,101,108,108,111>> +> <input>hello = binary_to_term(Bin).</input> +hello +</pre> <p>See also <seealso marker="#binary_to_term/1"> <c>binary_to_term/1</c></seealso>.</p> </desc> @@ -9507,6 +9529,10 @@ timestamp() -> <type name="trace_info_item_result"/> <type name="trace_info_flag"/> <type name="trace_match_spec"/> + <type name="match_variable"/> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> <desc> <p>Returns trace information about a port, process, function, or event.</p> @@ -9638,6 +9664,10 @@ timestamp() -> </fsummary> <type name="trace_pattern_mfa"/> <type name="trace_match_spec"/> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> + <type name="match_variable"/> <desc> <p>The same as <seealso marker="#trace_pattern/3"> @@ -9650,6 +9680,10 @@ timestamp() -> <name name="trace_pattern" arity="3" clause_i="1"/> <fsummary>Set trace pattern for message sending.</fsummary> <type name="trace_match_spec"/> + <type name="match_variable"/> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> <desc> <p>Sets trace pattern for <em>message sending</em>. Must be combined with @@ -9717,6 +9751,10 @@ timestamp() -> <name name="trace_pattern" arity="3" clause_i="2"/> <fsummary>Set trace pattern for tracing of message receiving.</fsummary> <type name="trace_match_spec"/> + <type name="match_variable"/> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> <desc> <p>Sets trace pattern for <em>message receiving</em>. Must be combined with @@ -9787,6 +9825,10 @@ timestamp() -> <type name="trace_pattern_mfa"/> <type name="trace_match_spec"/> <type name="trace_pattern_flag"/> + <type name="match_variable"/> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> <desc> <p>Enables or disables <em>call tracing</em> for one or more functions. Must be combined with diff --git a/erts/doc/src/run_erl.xml b/erts/doc/src/run_erl.xml index ad7b2c5b85..a9b6a7e2c6 100644 --- a/erts/doc/src/run_erl.xml +++ b/erts/doc/src/run_erl.xml @@ -49,7 +49,7 @@ <funcs> <func> <name>run_erl [-daemon] pipe_dir/ log_dir "exec command - [command_arguments]"</name> + arg1 arg2 ..."</name> <fsummary>Start the Erlang emulator without attached terminal.</fsummary> <desc> <p>Arguments:</p> @@ -92,11 +92,10 @@ </item> </list> </item> - <tag><c>"exec command [command_arguments]"</c></tag> + <tag><c>"exec command arg1 arg2 ..."</c></tag> <item> - <p>In the third argument, <c><![CDATA[command]]></c> is the - executable to execute where everything written to <c>stdin</c> - and <c>stdout</c> is logged to <c><![CDATA[log_dir]]></c>.</p> + <p>A space-separated string specifying the program to be executed. + The second field is typically a command name such as <c>erl</c>.</p> </item> </taglist> </desc> @@ -105,7 +104,7 @@ <section> <title>Notes concerning the Log Files</title> - <p>While running, <c>run_erl</c> (as stated earlier) sends all output, + <p>While running, <c>run_erl</c> sends all output, uninterpreted, to a log file. The file is named <c><![CDATA[erlang.log.N]]></c>, where <c>N</c> is an integer. When the log is "full" (default log size is 100 KB), <c>run_erl</c> starts to log diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 5969197168..8af7703f51 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -1623,10 +1623,10 @@ erts_purge_state_add_fun(ErlFunEntry *fe) } Export * -erts_suspend_process_on_pending_purge_lambda(Process *c_p) +erts_suspend_process_on_pending_purge_lambda(Process *c_p, ErlFunEntry* fe) { erts_smp_mtx_lock(&purge_state.mtx); - if (is_value(purge_state.module)) { + if (purge_state.module == fe->module) { /* * The process c_p is about to call a fun in the code * that we are trying to purge. Suspend it and call diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index ef4cdf9d5a..3be5c0d24c 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -6555,7 +6555,7 @@ call_fun(Process* p, /* Current process. */ * and let it try again when the purge operation is * done (may succeed or not). */ - ep = erts_suspend_process_on_pending_purge_lambda(p); + ep = erts_suspend_process_on_pending_purge_lambda(p, fe); ASSERT(ep); } else { diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h index 1200bb9c6f..9be5e14e40 100644 --- a/erts/emulator/beam/beam_load.h +++ b/erts/emulator/beam/beam_load.h @@ -124,7 +124,8 @@ int erts_is_module_native(BeamCodeHeader* code); void erts_beam_bif_load_init(void); struct erl_fun_entry; void erts_purge_state_add_fun(struct erl_fun_entry *fe); -Export *erts_suspend_process_on_pending_purge_lambda(Process *c_p); +Export *erts_suspend_process_on_pending_purge_lambda(Process *c_p, + struct erl_fun_entry*); /* * Layout of the line table. diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c index 66e5146da0..96275eb228 100644 --- a/erts/emulator/beam/erl_bif_trace.c +++ b/erts/emulator/beam/erl_bif_trace.c @@ -512,7 +512,7 @@ start_trace(Process *c_p, ErtsTracer tracer, && !ERTS_TRACER_COMPARE(ERTS_TRACER(port), tracer)) { /* This tracee is already being traced, and not by the * tracer to be */ - if (erts_is_tracer_enabled(tracer, common)) { + if (erts_is_tracer_enabled(ERTS_TRACER(port), common)) { /* The tracer is still in use */ return 1; } @@ -715,8 +715,8 @@ Eterm erts_internal_trace_3(BIF_ALIST_3) Process* tracee_p = erts_pix2proc(i); if (! tracee_p) continue; - start_trace(p, tracer, &tracee_p->common, on, mask); - matches++; + if (!start_trace(p, tracer, &tracee_p->common, on, mask)) + matches++; } } if (ports || mods) { @@ -730,8 +730,8 @@ Eterm erts_internal_trace_3(BIF_ALIST_3) state = erts_atomic32_read_nob(&tracee_port->state); if (state & ERTS_PORT_SFLGS_DEAD) continue; - start_trace(p, tracer, &tracee_port->common, on, mask); - matches++; + if (!start_trace(p, tracer, &tracee_port->common, on, mask)) + matches++; } } } diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c index c639ba623f..5258d83a18 100644 --- a/erts/emulator/beam/erl_fun.c +++ b/erts/emulator/beam/erl_fun.c @@ -236,7 +236,6 @@ erts_fun_purge_abort_prepare(ErlFunEntry **funs, Uint no) ErlFunEntry *fe = funs[ix]; if (fe->address == unloaded_fun) fe->address = fe->pend_purge_address; - fe->pend_purge_address = NULL; } } diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 3a547982da..9a873857b9 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -3360,7 +3360,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) veto = entry->reload(&env, &lib->priv_data, BIF_ARG_2); erts_post_nif(&env); if (veto) { - ret = load_nif_error(BIF_P, reload, "Library reload-call unsuccessful."); + ret = load_nif_error(BIF_P, reload, "Library reload-call unsuccessful (%d).", veto); } else { commit_opened_resource_types(lib); @@ -3382,7 +3382,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) erts_post_nif(&env); if (veto) { prev_mi->nif->priv_data = prev_old_data; - ret = load_nif_error(BIF_P, upgrade, "Library upgrade-call unsuccessful."); + ret = load_nif_error(BIF_P, upgrade, "Library upgrade-call unsuccessful (%d).", veto); } else commit_opened_resource_types(lib); @@ -3392,7 +3392,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) veto = entry->load(&env, &lib->priv_data, BIF_ARG_2); erts_post_nif(&env); if (veto) { - ret = load_nif_error(BIF_P, "load", "Library load-call unsuccessful."); + ret = load_nif_error(BIF_P, "load", "Library load-call unsuccessful (%d).", veto); } else commit_opened_resource_types(lib); diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c index 3336fded7a..dcb6c35bfa 100644 --- a/erts/emulator/hipe/hipe_bif0.c +++ b/erts/emulator/hipe/hipe_bif0.c @@ -1476,6 +1476,10 @@ int hipe_find_mfa_from_ra(const void *ra, Eterm *m, Eterm *f, unsigned int *a) struct hipe_mfa_info **bucket; unsigned int i, nrbuckets; + if (hipe_is_ra_mode_switch(ra)) { + return 0; + } + /* Note about locking: the table is only updated from the loader, which runs with the rest of the system suspended. */ /* XXX: alas not true; see comment at hipe_mfa_info_table.lock */ diff --git a/erts/emulator/hipe/hipe_mode_switch.h b/erts/emulator/hipe/hipe_mode_switch.h index c40077d558..e54b81cf78 100644 --- a/erts/emulator/hipe/hipe_mode_switch.h +++ b/erts/emulator/hipe/hipe_mode_switch.h @@ -64,6 +64,7 @@ Eterm hipe_build_stacktrace(Process *p, struct StackTrace *s); ERTS_GLB_INLINE void hipe_reserve_beam_trap_frame(Process*, Eterm reg[], unsigned arity); ERTS_GLB_INLINE void hipe_unreserve_beam_trap_frame(Process*); +ERTS_GLB_INLINE int hipe_is_ra_mode_switch(const void* ra); extern Uint hipe_beam_pc_return[]; extern Uint hipe_beam_pc_throw[]; @@ -112,6 +113,11 @@ ERTS_GLB_INLINE void hipe_unreserve_beam_trap_frame(Process *p) p->stop += 2; } +ERTS_GLB_INLINE int hipe_is_ra_mode_switch(const void* ra) +{ + return ra == nbif_return; +} + #endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */ #endif /* ASM */ diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index ba22a100c2..99e0aea4b5 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -715,13 +715,13 @@ static RETSIGTYPE suspend_signal(void) static RETSIGTYPE suspend_signal(int signum) #endif { - int res, buf[1], __errno = errno; + int res, buf[1], tmp_errno = errno; do { res = read(sig_suspend_fds[0], buf, sizeof(int)); } while (res < 0 && errno == EINTR); /* restore previous errno in case read changed it */ - errno = __errno; + errno = tmp_errno; } #endif /* #ifdef ERTS_SYS_SUSPEND_SIGNAL */ diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 4323849465..d4e77d634a 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -976,21 +976,21 @@ try_bad_env(Env) -> %% Test that we can handle a very very large environment gracefully. huge_env(Config) when is_list(Config) -> ct:timetrap({minutes, 2}), - Vars = case os:type() of - {win32,_} -> 500; - _ -> - %% We create a huge environment, - %% 20000 variables is about 25MB - %% which seems to be the limit on Linux. - 20000 - end, + {Vars, Cmd} = case os:type() of + {win32,_} -> {500, "cmd /q /c ls"}; + _ -> + %% We create a huge environment, + %% 20000 variables is about 25MB + %% which seems to be the limit on Linux. + {20000, "ls"} + end, Env = [{[$a + I div (25*25*25*25) rem 25, $a + I div (25*25*25) rem 25, $a + I div (25*25) rem 25, $a+I div 25 rem 25, $a+I rem 25], lists:duplicate(100,$a+I rem 25)} || I <- lists:seq(1,Vars)], - try erlang:open_port({spawn,"ls"},[exit_status, {env, Env}]) of + try erlang:open_port({spawn,Cmd},[exit_status, {env, Env}]) of P -> receive {P, {exit_status,N}} = M -> @@ -1009,7 +1009,10 @@ huge_env(Config) when is_list(Config) -> %% Test to spawn program with command payload buffer %% just around pipe capacity (9f779819f6bda734c5953468f7798) pipe_limit_env(Config) when is_list(Config) -> - Cmd = "true", + Cmd = case os:type() of + {win32,_} -> "cmd /q /c true"; + _ -> "true" + end, CmdSize = command_payload_size(Cmd), Limits = [4096, 16384, 65536], % Try a couple of common pipe buffer sizes @@ -1026,7 +1029,7 @@ pipe_limit_env_do(Bytes, Cmd, CmdSize) -> try erlang:open_port({spawn,Cmd},[exit_status, {env, Env}]) of P -> receive - {P, {exit_status,N}} = M -> + {P, {exit_status,N}} -> %% Bug caused exit_status 150 (EINVAL+128) 0 = N end diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index da6a6bdea4..f846b0f4b9 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -30,7 +30,7 @@ procs_trace/1, dist_procs_trace/1, procs_new_trace/1, suspend/1, mutual_suspend/1, suspend_exit/1, suspender_exit/1, suspend_system_limit/1, suspend_opts/1, suspend_waiting/1, - new_clear/1, existing_clear/1, + new_clear/1, existing_clear/1, tracer_die/1, set_on_spawn/1, set_on_first_spawn/1, cpu_timestamp/1, set_on_link/1, set_on_first_link/1, system_monitor_args/1, more_system_monitor_args/1, @@ -54,7 +54,7 @@ all() -> send_trace, procs_trace, dist_procs_trace, suspend, mutual_suspend, suspend_exit, suspender_exit, suspend_system_limit, suspend_opts, suspend_waiting, - new_clear, existing_clear, set_on_spawn, + new_clear, existing_clear, tracer_die, set_on_spawn, set_on_first_spawn, set_on_link, set_on_first_link, system_monitor_args, more_system_monitor_args, system_monitor_long_gc_1, @@ -1636,6 +1636,34 @@ existing_clear(Config) when is_list(Config) -> ok. +%% Test that erlang:trace/3 can be called on processes where the +%% tracer has died. OTP-13928 +tracer_die(Config) when is_list(Config) -> + Proc = spawn(fun receiver/0), + + Tracer = spawn(fun receiver/0), + timer:sleep(1), + N = erlang:trace(existing, true, [send, {tracer, Tracer}]), + {flags, [send]} = erlang:trace_info(Proc, flags), + {tracer, Tracer} = erlang:trace_info(Proc, tracer), + exit(Tracer, die), + + Tracer2 = spawn(fun receiver/0), + timer:sleep(1), + N = erlang:trace(existing, true, [send, {tracer, Tracer2}]), + {flags, [send]} = erlang:trace_info(Proc, flags), + {tracer, Tracer2} = erlang:trace_info(Proc, tracer), + exit(Tracer2, die), + + Tracer3 = spawn(fun receiver/0), + timer:sleep(1), + 1 = erlang:trace(Proc, true, [send, {tracer, Tracer3}]), + {flags, [send]} = erlang:trace_info(Proc, flags), + {tracer, Tracer3} = erlang:trace_info(Proc, tracer), + exit(Tracer3, die), + + ok. + %% Test that an invalid flag cause badarg bad_flag(Config) when is_list(Config) -> %% A bad flag could deadlock the SMP emulator in erts-5.5 diff --git a/erts/etc/unix/cerl.src b/erts/etc/unix/cerl.src index c5422ab2ed..30f2d831b5 100644 --- a/erts/etc/unix/cerl.src +++ b/erts/etc/unix/cerl.src @@ -399,19 +399,29 @@ elif [ "x$GDB" = "xdump" ]; then cmdfile="/tmp/.cerlgdb.$$" case "x$core" in x/*) - gdbcmd="$EMU_NAME ${core}" ;; *) dir=`pwd` - gdbcmd="$EMU_NAME ${dir}/${core}" + core="${dir}/${core}" ;; esac - echo "set width 0 + case `uname` in + Darwin) + echo " +thread backtrace all +quit +" > $cmdfile + exec lldb -s $cmdfile -c ${core} $EMU_NAME + ;; + *) + echo "set width 0 set height 0 set verbose off source $ROOTDIR/erts/etc/unix/etp-commands thread apply all bt " > $cmdfile - exec gdb --batch --command=$cmdfile $gdbcmd + exec gdb --batch --command=$cmdfile $EMU_NAME $core + ;; + esac fi diff --git a/erts/etc/unix/etp-commands.in b/erts/etc/unix/etp-commands.in index e2bf302cca..1a4f641301 100644 --- a/erts/etc/unix/etp-commands.in +++ b/erts/etc/unix/etp-commands.in @@ -52,7 +52,7 @@ document etp-help % etpf-cons, etpf-boxed, % % Special commands for not really terms: -% etp-mfa, etp-cp, +% etp-mfa, etp-cp, etp-disasm, % etp-msgq, etpf-msgq, % etp-stacktrace, etp-stackdump, etpf-stackdump, etp-dictdump % etp-process-info, etp-process-memory-info @@ -1090,12 +1090,10 @@ document etp-mfa %--------------------------------------------------------------------------- end - - -define etp-cp-1 +define etp-cp-func-info-1 # Args: Eterm cp # -# Non-reentrant +# Non-reentrant, takes cp, sets $etp_cp_p to MFA in func_info # set $etp_cp = (Eterm)($arg0) set $etp_ranges = &r[(int)the_active_code_index] @@ -1137,8 +1135,21 @@ define etp-cp-1 end end if $etp_cp_p + set $cp_cp_p_offset = ($etp_cp-((Eterm)($etp_cp_p-2))) + else + set $cp_cp_p_offset = 0 + end +end + +define etp-cp-1 +# Args: Eterm cp +# +# Non-reentrant +# + etp-cp-func-info-1 $arg0 + if $etp_cp_p printf "#Cp" - etp-mfa-1 ($etp_cp_p) ($etp_cp-((Eterm)($etp_cp_p-2))) + etp-mfa-1 $etp_cp_p $cp_cp_p_offset else if $etp_cp == beam_apply+1 printf "#Cp<terminate process normally>" @@ -2478,11 +2489,58 @@ end document etp-schedulers %--------------------------------------------------------------------------- % etp-schedulers -% +% % Print misc info about all schedulers %--------------------------------------------------------------------------- end +define etp-disasm-1 + set $code_ptr = ((BeamInstr*)$arg0) + set $addr = *$code_ptr + set $i = 0 + while $i < (sizeof(opc) / sizeof(OpEntry)) + if $addr == beam_ops[$i] + printf "%s %d", opc[$i].name, opc[$i].sz + set $next_i = $code_ptr + opc[$i].sz + set $i += 4999 + end + set $i++ + end +end + +define etp-disasm + etp-cp-func-info-1 $arg0 + if $etp_cp_p == 0 + printf "invalid argument" + else + etp-mfa-1 $etp_cp_p $cp_cp_p_offset + printf ": " + etp-disasm-1 $arg0 + printf "\r\n" + while $next_i < ((BeamInstr*)$arg1) + set $prev_i = $next_i + etp-cp-func-info-1 $next_i + etp-mfa-1 $etp_cp_p $cp_cp_p_offset + printf ": " + etp-disasm-1 $next_i + if $prev_i == $next_i + # ptr did not advance, we are inside some strange opcode with argument + set $next_i++ + printf "instr argument" + end + printf "\r\n" + end + end +end + +document etp-disasm +%--------------------------------------------------------------------------- +% etp-disasm StartI EndI +% +% Disassemble the code inbetween StartI and EndI +%--------------------------------------------------------------------------- +end + define etp-migration-info set $minfo = (ErtsMigrationPaths *) *((UWord *) &erts_migration_paths) set $rq_ix = 0 diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex c68debeabc..fbbfefa462 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam Binary files differindex 227b62b7d3..2a7bfb8b86 100644 --- a/erts/preloaded/ebin/erts_internal.beam +++ b/erts/preloaded/ebin/erts_internal.beam diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam Binary files differindex 849273f746..74a0184818 100644 --- a/erts/preloaded/ebin/init.beam +++ b/erts/preloaded/ebin/init.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 652a954807..8771089b65 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -2408,10 +2408,11 @@ term_to_binary(_Term, _Options) -> tl(_List) -> erlang:nif_error(undefined). +-type match_variable() :: atom(). % Approximation of '$1' | '$2' | ... -type trace_pattern_mfa() :: {atom(),atom(),arity() | '_'} | on_load. -type trace_match_spec() :: - [{[term()] | '_' ,[term()],[term()]}]. + [{[term()] | '_' | match_variable() ,[term()],[term()]}]. -spec erlang:trace_pattern(MFA, MatchSpec) -> non_neg_integer() when MFA :: trace_pattern_mfa() | send | 'receive', diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl index 6aae5ba38c..f4518c4008 100644 --- a/erts/preloaded/src/erts_internal.erl +++ b/erts/preloaded/src/erts_internal.erl @@ -438,10 +438,11 @@ microstate_accounting(Ref, Threads) -> trace(_PidSpec, _How, _FlagList) -> erlang:nif_error(undefined). +-type match_variable() :: atom(). % Approximation of '$1' | '$2' | ... -type trace_pattern_mfa() :: {atom(),atom(),arity() | '_'} | on_load. -type trace_match_spec() :: - [{[term()] | '_' ,[term()],[term()]}]. + [{[term()] | '_' | match_variable() ,[term()],[term()]}]. -spec trace_pattern(MFA, MatchSpec, FlagList) -> non_neg_integer() when MFA :: trace_pattern_mfa(), diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl index 962528f7ab..551ca4ea40 100644 --- a/erts/preloaded/src/init.erl +++ b/erts/preloaded/src/init.erl @@ -205,7 +205,7 @@ boot(BootArgs) -> {Start0,Flags,Args} = parse_boot_args(BootArgs), %% We don't get to profile parsing of BootArgs - case get_flag(profile_boot, Flags, false) of + case b2a(get_flag(profile_boot, Flags, false)) of false -> ok; true -> debug_profile_start() end, @@ -782,7 +782,7 @@ do_boot(Init,Flags,Start) -> (catch erlang:system_info({purify, "Node: " ++ atom_to_list(node())})), start_em(Start), - case get_flag(profile_boot,Flags,false) of + case b2a(get_flag(profile_boot,Flags,false)) of false -> ok; true -> debug_profile_format_mfas(debug_profile_mfas()), |