summaryrefslogtreecommitdiff
path: root/src/r3.erl
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2018-10-22 19:46:09 -0400
committerFred Hebert <mononcqc@ferd.ca>2018-10-22 20:35:44 -0400
commit9b03dacf2b7829b584d26a999f80c315ae8ce897 (patch)
tree582cac5837e98a614b345bbd1cbf0e99c00038b7 /src/r3.erl
parent78e0d7923d78d912844e413bc82aa24ff1484d6e (diff)
Allow Breakpoints during task runs
This is mostly useful for tests, where a test suite of any kind can be interrupted halfway through so that the user can probe the running system to see what is happening. This is done as follows: 1. the user must call `r3:break()` in a test suite 2. the user runs the task as `r3:async_do(ct)` 3. the test holds up and the user can do whatever 4. the user calls `r3:resume()` and the test proceeds as normal A safeguard is added so that breakpoints are only triggered in the shell in async mode Sample session: $ rebar3 shell ... 1> rebar_agent:async_do(ct). ok ... Running Common Test suites... %%% rebar_alias_SUITE: . === BREAK === 2> % <do some checks> 2> r3:resume(). ok 3> ..... %%% rebar_as_SUITE: ........... %%% rebar_compile_SUITE: ...... ...
Diffstat (limited to 'src/r3.erl')
-rw-r--r--src/r3.erl43
1 files changed, 42 insertions, 1 deletions
diff --git a/src/r3.erl b/src/r3.erl
index bbf9eea..a79cc3a 100644
--- a/src/r3.erl
+++ b/src/r3.erl
@@ -1,8 +1,9 @@
%%% @doc external alias for `rebar_agent' for more convenient
%%% calls from a shell.
-module(r3).
--export([do/1, do/2]).
+-export([do/1, do/2, async_do/1, async_do/2, break/0, resume/0]).
-export(['$handle_undefined_function'/2]).
+-include("rebar.hrl").
%% @doc alias for `rebar_agent:do/1'
-spec do(atom()) -> ok | {error, term()}.
@@ -12,6 +13,46 @@ do(Command) -> rebar_agent:do(Command).
-spec do(atom(), atom()) -> ok | {error, term()}.
do(Namespace, Command) -> rebar_agent:do(Namespace, Command).
+%% @async_doc alias for `rebar_agent:async_do/1'
+-spec async_do(atom()) -> ok | {error, term()}.
+async_do(Command) -> rebar_agent:async_do(Command).
+
+%% @async_doc alias for `rebar_agent:async_do/2'
+-spec async_do(atom(), atom()) -> ok | {error, term()}.
+async_do(Namespace, Command) -> rebar_agent:async_do(Namespace, Command).
+
+break() ->
+ case whereis(rebar_agent) of % is the shell running
+ undefined ->
+ ok;
+ Pid ->
+ {dictionary, Dict} = process_info(Pid, dictionary),
+ case lists:keyfind(cmd_type, 1, Dict) of
+ {cmd_type, async} ->
+ Self = self(),
+ Ref = make_ref(),
+ spawn_link(fun() ->
+ register(r3_breakpoint_handler, self()),
+ receive
+ resume ->
+ Self ! Ref
+ end
+ end),
+ io:format(user, "~n=== BREAK ===~n", []),
+ receive
+ Ref -> ok
+ end;
+ _ ->
+ ?DEBUG("ignoring breakpoint since command is not run "
+ "in async mode", []),
+ ok
+ end
+ end.
+
+resume() ->
+ r3_breakpoint_handler ! resume,
+ ok.
+
%% @private defer to rebar_agent
'$handle_undefined_function'(Cmd, Args) ->
rebar_agent:'$handle_undefined_function'(Cmd, Args).