From 115f0ba77ad7d01ab95fd9f9bbeca53f04f12284 Mon Sep 17 00:00:00 2001
From: Lukas Larsson The different trace tags that the tracer will be called with.
Each trace tag is described in greater detail in
- The options for the tracee.
This callback will be called when a tracepoint is triggered and
the
If
If
This callback will be called when a tracepoint is triggered and
the
If
If
This callback will be called when a tracepoint is triggered and
the
If
If
This callback will be called when a tracepoint is triggered and
the
If
If
This callback will be called when a tracepoint is triggered and
the
If
If
This callback will be called when a tracepoint is triggered and
the
If
If
This callback will be called when a tracepoint is triggered and
the
If
If
This callback will be called when a tracepoint is triggered and
the
If
If
-module(erl_msg_tracer). --export([enabled/3, trace/6, load/0]). +-export([enabled/3, trace/5, load/0]). load() -> erlang:load_nif("erl_msg_tracer", []). @@ -551,7 +546,7 @@ load() -> enabled(_, _, _) -> error. -trace(_, _, _,_, _, _) -> +trace(_, _, _,_, _) -> error.
erl_msg_tracer.c
@@ -569,7 +564,7 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ErlNifFunc nif_funcs[] = { {"enabled", 3, enabled}, - {"trace", 6, trace} + {"trace", 5, trace} }; ERL_NIF_INIT(erl_msg_tracer, nif_funcs, load, NULL, upgrade, unload) @@ -632,9 +627,8 @@ static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) * argv[0]: TraceTag, should only be 'send' * argv[1]: TracerState, process to send {argv[2], argv[4]} to * argv[2]: Tracee - * argv[3]: Message, ignored - * argv[4]: Recipient - * argv[5]: Options, ignored + * argv[3]: Recipient + * argv[4]: Options, ignored */ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index 8f65e71531..7fdce62bd1 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -228,9 +228,6 @@ atom endian atom env atom eof atom eol -atom exception_from -atom exception_trace -atom extended atom Eq='=:=' atom Eqeq='==' atom erl_tracer @@ -243,6 +240,8 @@ atom ets atom ETS_TRANSFER='ETS-TRANSFER' atom event atom exact_reductions +atom exception_from +atom exception_trace atom exclusive atom exit_status atom existing @@ -251,7 +250,9 @@ atom existing_ports atom existing atom exiting atom exports +atom extended atom external +atom extra atom false atom fcgi atom fd diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index ca001fc156..3dca58d60b 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -2625,7 +2625,7 @@ static void init_tracer_template(ErtsTracerNif *tnif) { /* default tracer functions */ tnif->tracers[TRACE_FUN_DEFAULT].name = "trace"; - tnif->tracers[TRACE_FUN_DEFAULT].arity = 6; + tnif->tracers[TRACE_FUN_DEFAULT].arity = 5; tnif->tracers[TRACE_FUN_DEFAULT].cb = NULL; tnif->tracers[TRACE_FUN_ENABLED].name = "enabled"; @@ -2634,35 +2634,35 @@ static void init_tracer_template(ErtsTracerNif *tnif) { /* specific tracer functions */ tnif->tracers[TRACE_FUN_T_SEND].name = "trace_send"; - tnif->tracers[TRACE_FUN_T_SEND].arity = 6; + tnif->tracers[TRACE_FUN_T_SEND].arity = 5; tnif->tracers[TRACE_FUN_T_SEND].cb = NULL; tnif->tracers[TRACE_FUN_T_RECEIVE].name = "trace_receive"; - tnif->tracers[TRACE_FUN_T_RECEIVE].arity = 6; + tnif->tracers[TRACE_FUN_T_RECEIVE].arity = 5; tnif->tracers[TRACE_FUN_T_RECEIVE].cb = NULL; tnif->tracers[TRACE_FUN_T_CALL].name = "trace_call"; - tnif->tracers[TRACE_FUN_T_CALL].arity = 6; + tnif->tracers[TRACE_FUN_T_CALL].arity = 5; tnif->tracers[TRACE_FUN_T_CALL].cb = NULL; tnif->tracers[TRACE_FUN_T_SCHED_PROC].name = "trace_running_procs"; - tnif->tracers[TRACE_FUN_T_SCHED_PROC].arity = 6; + tnif->tracers[TRACE_FUN_T_SCHED_PROC].arity = 5; tnif->tracers[TRACE_FUN_T_SCHED_PROC].cb = NULL; tnif->tracers[TRACE_FUN_T_SCHED_PORT].name = "trace_running_ports"; - tnif->tracers[TRACE_FUN_T_SCHED_PORT].arity = 6; + tnif->tracers[TRACE_FUN_T_SCHED_PORT].arity = 5; tnif->tracers[TRACE_FUN_T_SCHED_PORT].cb = NULL; tnif->tracers[TRACE_FUN_T_GC].name = "trace_garbage_collection"; - tnif->tracers[TRACE_FUN_T_GC].arity = 6; + tnif->tracers[TRACE_FUN_T_GC].arity = 5; tnif->tracers[TRACE_FUN_T_GC].cb = NULL; tnif->tracers[TRACE_FUN_T_PROCS].name = "trace_procs"; - tnif->tracers[TRACE_FUN_T_PROCS].arity = 6; + tnif->tracers[TRACE_FUN_T_PROCS].arity = 5; tnif->tracers[TRACE_FUN_T_PROCS].cb = NULL; tnif->tracers[TRACE_FUN_T_PORTS].name = "trace_ports"; - tnif->tracers[TRACE_FUN_T_PORTS].arity = 6; + tnif->tracers[TRACE_FUN_T_PORTS].arity = 5; tnif->tracers[TRACE_FUN_T_PORTS].cb = NULL; /* specific enabled functions */ @@ -2834,10 +2834,12 @@ send_to_tracer_nif_raw(Process *c_p, Process *tracee, Eterm tag, Eterm msg, Eterm extra, Eterm pam_result) { if (tnif || (tnif = lookup_tracer_nif(tracer)) != NULL) { -#define MAP_SIZE 3 - Eterm argv[6], local_heap[3+MAP_SIZE /* values */ + (MAP_SIZE+1 /* keys */)]; +#define MAP_SIZE 4 + Eterm argv[5], local_heap[3+MAP_SIZE /* values */ + (MAP_SIZE+1 /* keys */)]; flatmap_t *map = (flatmap_t*)(local_heap+(MAP_SIZE+1)); Eterm *map_values = flatmap_get_values(map); + Eterm *map_keys = local_heap + 1; + Uint map_elem_count = 0; topt = (tnif->tracers[topt].cb) ? topt : TRACE_FUN_DEFAULT; ASSERT(topt < NIF_TRACER_TYPES); @@ -2846,31 +2848,40 @@ send_to_tracer_nif_raw(Process *c_p, Process *tracee, argv[1] = ERTS_TRACER_STATE(tracer); argv[2] = t_p_id; argv[3] = msg; - argv[4] = extra == THE_NON_VALUE ? am_undefined : extra; - argv[5] = make_flatmap(map); + argv[4] = make_flatmap(map); map->thing_word = MAP_HEADER_FLATMAP; - map->size = MAP_SIZE; - map->keys = TUPLE3(local_heap, am_match_spec_result, am_scheduler_id, am_timestamp); - - *map_values++ = pam_result; - if (tracee_flags & F_TRACE_SCHED_NO) - *map_values++ = make_small(erts_get_scheduler_id()); - else - *map_values++ = am_undefined; + + if (extra != THE_NON_VALUE) { + map_keys[map_elem_count] = am_extra; + map_values[map_elem_count++] = extra; + } + + if (pam_result != am_true) { + map_keys[map_elem_count] = am_match_spec_result; + map_values[map_elem_count++] = pam_result; + } + + if (tracee_flags & F_TRACE_SCHED_NO) { + map_keys[map_elem_count] = am_scheduler_id; + map_values[map_elem_count++] = make_small(erts_get_scheduler_id()); + } + map_keys[map_elem_count] = am_timestamp; if (tracee_flags & F_NOW_TS) #ifdef HAVE_ERTS_NOW_CPU if (erts_cpu_timestamp) - *map_values++ = am_cpu_timestamp; + map_values[map_elem_count++] = am_cpu_timestamp; else #endif - *map_values++ = am_timestamp; + map_values[map_elem_count++] = am_timestamp; else if (tracee_flags & F_STRICT_MON_TS) - *map_values++ = am_strict_monotonic; + map_values[map_elem_count++] = am_strict_monotonic; else if (tracee_flags & F_MON_TS) - *map_values++ = am_monotonic; - else - *map_values++ = am_undefined; + map_values[map_elem_count++] = am_monotonic; + + map->size = map_elem_count; + map->keys = make_tuple(local_heap); + local_heap[0] = make_arityval(map_elem_count); #undef MAP_SIZE erts_nif_call_function(c_p, tracee ? tracee : c_p, diff --git a/erts/emulator/nifs/common/erl_tracer_nif.c b/erts/emulator/nifs/common/erl_tracer_nif.c index 6dddc80607..c0cc48ff42 100644 --- a/erts/emulator/nifs/common/erl_tracer_nif.c +++ b/erts/emulator/nifs/common/erl_tracer_nif.c @@ -45,7 +45,7 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ErlNifFunc nif_funcs[] = { {"enabled", 3, enabled}, - {"trace", 6, trace} + {"trace", 5, trace} }; @@ -57,6 +57,7 @@ ERL_NIF_INIT(erl_tracer, nif_funcs, load, NULL, upgrade, unload) ATOM_DECL(cpu_timestamp); \ ATOM_DECL(discard); \ ATOM_DECL(exception_from); \ + ATOM_DECL(extra); \ ATOM_DECL(match_spec_result); \ ATOM_DECL(monotonic); \ ATOM_DECL(ok); \ @@ -76,8 +77,7 @@ ERL_NIF_INIT(erl_tracer, nif_funcs, load, NULL, upgrade, unload) ATOM_DECL(gc_minor_start); \ ATOM_DECL(gc_minor_end); \ ATOM_DECL(gc_major_start); \ - ATOM_DECL(gc_major_end); \ - ATOM_DECL(undefined); + ATOM_DECL(gc_major_end); #define ATOM_DECL(A) static ERL_NIF_TERM atom_##A ATOMS @@ -154,11 +154,6 @@ static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) Tracee :: pid() || port() || undefined, Msg :: term(), Opts :: map()) -> ignored(). - -spec trace(Tag :: atom(), TracerState :: pid() | port(), - Tracee :: pid() || port() || undefined, - Msg :: term(), - Extra :: term(), - Opts :: map()) -> ignored(). */ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { @@ -167,7 +162,8 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ErlNifPort to_port; size_t tt_sz = 0; int is_port = 0; - ASSERT(argc == 6); + size_t opts_sz = 0; + ASSERT(argc == 5); if (!enif_get_local_pid(env, argv[1], &to_pid)) { if (!enif_get_local_port(env, argv[1], &to_port)) { @@ -179,12 +175,17 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) is_port = 1; } - if (!enif_is_identical(argv[4], atom_undefined)) { + opts = argv[4]; + + if (!enif_get_map_size(env, opts, &opts_sz)) + opts_sz = 0; + + if (opts_sz && enif_get_map_value(env, opts, atom_extra, &value)) { tt[tt_sz++] = atom_trace; tt[tt_sz++] = argv[2]; tt[tt_sz++] = argv[0]; tt[tt_sz++] = argv[3]; - tt[tt_sz++] = argv[4]; + tt[tt_sz++] = value; } else { if (enif_is_identical(argv[0], atom_seq_trace)) { tt[tt_sz++] = atom_seq_trace; @@ -198,21 +199,16 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) } } - opts = argv[5]; - if (enif_get_map_value(env, opts, atom_match_spec_result, - &value) - && !enif_is_identical(value, atom_true)) { + if (opts_sz && enif_get_map_value(env, opts, atom_match_spec_result, &value)) { tt[tt_sz++] = value; } - if (enif_get_map_value(env, opts, atom_scheduler_id, &value) - && !enif_is_identical(value, atom_undefined)) { + if (opts_sz && enif_get_map_value(env, opts, atom_scheduler_id, &value)) { tt[tt_sz++] = value; } - if (enif_get_map_value(env, opts, atom_timestamp, &value) - && !enif_is_identical(value, atom_undefined)) { + if (opts_sz && enif_get_map_value(env, opts, atom_timestamp, &value)) { ERL_NIF_TERM ts; if (enif_is_identical(value, atom_monotonic)) { ErlNifTime mon = enif_monotonic_time(ERL_NIF_NSEC); diff --git a/erts/emulator/test/tracer_SUITE.erl b/erts/emulator/test/tracer_SUITE.erl index 20fb7e475e..9eb55c9af3 100644 --- a/erts/emulator/test/tracer_SUITE.erl +++ b/erts/emulator/test/tracer_SUITE.erl @@ -28,9 +28,9 @@ init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]). -export([load/1, unload/1, reload/1, invalid_tracers/1]). --export([send/1, recv/1, spawn/1, exit/1, link/1, unlink/1, - getting_linked/1, getting_unlinked/1, register/1, unregister/1, - in/1, out/1, gc_start/1, gc_end/1]). +-export([send/1, recv/1, call/1, call_return/1, spawn/1, exit/1, + link/1, unlink/1, getting_linked/1, getting_unlinked/1, + register/1, unregister/1, in/1, out/1, gc_start/1, gc_end/1]). suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {minutes, 1}}]. @@ -39,9 +39,9 @@ all() -> [load, unload, reload, invalid_tracers, {group, basic}]. groups() -> - [{ basic, [], [send, recv, spawn, exit, link, unlink, getting_linked, - getting_unlinked, register, unregister, in, out, - gc_start, gc_end]}]. + [{ basic, [], [send, recv, call, call_return, spawn, exit, + link, unlink, getting_linked, getting_unlinked, + register, unregister, in, out, gc_start, gc_end]}]. init_per_suite(Config) -> erlang:trace_pattern({'_','_','_'}, false, [local]), @@ -223,8 +223,8 @@ send(_Config) -> Expect = fun(Pid, State, EOpts) -> receive Msg -> - {send, State, Pid, ok, Self, Opts} = Msg, - check_opts(EOpts, Opts) + {send, State, Pid, ok, Opts} = Msg, + check_opts(EOpts, Opts, Self) end end, test(send, Tc, Expect). @@ -239,13 +239,59 @@ recv(_Config) -> Expect = fun(Pid, State, EOpts) -> receive Msg -> - {'receive', State, Pid, ok, undefined, Opts} = Msg, + {'receive', State, Pid, ok, Opts} = Msg, check_opts(EOpts, Opts) end end, test('receive', Tc, Expect, false). +call(_Config) -> + + Self = self(), + Tc = fun(Pid) -> + Pid ! fun() -> call_test(Self), Self ! ok end, + receive ok -> ok after 100 -> ct:fail(timeout) end + end, + + erlang:trace_pattern({?MODULE, call_test, 1}, [], [local]), + + Expect = fun(Pid, State, EOpts) -> + receive + Msg -> + {call, State, Pid, {?MODULE, call_test, [Self]}, Opts} = Msg, + check_opts(EOpts, Opts) + end + end, + test(call, Tc, Expect). + +call_return(_Config) -> + + Self = self(), + Tc = fun(Pid) -> + Pid ! fun() -> call_test(undefined), Self ! ok end, + receive ok -> ok after 100 -> ct:fail(timeout) end + end, + + 1 = erlang:trace_pattern({?MODULE, call_test, 1}, [{'_',[],[{return_trace}]}], [local]), + + Expect = fun(Pid, State, EOpts) -> + receive + CallMsg -> + {call, State, Pid, {?MODULE, call_test, [undefined]}, COpts} = CallMsg, + check_opts(EOpts, COpts) + end, + receive + RetMsg -> + {return_from, State, Pid, {?MODULE, call_test, 1}, ROpts} = RetMsg, + check_opts(EOpts, ROpts, undefined) + end + end, + test(call, Tc, Expect). + +call_test(Arg) -> + Arg. + spawn(_Config) -> Tc = fun(Pid) -> @@ -256,9 +302,8 @@ spawn(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {spawn, State, Pid, NewPid, - {lists,seq,[1,10]}, Opts} = Msg, - check_opts(EOpts, Opts), + {spawn, State, Pid, NewPid, Opts} = Msg, + check_opts(EOpts, Opts, {lists,seq,[1,10]}), true = is_pid(NewPid) andalso NewPid /= Pid end end, @@ -274,7 +319,7 @@ exit(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {exit, State, Pid, normal, undefined, Opts} = Msg, + {exit, State, Pid, normal, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -295,7 +340,7 @@ link(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {link, State, Pid, NewPid, undefined, Opts} = Msg, + {link, State, Pid, NewPid, Opts} = Msg, check_opts(EOpts, Opts), true = is_pid(NewPid) andalso NewPid /= Pid end @@ -318,7 +363,7 @@ unlink(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {unlink, State, Pid, NewPid, undefined, Opts} = Msg, + {unlink, State, Pid, NewPid, Opts} = Msg, check_opts(EOpts, Opts), true = is_pid(NewPid) andalso NewPid /= Pid end @@ -340,7 +385,7 @@ getting_linked(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {getting_linked, State, Pid, NewPid, undefined, Opts} = Msg, + {getting_linked, State, Pid, NewPid, Opts} = Msg, check_opts(EOpts, Opts), true = is_pid(NewPid) andalso NewPid /= Pid end @@ -364,7 +409,7 @@ getting_unlinked(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {getting_unlinked, State, Pid, NewPid, undefined, Opts} = Msg, + {getting_unlinked, State, Pid, NewPid, Opts} = Msg, check_opts(EOpts, Opts), true = is_pid(NewPid) andalso NewPid /= Pid end @@ -386,7 +431,7 @@ register(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {register, State, Pid, ?MODULE, undefined, Opts} = Msg, + {register, State, Pid, ?MODULE, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -407,7 +452,7 @@ unregister(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {unregister, State, Pid, ?MODULE, undefined, Opts} = Msg, + {unregister, State, Pid, ?MODULE, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -427,8 +472,7 @@ in(_Config) -> N = (fun F(N) -> receive Msg -> - {in, State, Pid, _, - undefined, Opts} = Msg, + {in, State, Pid, _, Opts} = Msg, check_opts(EOpts, Opts), F(N+1) after 0 -> N @@ -452,8 +496,7 @@ out(_Config) -> N = (fun F(N) -> receive Msg -> - {out, State, Pid, _, - undefined, Opts} = Msg, + {out, State, Pid, _, Opts} = Msg, check_opts(EOpts, Opts), F(N+1) after 0 -> N @@ -477,7 +520,7 @@ gc_start(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {gc_major_start, State, Pid, _, undefined, Opts} = Msg, + {gc_major_start, State, Pid, _, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -497,7 +540,7 @@ gc_end(_Config) -> fun(Pid, State, EOpts) -> receive Msg -> - {gc_major_end, State, Pid, _, undefined, Opts} = Msg, + {gc_major_end, State, Pid, _, Opts} = Msg, check_opts(EOpts, Opts) end end, @@ -513,9 +556,7 @@ test(Event, TraceFlag, Tc, Expect, Removes) -> test(Event, TraceFlag, Tc, Expect, _Removes, Dies) -> ComplexState = {fun() -> ok end, <<0:(128*8)>>}, - Opts = #{ timestamp => undefined, - scheduler_id => undefined, - match_spec_result => true }, + Opts = #{ }, %% Test that trace works State1 = {#{ Event => trace }, self(), ComplexState}, @@ -540,8 +581,8 @@ test(Event, TraceFlag, Tc, Expect, _Removes, Dies) -> Tc(Pid1T), ok = trace_delivered(Pid1T), - Expect(Pid1T, State1, Opts#{ scheduler_id := number, - timestamp := timestamp}), + Expect(Pid1T, State1, Opts#{ scheduler_id => number, + timestamp => timestamp}), receive M11T -> ct:fail({unexpected, M11T}) after 0 -> ok end, if not Dies -> {flags, [scheduler_id, TraceFlag, timestamp]} @@ -568,6 +609,8 @@ test(Event, TraceFlag, Tc, Expect, _Removes, Dies) -> ok. +check_opts(E, O, Extra) -> + check_opts(E#{ extra => Extra }, O). check_opts(#{ scheduler_id := number } = E, #{ scheduler_id := N } = O) when is_integer(N) -> E1 = maps:remove(scheduler_id, E), diff --git a/erts/emulator/test/tracer_SUITE_data/tracer_test.c b/erts/emulator/test/tracer_SUITE_data/tracer_test.c index 908f35da9c..a26bb33600 100644 --- a/erts/emulator/test/tracer_SUITE_data/tracer_test.c +++ b/erts/emulator/test/tracer_SUITE_data/tracer_test.c @@ -36,7 +36,7 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ErlNifFunc nif_funcs[] = { {"enabled", 3, enabled}, - {"trace", 6, trace} + {"trace", 5, trace} }; ERL_NIF_INIT(tracer_test, nif_funcs, load, NULL, upgrade, unload) @@ -100,7 +100,7 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ErlNifPid self, to; ERL_NIF_TERM *tuple, msg; const ERL_NIF_TERM *state_tuple; - ASSERT(argc == 6); + ASSERT(argc == 5); enif_get_tuple(env, argv[1], &state_arity, &state_tuple); diff --git a/erts/emulator/test/tracer_test.erl b/erts/emulator/test/tracer_test.erl index d4778f4531..1da80bfe31 100644 --- a/erts/emulator/test/tracer_test.erl +++ b/erts/emulator/test/tracer_test.erl @@ -24,14 +24,14 @@ %%% Test tracer %%% --export([enabled/3, trace/6]). +-export([enabled/3, trace/5]). -export([load/1, load/2]). -on_load(load/0). enabled(_, _, _) -> erlang:nif_error(nif_not_loaded). -trace(_, _, _, _, _, _) -> +trace(_, _, _, _, _) -> erlang:nif_error(nif_not_loaded). load() -> diff --git a/erts/preloaded/ebin/erl_tracer.beam b/erts/preloaded/ebin/erl_tracer.beam index 69804540c9..22286ed221 100644 Binary files a/erts/preloaded/ebin/erl_tracer.beam and b/erts/preloaded/ebin/erl_tracer.beam differ diff --git a/erts/preloaded/src/erl_tracer.erl b/erts/preloaded/src/erl_tracer.erl index fe15812535..c810069d17 100644 --- a/erts/preloaded/src/erl_tracer.erl +++ b/erts/preloaded/src/erl_tracer.erl @@ -1,6 +1,6 @@ -module(erl_tracer). --export([enabled/3, trace/6, on_load/0]). +-export([enabled/3, trace/5, on_load/0]). -type tracee() :: port() | pid() | undefined. @@ -26,9 +26,9 @@ | trace_tag_running_ports() | trace_tag_gc(). --type trace_opts() :: #{ match_spec_result => true | term(), - scheduler_id => undefined | non_neg_integer(), - timestamp => undefined | timestamp | cpu_timestamp | +-type trace_opts() :: #{ extra => term(), match_spec_result => term(), + scheduler_id => non_neg_integer(), + timestamp => timestamp | cpu_timestamp | monotonic | strict_monotonic }. -type tracer_state() :: term(). @@ -41,6 +41,9 @@ on_load() -> %%% NIF placeholders %%% +%% This suppression is needed as trace_tag gets collapsed to atom() +-dialyzer({no_contracts, enabled/3}). + -spec enabled(Tag :: trace_status, TracerState :: tracer_state(), Tracee :: tracee()) -> @@ -56,8 +59,7 @@ enabled(_, _, _) -> TracerState :: tracer_state(), Tracee :: tracee(), Msg :: term(), - Extra :: term(), Opts :: trace_opts()) -> any(). -trace(_, _, _, _, _, _) -> +trace(_, _, _, _, _) -> erlang:nif_error(nif_not_loaded). diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index e7a4a73373..3d2de9c21c 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -96,14 +96,14 @@ static ErlNifFunc nif_funcs[] = { {"user_trace_i4s4", 9, user_trace_i4s4}, {"user_trace_n", 10, user_trace_n}, #ifdef HAVE_USE_LTTNG - {"trace_procs", 6, trace_procs}, - {"trace_ports", 6, trace_ports}, - {"trace_running_procs", 6, trace_running_procs}, - {"trace_running_ports", 6, trace_running_ports}, - {"trace_call", 6, trace_call}, - {"trace_send", 6, trace_send}, - {"trace_receive", 6, trace_receive}, - {"trace_garbage_collection", 6, trace_garbage_collection}, + {"trace_procs", 5, trace_procs}, + {"trace_ports", 5, trace_ports}, + {"trace_running_procs", 5, trace_running_procs}, + {"trace_running_ports", 5, trace_running_ports}, + {"trace_call", 5, trace_call}, + {"trace_send", 5, trace_send}, + {"trace_receive", 5, trace_receive}, + {"trace_garbage_collection", 5, trace_garbage_collection}, {"enabled_procs", 3, enabled_procs}, {"enabled_ports", 3, enabled_ports}, {"enabled_running_procs", 3, enabled_running_procs}, @@ -114,8 +114,7 @@ static ErlNifFunc nif_funcs[] = { {"enabled_garbage_collection", 3, enabled_garbage_collection}, #endif {"enabled", 3, enabled}, - {"trace", 5, trace}, - {"trace", 6, trace} + {"trace", 5, trace} }; ERL_NIF_INIT(dyntrace, nif_funcs, load, NULL, NULL, NULL) @@ -123,6 +122,7 @@ ERL_NIF_INIT(dyntrace, nif_funcs, load, NULL, NULL, NULL) static ERL_NIF_TERM atom_true; static ERL_NIF_TERM atom_false; static ERL_NIF_TERM atom_error; +static ERL_NIF_TERM atom_extra; static ERL_NIF_TERM atom_not_available; static ERL_NIF_TERM atom_badarg; static ERL_NIF_TERM atom_ok; @@ -187,6 +187,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_true = enif_make_atom(env,"true"); atom_false = enif_make_atom(env,"false"); atom_error = enif_make_atom(env,"error"); + atom_extra = enif_make_atom(env,"extra"); atom_not_available = enif_make_atom(env,"not_available"); atom_badarg = enif_make_atom(env,"badarg"); atom_ok = enif_make_atom(env,"ok"); @@ -325,7 +326,7 @@ static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL int arity; unsigned long ohbsz, nhbsz, size; - ASSERT(argc == 6); + ASSERT(argc == 5); /* Assume gc info order does not change */ gci = argv[3]; @@ -428,11 +429,13 @@ static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv } } else if (argv[0] == atom_exception_from) { const ERL_NIF_TERM* tuple; + ERL_NIF_TERM extra; int arity; lttng_decl_mfabuf(mfa); char class[LTTNG_BUFFER_SZ]; - enif_get_tuple(env, argv[4], &arity, &tuple); + enif_get_map_value(env, argv[4], atom_extra, &extra); + enif_get_tuple(env, extra, &arity, &tuple); enif_snprintf(class, LTTNG_BUFFER_SZ, "%T", tuple[0]); if (enif_get_tuple(env, argv[3], &arity, &tuple)) { @@ -457,14 +460,17 @@ static ERL_NIF_TERM enabled_send(ErlNifEnv *env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { + ERL_NIF_TERM extra; lttng_decl_procbuf(pid); lttng_pid_to_str(argv[2], pid); + enif_get_map_value(env, argv[4], atom_extra, &extra); + if (argv[0] == atom_send) { lttng_decl_procbuf(to); char msg[LTTNG_BUFFER_SZ]; - lttng_pid_to_str(argv[4], to); + lttng_pid_to_str(extra, to); enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); LTTNG3(message_send, pid, to, msg); @@ -472,7 +478,7 @@ static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv lttng_decl_procbuf(to); char msg[LTTNG_BUFFER_SZ]; - lttng_pid_to_str(argv[4], to); + lttng_pid_to_str(extra, to); enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); /* mark it as non existing ? */ @@ -537,6 +543,7 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg /* spawn */ if (argv[0] == atom_spawn) { + ERL_NIF_TERM extra; char undef[] = "undefined"; const ERL_NIF_TERM* tuple; int arity; @@ -545,7 +552,9 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg lttng_pid_to_str(argv[3], to); - if (enif_get_tuple(env, argv[4], &arity, &tuple)) { + enif_get_map_value(env, argv[4], atom_extra, &extra); + + if (enif_get_tuple(env, extra, &arity, &tuple)) { if (enif_is_list(env, tuple[2])) { enif_get_list_length(env, tuple[2], &len); } else { @@ -618,11 +627,13 @@ static ERL_NIF_TERM trace_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg /* open and closed */ if (argv[0] == atom_open) { + ERL_NIF_TERM extra; char driver[LTTNG_BUFFER_SZ]; lttng_decl_procbuf(pid); lttng_pid_to_str(argv[3], pid); + enif_get_map_value(env, argv[4], atom_extra, &extra); - enif_snprintf(driver, LTTNG_BUFFER_SZ, "%T", argv[4]); + enif_snprintf(driver, LTTNG_BUFFER_SZ, "%T", extra); LTTNG3(port_open, pid, driver, port); } else if (argv[0] == atom_closed) { char reason[LTTNG_BUFFER_SZ]; diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl index 28e6d67d96..58c5a773c3 100644 --- a/lib/runtime_tools/src/dyntrace.erl +++ b/lib/runtime_tools/src/dyntrace.erl @@ -42,15 +42,14 @@ -export([put_tag/1, get_tag/0, get_tag_data/0, spread_tag/1, restore_tag/1]). -export([trace/5, - trace/6, - trace_procs/6, - trace_ports/6, - trace_running_procs/6, - trace_running_ports/6, - trace_call/6, - trace_send/6, - trace_receive/6, - trace_garbage_collection/6]). + trace_procs/5, + trace_ports/5, + trace_running_procs/5, + trace_running_ports/5, + trace_call/5, + trace_send/5, + trace_receive/5, + trace_garbage_collection/5]). -export([enabled_procs/3, enabled_ports/3, @@ -147,34 +146,31 @@ user_trace_i4s4(_, _, _, _, _, _, _, _, _) -> user_trace_n(_, _, _, _, _, _, _, _, _, _) -> erlang:nif_error(nif_not_loaded). -trace(_TracerState, _Label, _SeqTraceInfo, _, _Opts) -> +trace(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). -trace(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> +trace_procs(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). -trace_procs(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> +trace_ports(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). -trace_ports(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> +trace_running_procs(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). -trace_running_procs(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> +trace_running_ports(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). -trace_running_ports(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> +trace_call(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). -trace_call(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> +trace_send(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). -trace_send(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> +trace_receive(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). -trace_receive(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> - erlang:nif_error(nif_not_loaded). - -trace_garbage_collection(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> +trace_garbage_collection(_TraceTag, _TracerState, _Tracee, _TraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). enabled(_TraceTag, _TracerState, _Tracee) -> -- cgit v1.2.3