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