[erlang-questions] Exceptions and gen_server

Vance Shipley vances@REDACTED
Sat Nov 7 22:03:36 CET 2009


Some time ago I was asking myself whether it was better to
throw an exception in the client or the server.  In the end
I decided your method was better because SASL handled it better.

	-Vance

--------------------------------------------------------------------------
-module(foo_client).

-export([do_local/2, do_remote/2]).

do_local(Pid, Request) ->
	case gen_server:call(Pid, Request) of
		{ok, Value} ->
			Value;                                                       
		{error, Error} ->
			exit(Error)                                     
	end.

do_remote(Pid, Request) ->
	gen_server:call(Pid, Request).

--------------------------------------------------------------------------
-module(foo_server).

-behaviour(gen_server).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
			terminate/2, code_change/3]).

init(Arg) ->
	{ok, Arg}.

handle_call(foo_local, _From, State) ->
	{reply, {ok, 42}, State};
handle_call(foo_remote, _From, State) ->
	{reply, 42, State};
handle_call(bar_local, _From, State) ->
	{reply, {error, badarg}, State};
handle_call(bar_remote, {Pid, _Tag}, State) ->
	exit(Pid, badarg),
	{noreply, State}.

handle_cast(_Request, State) ->
	{noreply, State}.

handle_info(_Info, State) ->
	{noreply, State}.

terminate(_Reason, _State) ->
	ok.

code_change(_OldVsn, State, _Extra) ->
	{ok, State}.

--------------------------------------------------------------------------
1> application:start(sasl).
ok
2>  {ok, S} = gen_server:start(foo_server, [], []).
{ok,<0.45.0>}
3> foo_client:do_local(S, foo_local).
42
4> foo_client:do_local(S, bar_local).
** exception exit: badarg
     in function  foo_client:do_local/2
5> foo_client:do_remote(S, foo_remote).
42
6> foo_client:do_remote(S, bar_remote).
** exception exit: badarg
7> 


On Fri, Nov 06, 2009 at 03:57:24PM +0000, Anton Krasovsky wrote:
}  What would be the standard way of returning/throwing an exception in a
}  result to a gen_server:call?
}  
}  Would something like that be reasonable:
}  
}  a() ->
}  case gen_server:call(..., a) of
}      {ok, Value} -> Value;
}      {error, Error} -> throw({error, Error})
}  end
}  
}  and
}  
}  handle_call(a, ...) ->
}  case ... of
}      {ok, Value} -> {reply, {ok, Value} , State};
}      {error, Error} -> {reply, {error, Error} , State}
}  end


More information about the erlang-questions mailing list