diff options
author | Simon MacMullen <simon@lshift.net> | 2010-05-05 10:32:13 +0100 |
---|---|---|
committer | Simon MacMullen <simon@lshift.net> | 2010-05-05 10:32:13 +0100 |
commit | b13fede8cbcab7290d0f07c813c62c1281c56c5a (patch) | |
tree | 6d9bafe1543f149e5344f70d7bf2bef9ce6d5532 /src/delegate.erl | |
parent | 33a66243733fbf36ec32d48d9f290aece290579b (diff) | |
download | rabbitmq-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.erl | 36 |
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) -> |