summaryrefslogtreecommitdiff
path: root/src/delegate.erl
diff options
context:
space:
mode:
authorSimon MacMullen <simon@lshift.net>2010-05-05 10:32:13 +0100
committerSimon MacMullen <simon@lshift.net>2010-05-05 10:32:13 +0100
commitb13fede8cbcab7290d0f07c813c62c1281c56c5a (patch)
tree6d9bafe1543f149e5344f70d7bf2bef9ce6d5532 /src/delegate.erl
parent33a66243733fbf36ec32d48d9f290aece290579b (diff)
downloadrabbitmq-server-b13fede8cbcab7290d0f07c813c62c1281c56c5a.tar.gz
Retain all exception information if thrown. Use that to rethrow in the single pid case, and mimic gen_server:multi_call in the multiple pid case.
Diffstat (limited to 'src/delegate.erl')
-rw-r--r--src/delegate.erl36
1 files changed, 25 insertions, 11 deletions
diff --git a/src/delegate.erl b/src/delegate.erl
index 104315e0..a264d60c 100644
--- a/src/delegate.erl
+++ b/src/delegate.erl
@@ -62,11 +62,24 @@ start_link(Hash) ->
gen_server2:start_link({local, server(Hash)}, ?MODULE, [], []).
invoke(Pid, Fun) when is_pid(Pid) ->
- [{Status, Res, _}] = invoke_per_node([{node(Pid), [Pid]}], Fun),
- {Status, Res};
+ [Res] = invoke_per_node([{node(Pid), [Pid]}], Fun),
+ case Res of
+ {ok, Result, _} ->
+ Result;
+ {error, {Class, Reason, StackTrace}, _} ->
+ erlang:raise(Class, Reason, StackTrace)
+ end;
invoke(Pids, Fun) when is_list(Pids) ->
- invoke_per_node(split_delegate_per_node(Pids), Fun).
+ lists:foldl(
+ fun({Status, Result, Pid}, {Good, Bad}) ->
+ case Status of
+ ok -> {[{Pid, Result}|Good], Bad};
+ error -> {Good, [{Pid, Result}|Bad]}
+ end
+ end,
+ {[], []},
+ invoke_per_node(split_delegate_per_node(Pids), Fun)).
invoke_no_result(Pid, Fun) when is_pid(Pid) ->
invoke_no_result_per_node([{node(Pid), [Pid]}], Fun),
@@ -156,12 +169,11 @@ server(Hash) ->
list_to_atom("delegate_process_" ++ integer_to_list(Hash)).
safe_invoke(Fun, Pid) ->
- %% We need the catch here for the local case. In the remote case
- %% there will already have been a catch in handle_ca{ll,st} below,
- %% but that's OK, catch is idempotent.
- case catch Fun(Pid) of
- {'EXIT', Reason} -> {error, {'EXIT', Reason}, Pid};
- Result -> {ok, Result, Pid}
+ try
+ {ok, Fun(Pid), Pid}
+ catch
+ Class:Reason ->
+ {error, {Class, Reason, erlang:get_stacktrace()}, Pid}
end.
process_count() ->
@@ -173,11 +185,13 @@ init([]) ->
{ok, no_state, hibernate,
{backoff, ?HIBERNATE_AFTER_MIN, ?HIBERNATE_AFTER_MIN, ?DESIRED_HIBERNATE}}.
+%% We don't need a catch here; we always go via safe_invoke. A catch here would
+%% be the wrong thing anyway since the Thunk can throw multiple errors.
handle_call({thunk, Thunk}, _From, State) ->
- {reply, catch Thunk(), State, hibernate}.
+ {reply, Thunk(), State, hibernate}.
handle_cast({thunk, Thunk}, State) ->
- catch Thunk(),
+ Thunk(),
{noreply, State, hibernate}.
handle_info(_Info, State) ->