From 6117ee72af5c0c2973a0f20fb847a216825db03f Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 18 Mar 2016 19:46:04 +0100 Subject: runtime_tools: Make dbg work with erl_tracer modules OTP-13500 --- lib/runtime_tools/test/dbg_SUITE.erl | 79 +++++++++++++- lib/runtime_tools/test/dbg_SUITE_data/Makefile.src | 8 ++ lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c | 113 +++++++++++++++++++++ 3 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 lib/runtime_tools/test/dbg_SUITE_data/Makefile.src create mode 100644 lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c (limited to 'lib/runtime_tools/test') diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl index 458c6a2dea..17c04c0ed4 100644 --- a/lib/runtime_tools/test/dbg_SUITE.erl +++ b/lib/runtime_tools/test/dbg_SUITE.erl @@ -26,10 +26,12 @@ ip_port/1, file_port/1, file_port2/1, file_port_schedfix/1, ip_port_busy/1, wrap_port/1, wrap_port_time/1, with_seq_trace/1, dead_suspend/1, local_trace/1, - saved_patterns/1, tracer_exit_on_stop/1]). + saved_patterns/1, tracer_exit_on_stop/1, + erl_tracer/1, distributed_erl_tracer/1]). -export([init_per_testcase/2, end_per_testcase/2]). -export([tracee1/1, tracee2/1]). -export([dummy/0, exported/1]). +-export([enabled/3, trace/6, load_nif/1]). -include_lib("common_test/include/ct.hrl"). -define(default_timeout, ?t:minutes(1)). @@ -48,7 +50,8 @@ all() -> [big, tiny, simple, message, distributed, port, ip_port, file_port, file_port2, file_port_schedfix, ip_port_busy, wrap_port, wrap_port_time, with_seq_trace, dead_suspend, - local_trace, saved_patterns, tracer_exit_on_stop]. + local_trace, saved_patterns, tracer_exit_on_stop, + erl_tracer, distributed_erl_tracer]. groups() -> []. @@ -805,6 +808,78 @@ spawn_once_handler(Event, {Pid, Fun}) -> {Pid, done} end. +%% Test that erl_tracer modules work correctly +erl_tracer(Config) -> + stop(), + + ok = load_nif(Config), + + Self = self(), + {ok, _} = dbg:tracer(module, {?MODULE, Self}), + {ok, {?MODULE, Self}} = dbg:get_tracer(), + {ok, _} = dbg:p(self(), [c, timestamp]), + {ok, _} = dbg:tp(?MODULE, dummy, []), + ok = ?MODULE:dummy(), + [{Self, call, Self, Self, {?MODULE, dummy, []}, undefined, #{}}] = flush(), + ok. + +%% Test that distributed erl_tracer modules work +distributed_erl_tracer(Config) -> + stop(), + + S = self(), + + ok = load_nif(Config), + + LNode = node(), + RNode = start_slave(), + true = rpc:call(RNode, code, add_patha, [filename:join(proplists:get_value(data_dir, Config), "..")]), + ok = rpc:call(RNode, ?MODULE, load_nif, [Config]), + + NifProxy = fun() -> + register(nif_proxy, self()), + receive M -> S ! M end + end, + + LNifProxy = spawn_link(LNode, NifProxy), + RNifProxy = spawn_link(RNode, NifProxy), + + TracerFun = fun() -> {?MODULE, whereis(nif_proxy)} end, + + {ok, _} = dbg:tracer(LNode, module, TracerFun), + {ok, _} = dbg:tracer(RNode, module, TracerFun), + + {ok, [{matched, _, _}, {matched, _, _}]} = dbg:p(all,c), + {ok, [_, _]} = dbg:tp(?MODULE, dummy, []), + + {ok, {?MODULE, LNifProxy}} = dbg:get_tracer(LNode), + {ok, {?MODULE, RNifProxy}} = dbg:get_tracer(RNode), + + LCall = spawn_link(LNode, fun() -> ?MODULE:dummy() end), + [{LCall, call, LNifProxy, LCall, {?MODULE, dummy, []}, undefined, #{}}] = flush(), + + RCall = spawn_link(RNode, fun() -> ?MODULE:dummy() end), + [{RCall, call, RNifProxy, RCall, {?MODULE, dummy, []}, undefined, #{}}] = flush(), + + + ok. + +load_nif(Config) -> + SoFile = atom_to_list(?MODULE), + DataDir = proplists:get_value(data_dir, Config), + case erlang:load_nif(filename:join(DataDir, SoFile) , 0) of + {error, {reload, _}} -> + ok; + ok -> + ok + end. + +enabled(_, _, _) -> + erlang:nif_error(nif_not_loaded). + +trace(_, _, _, _, _, _) -> + erlang:nif_error(nif_not_loaded). + %% %% Support functions %% diff --git a/lib/runtime_tools/test/dbg_SUITE_data/Makefile.src b/lib/runtime_tools/test/dbg_SUITE_data/Makefile.src new file mode 100644 index 0000000000..f3d63bd4d1 --- /dev/null +++ b/lib/runtime_tools/test/dbg_SUITE_data/Makefile.src @@ -0,0 +1,8 @@ + +NIF_LIBS = dbg_SUITE@dll@ + +all: $(NIF_LIBS) + +@SHLIB_RULES@ + +$(NIF_LIBS): dbg_SUITE.c diff --git a/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c b/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c new file mode 100644 index 0000000000..45f14938c6 --- /dev/null +++ b/lib/runtime_tools/test/dbg_SUITE_data/dbg_SUITE.c @@ -0,0 +1,113 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009-2014. 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% + */ + +#include "erl_nif.h" + +#include +#include +#include +#include + +/* NIF interface declarations */ +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info); +static void unload(ErlNifEnv* env, void* priv_data); + +/* The NIFs: */ +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + +static ErlNifFunc nif_funcs[] = { + {"enabled", 3, enabled}, + {"trace", 6, trace} +}; + +ERL_NIF_INIT(dbg_SUITE, nif_funcs, load, NULL, upgrade, unload) + +static ERL_NIF_TERM atom_trace; +static ERL_NIF_TERM atom_ok; + +#define ASSERT(expr) assert(expr) + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + + atom_trace = enif_make_atom(env, "trace"); + atom_ok = enif_make_atom(env, "ok"); + + *priv_data = NULL; + + return 0; +} + +static void unload(ErlNifEnv* env, void* priv_data) +{ + +} + +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, + ERL_NIF_TERM load_info) +{ + if (*old_priv_data != NULL) { + return -1; /* Don't know how to do that */ + } + if (*priv_data != NULL) { + return -1; /* Don't know how to do that */ + } + if (load(env, priv_data, load_info)) { + return -1; + } + return 0; +} + +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int state_arity; + const ERL_NIF_TERM *state_tuple; + ERL_NIF_TERM value; + ASSERT(argc == 3); + + + return atom_trace; +} + +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int state_arity; + ErlNifPid self, to; + ERL_NIF_TERM *tuple, msg; + ASSERT(argc == 6); + + tuple = enif_alloc(sizeof(ERL_NIF_TERM)*(argc+1)); + memcpy(tuple+1,argv,sizeof(ERL_NIF_TERM)*argc); + + if (enif_self(env, &self)) { + tuple[0] = enif_make_pid(env, &self); + } else { + tuple[0] = enif_make_atom(env, "undefined"); + } + + msg = enif_make_tuple_from_array(env, tuple, argc + 1); + enif_get_local_pid(env, argv[1], &to); + enif_send(env, &to, NULL, msg); + enif_free(tuple); + + return atom_ok; +} -- cgit v1.2.3