From 65c94fe4976cc4589e42ace1873640a0e7c73bf8 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 12 May 2016 13:57:23 +0200 Subject: erts: Fix bug when tracing in non-smp non-scheduler thread --- erts/emulator/beam/erl_nif.c | 18 +++++++-- erts/emulator/test/port_trace_SUITE.erl | 44 ++++++++++++++++++++-- .../emulator/test/port_trace_SUITE_data/echo_drv.c | 36 ++++++++++++++++++ 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 159dc66ad5..bd9367a3d5 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -667,6 +667,9 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, erts_smp_proc_trylock(rp, ERTS_PROC_LOCK_MSGQ) == EBUSY) { if (!msgq) { +#ifdef ERTS_SMP + ErtsThrPrgrDelayHandle dhndl; +#endif msgq = erts_alloc(ERTS_ALC_T_TRACE_MSG_QUEUE, sizeof(ErlTraceMessageQueue)); @@ -681,8 +684,15 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, erts_smp_proc_unlock(t_p, ERTS_PROC_LOCK_TRACE); +#ifdef ERTS_SMP + if (!scheduler) + dhndl = erts_thr_progress_unmanaged_delay(); +#endif erts_schedule_flush_trace_messages(t_p->common.id); - +#ifdef ERTS_SMP + if (!scheduler) + erts_thr_progress_unmanaged_continue(dhndl); +#endif } else { msgq->len++; *msgq->last = mp; @@ -1669,7 +1679,8 @@ int enif_is_process_alive(ErlNifEnv* env, ErlNifPid *proc) return !!rp; #else erts_exit(ERTS_ABORT_EXIT, "enif_is_process_alive: " - "called from non-scheduler thread"); + "called from non-scheduler thread " + "in non-smp emulator"); return 0; #endif } @@ -1694,7 +1705,8 @@ int enif_is_port_alive(ErlNifEnv *env, ErlNifPort *port) return !!prt; #else erts_exit(ERTS_ABORT_EXIT, "enif_is_port_alive: " - "called from non-scheduler thread"); + "called from non-scheduler thread " + "in non-smp emulator"); return 0; #endif } diff --git a/erts/emulator/test/port_trace_SUITE.erl b/erts/emulator/test/port_trace_SUITE.erl index bfdea0761b..5d9a75bcd3 100644 --- a/erts/emulator/test/port_trace_SUITE.erl +++ b/erts/emulator/test/port_trace_SUITE.erl @@ -31,7 +31,8 @@ failure_atom/1, failure_posix/1, failure/1, output_term/1, driver_output_term/1, - send_term/1, driver_send_term/1]). + send_term/1, driver_send_term/1, + driver_remote_send_term/1]). -define(ECHO_DRV_NOOP, 0). -define(ECHO_DRV_OUTPUT, 1). @@ -48,6 +49,7 @@ -define(ECHO_DRV_SEND_TERM, 12). -define(ECHO_DRV_DRIVER_SEND_TERM, 13). -define(ECHO_DRV_SAVE_CALLER, 14). +-define(ECHO_DRV_REMOTE_SEND_TERM, 15). suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {seconds, 30}}]. @@ -60,7 +62,8 @@ all() -> failure_atom, failure_posix, failure, output_term, driver_output_term, - send_term, driver_send_term]. + send_term, driver_send_term, + driver_remote_send_term]. init_per_suite(Config) -> Config. @@ -75,6 +78,13 @@ end_per_group(_GroupName, Config) -> Config. +init_per_testcase(driver_remote_send_term, Config) -> + case erlang:system_info(smp_support) of + false -> + {skip,"Only supported on smp systems"}; + true -> + init_per_testcase(driver_remote_send_term_smp, Config) + end; init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> erlang:trace(all, false, [all]), os:unsetenv("OUTPUTV"), @@ -543,6 +553,34 @@ driver_send_term(_Config) -> ok. +%% Test that driver_send_term from non-scheduler thread does not +%% generate trace messages. +driver_remote_send_term(_Config) -> + + Flags = [send], + {Prt, S} = trace_and_open(Flags,[binary]), + + erlang:port_command(Prt, <>), + recv({echo, Prt, <<123456:32>>}), + [] = flush(), + + Pid = spawn_link( + fun() -> + erlang:port_command(Prt, <>), + S ! ok, + receive M -> S ! M end + end), + recv(ok), + erlang:trace(Pid, true, ['receive']), + + erlang:port_command(Prt, <>), + recv({echo, Prt, <<123456:32>>}), + [{trace, Pid, 'receive', {echo, Prt, <<123456:32>>}}] = flush(), + + close(Prt, Flags), + + ok. + %%%%%%%%%%%%%%%%%%% %% Helper functions %%%%%%%%%%%%%%%%%%% @@ -598,7 +636,7 @@ f(From) -> end. recv(Msg) -> - receive Msg -> ok after 100 -> ct:fail({did_not_get_data,Msg,flush()}) end. + receive Msg -> ok after 1000 -> ct:fail({did_not_get_data,Msg,flush()}) end. load_drv(Config) -> Path = proplists:get_value(data_dir, Config), diff --git a/erts/emulator/test/port_trace_SUITE_data/echo_drv.c b/erts/emulator/test/port_trace_SUITE_data/echo_drv.c index b5ae9389b4..b545523192 100644 --- a/erts/emulator/test/port_trace_SUITE_data/echo_drv.c +++ b/erts/emulator/test/port_trace_SUITE_data/echo_drv.c @@ -14,6 +14,13 @@ typedef struct _erl_drv_data { ErlDrvTermData caller; } EchoDrvData; +struct remote_send_term { + char *buf; + int len; + ErlDrvTermData port; + ErlDrvTermData caller; +}; + #define ECHO_DRV_NOOP 0 #define ECHO_DRV_OUTPUT 1 #define ECHO_DRV_OUTPUT2 2 @@ -29,6 +36,7 @@ typedef struct _erl_drv_data { #define ECHO_DRV_SEND_TERM 12 #define ECHO_DRV_DRIVER_SEND_TERM 13 #define ECHO_DRV_SAVE_CALLER 14 +#define ECHO_DRV_REMOTE_SEND_TERM 15 /* ------------------------------------------------------------------------- @@ -78,6 +86,8 @@ static ErlDrvEntry echo_drv_entry = { NULL }; +static void send_term_thread(void *); + /* ------------------------------------------------------------------------- ** Entry functions **/ @@ -200,6 +210,18 @@ static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { } break; } + case ECHO_DRV_REMOTE_SEND_TERM: + { + ErlDrvTid tid; + struct remote_send_term *t = malloc(sizeof(struct remote_send_term)); + t->len = len-1; + t->buf = malloc(len-1); + t->port = driver_mk_port(port); + t->caller = data_p->caller; + memcpy(t->buf, buf+1, t->len); + erl_drv_thread_create("tmp_thread", &tid, send_term_thread, t, NULL); + break; + } case ECHO_DRV_SAVE_CALLER: data_p->caller = driver_caller(port); break; @@ -239,3 +261,17 @@ static ErlDrvSSizeT echo_drv_call(ErlDrvData drv_data, memcpy(*rbuf, buf+command, len-command); return len-command; } + +static void send_term_thread(void *a) +{ + struct remote_send_term *t = (struct remote_send_term*)a; + ErlDrvTermData term[] = { + ERL_DRV_ATOM, driver_mk_atom("echo"), + ERL_DRV_PORT, t->port, + ERL_DRV_BUF2BINARY, (ErlDrvTermData)(t->buf), + (ErlDrvTermData)(t->len), + ERL_DRV_TUPLE, 3}; + erl_drv_send_term(t->port, t->caller, + term, sizeof(term) / sizeof(ErlDrvTermData)); + return; +} -- cgit v1.2.3 From 1ba422f4e4a18dd9874c9704b73cbf38b4252fa7 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 13 May 2016 10:28:22 +0200 Subject: erts: Fix erl_tracer xml doc errors --- erts/doc/src/erl_tracer.xml | 62 ++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 40 deletions(-) diff --git a/erts/doc/src/erl_tracer.xml b/erts/doc/src/erl_tracer.xml index 7fd5512b33..d4c8bbad31 100644 --- a/erts/doc/src/erl_tracer.xml +++ b/erts/doc/src/erl_tracer.xml @@ -67,7 +67,7 @@

The different trace tags that the tracer will be called with. Each trace tag is described in greater detail in - Module:trace/6 + Module:trace/6

@@ -81,7 +81,7 @@ -

The options for the tracee. +

The options for the tracee.

timestamp If not set to undefined, the tracer has been requested to @@ -93,7 +93,6 @@ Set to a number if the scheduler id is to be included by the tracer. Otherwise it is set to undefined. -

@@ -114,30 +113,30 @@

The following functions should be exported from a erl_tracer callback module.

- Module:enabled/3 + Module:enabled/3 Mandatory - Module:trace/6 + Module:trace/6 Mandatory - Module:enabled_procs/3 + Module:enabled_procs/3 Optional - Module:trace_procs/6 + Module:trace_procs/6 Optional - Module:enabled_ports/3 + Module:enabled_ports/3 Optional - Module:trace_ports/6 + Module:trace_ports/6 Optional - Module:enabled_running_ports/3 + Module:enabled_running_ports/3 Optional - Module:trace_running_ports/6 + Module:trace_running_ports/6 Optional - Module:enabled_running_procs/3 + Module:enabled_running_procs/3 Optional - Module:trace_running_procs/6 + Module:trace_running_procs/6 Optional - + Module:enabled(TraceTag, TracerState, Tracee) -> Result @@ -166,7 +165,6 @@ is important that it is both fast and side effect free.

- Module:trace(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result Check if a trace event should be generated. @@ -181,7 +179,7 @@

This callback will be called when a tracepoint is triggered and - the Module:enabled/3 + the Module:enabled/3 callback returned trace. In it any side effects needed by the tracer should be done. The tracepoint payload is located in the FirstTraceTerm and SecondTraceTerm. The content @@ -212,7 +210,6 @@ - Module:enabled_procs(TraceTag, TracerState, Tracee) -> Result Check if a trace event should be generated. @@ -230,7 +227,6 @@ - Module:trace_procs(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result Check if a trace event should be generated. @@ -245,13 +241,12 @@

This callback will be called when a tracepoint is triggered and - the Module:enabled_procs/3 + the Module:enabled_procs/3 callback returned trace.

If trace_procs/6 is not defined trace/6 will be called instead.

- Module:enabled_ports(TraceTag, TracerState, Tracee) -> Result Check if a trace event should be generated. @@ -269,7 +264,6 @@ - Module:trace_ports(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result Check if a trace event should be generated. @@ -284,13 +278,12 @@

This callback will be called when a tracepoint is triggered and - the Module:enabled_ports/3 + the Module:enabled_ports/3 callback returned trace.

If trace_ports/6 is not defined trace/6 will be called instead.

- Module:enabled_running_procs(TraceTag, TracerState, Tracee) -> Result Check if a trace event should be generated. @@ -308,7 +301,6 @@ - Module:trace_running_procs(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result Check if a trace event should be generated. @@ -323,13 +315,12 @@

This callback will be called when a tracepoint is triggered and - the Module:enabled_running_procs/3 + the Module:enabled_running_procs/3 callback returned trace.

If trace_running_procs/6 is not defined trace/6 will be called instead.

- Module:enabled_running_ports(TraceTag, TracerState, Tracee) -> Result Check if a trace event should be generated. @@ -347,7 +338,6 @@ - Module:trace_running_ports(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result Check if a trace event should be generated. @@ -362,13 +352,12 @@

This callback will be called when a tracepoint is triggered and - the Module:enabled_running_ports/3 + the Module:enabled_running_ports/3 callback returned trace.

If trace_running_ports/6 is not defined trace/6 will be called instead.

- Module:enabled_call(TraceTag, TracerState, Tracee) -> Result Check if a trace event should be generated. @@ -386,7 +375,6 @@ - Module:trace_call(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result Check if a trace event should be generated. @@ -401,13 +389,12 @@

This callback will be called when a tracepoint is triggered and - the Module:enabled_call/3 + the Module:enabled_call/3 callback returned trace.

If trace_call/6 is not defined trace/6 will be called instead.

- Module:enabled_send(TraceTag, TracerState, Tracee) -> Result Check if a trace event should be generated. @@ -425,7 +412,6 @@ - Module:trace_send(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result Check if a trace event should be generated. @@ -440,13 +426,12 @@

This callback will be called when a tracepoint is triggered and - the Module:enabled_send/3 + the Module:enabled_send/3 callback returned trace.

If trace_send/6 is not defined trace/6 will be called instead.

- Module:enabled_receive(TraceTag, TracerState, Tracee) -> Result Check if a trace event should be generated. @@ -464,7 +449,6 @@ - Module:trace_receive(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result Check if a trace event should be generated. @@ -479,13 +463,12 @@

This callback will be called when a tracepoint is triggered and - the Module:enabled_receive/3 + the Module:enabled_receive/3 callback returned trace.

If trace_receive/6 is not defined trace/6 will be called instead.

- Module:enabled_garbage_collection(TraceTag, TracerState, Tracee) -> Result Check if a trace event should be generated. @@ -503,7 +486,6 @@ - Module:trace_garbage_collection(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result Check if a trace event should be generated. @@ -518,7 +500,7 @@

This callback will be called when a tracepoint is triggered and - the Module:enabled_garbage_collection/3 + the Module:enabled_garbage_collection/3 callback returned trace.

If trace_garbage_collection/6 is not defined trace/6 will be called instead.

-- cgit v1.2.3