|
View:
New views
10 Messages
—
Rating Filter:
Alert me
|
|
|
Exceptions and gen_serverWhat 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 Regards, Anton ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: Exceptions and gen_serverHi Anton,
I usually do the following: foo(Params) -> case gen_server:call(?MODULE, {foo, Params}) of {error, Reason} -> erlang:error({Reason, Params}); % I return params to understand what's going on... {ok, Value} -> Value end. handle_call({create, Name, Opts}, _From, State) -> ... Regards, Roberto Aloi Erlang Training and Consulting Ltd. http://www.erlang-consulting.com 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 > > Regards, > Anton > > ________________________________________________________________ > erlang-questions mailing list. See http://www.erlang.org/faq.html > erlang-questions (at) erlang.org > > ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
RE: Exceptions and gen_serverIs there any particular reason you want to throw the value rather than just
erroring out? If you need to throw it to a catch, I'd probably do as you say, but otherwise, I'd just do a match and let an error happen when it doesn't match. Something like: a() -> {ok, Value} = gen_server:call(..., a), Value. Your handle_call looks OK to me. Cheers, David > -----Original Message----- > From: erlang-questions@... [mailto:erlang-questions@...] On > Behalf Of Anton Krasovsky > Sent: Friday, November 06, 2009 9:57 AM > To: erlang-questions@... > Subject: [erlang-questions] Exceptions and gen_server > > 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 > > Regards, > Anton > > ________________________________________________________________ > erlang-questions mailing list. See http://www.erlang.org/faq.html > erlang-questions (at) erlang.org ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: Exceptions and gen_serverSome 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 ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: Exceptions and gen_serverYou're right, your approach is better.
Regards, anton On Fri, Nov 6, 2009 at 5:08 PM, David Mercer <dmercer@...> wrote: > Is there any particular reason you want to throw the value rather than just > erroring out? If you need to throw it to a catch, I'd probably do as you > say, but otherwise, I'd just do a match and let an error happen when it > doesn't match. Something like: > > a() -> > {ok, Value} = gen_server:call(..., a), > Value. > > Your handle_call looks OK to me. > > Cheers, > > David > >> -----Original Message----- >> From: erlang-questions@... [mailto:erlang-questions@...] On >> Behalf Of Anton Krasovsky >> Sent: Friday, November 06, 2009 9:57 AM >> To: erlang-questions@... >> Subject: [erlang-questions] Exceptions and gen_server >> >> 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 >> >> Regards, >> Anton >> >> ________________________________________________________________ >> erlang-questions mailing list. See http://www.erlang.org/faq.html >> erlang-questions (at) erlang.org > > ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: Exceptions and gen_serverI suppose you'd get better stack trace in my case, but also I didn't
realize you can do exit(Pid, Reason) to a caller process. Anton On Sat, Nov 7, 2009 at 9:03 PM, Vance Shipley <vances@...> wrote: > 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 > ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: Exceptions and gen_serverOn Sat, Nov 07, 2009 at 09:33:33PM +0000, Anton Krasovsky wrote:
} I suppose you'd get better stack trace in my case, but also I didn't } realize you can do exit(Pid, Reason) to a caller process. I do use this method to handle unknown calls in servers where I'd rather the server kept running than have it fail and expose a programming error in another process. handle_call(Request, From, State) -> ... {reply, Reply, State}; handle_call(_Request, {Pid, _Tag}, State) -> exit(Pid, badarg), {noreply, State}. This way if some process attempts gen_server:call(S, foo), where foo is not a supported API call, they get the appropriate response. -- -Vance ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: Exceptions and gen_serverTrue, I'd normally just print unexpected requests, but it's better this way.
Anton On Sat, Nov 7, 2009 at 9:42 PM, Vance Shipley <vances@...> wrote: > On Sat, Nov 07, 2009 at 09:33:33PM +0000, Anton Krasovsky wrote: > } I suppose you'd get better stack trace in my case, but also I didn't > } realize you can do exit(Pid, Reason) to a caller process. > > I do use this method to handle unknown calls in servers where I'd > rather the server kept running than have it fail and expose a > programming error in another process. > > handle_call(Request, From, State) -> > ... > {reply, Reply, State}; > handle_call(_Request, {Pid, _Tag}, State) -> > exit(Pid, badarg), > {noreply, State}. > > This way if some process attempts gen_server:call(S, foo), where > foo is not a supported API call, they get the appropriate response. > > -- > -Vance > ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
|
|
Re: Exceptions and gen_serverThere have been a number of different suggestions as to how you could
program this. I think the main thing for you to decide is *HOW* you want to see the error, then it is relatively easy for you to program it. For example: - First off: do you want the error to crash the server or not? If so is links and exit signals a good enough way for you to see the error? - If the server is to live, how should your app see the error? Two valid suggestions which have been given here are: 1. Signal the error using exit/2. This "simulates" the exit signals as if the server had crashed. 2. Return an error value which either: returns an error value to the caller; or generates an error using erlang:error/1. Which is best for you depends on your app. All these solutions are easy to program so the main problem is for you to decide which is best for your app. One thing I would *NOT* do is use throw/1 to signal error! Throw is for non-local returns not errors. Using it for errors will just lead to confusion and maybe errors if other parts of app assume it is a non-local return. As try can differentiate between throw, exit and error it is important that they are used for the right thing. Robert P.S. I would LOVE to change catch now so it only catches throws, but I don't think it would be possible. :-( 2009/11/6 Anton Krasovsky <anton.krasovsky@...> > 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 > > Regards, > Anton > > ________________________________________________________________ > erlang-questions mailing list. See http://www.erlang.org/faq.html > erlang-questions (at) erlang.org > > |
|
|
Re: Exceptions and gen_serverThanks for clarifying that, especially throw vs error part!
Regards, Anton On Sun, Nov 8, 2009 at 6:47 PM, Robert Virding <rvirding@...> wrote: > There have been a number of different suggestions as to how you could > program this. I think the main thing for you to decide is *HOW* you want to > see the error, then it is relatively easy for you to program it. For > example: > > - First off: do you want the error to crash the server or not? If so is > links and exit signals a good enough way for you to see the error? > > - If the server is to live, how should your app see the error? Two valid > suggestions which have been given here are: > > 1. Signal the error using exit/2. This "simulates" the exit signals as if > the server had crashed. > 2. Return an error value which either: returns an error value to the caller; > or generates an error using erlang:error/1. Which is best for you depends on > your app. > > All these solutions are easy to program so the main problem is for you to > decide which is best for your app. > > One thing I would *NOT* do is use throw/1 to signal error! Throw is for > non-local returns not errors. Using it for errors will just lead to > confusion and maybe errors if other parts of app assume it is a non-local > return. As try can differentiate between throw, exit and error it is > important that they are used for the right thing. > > Robert > > P.S. I would LOVE to change catch now so it only catches throws, but I don't > think it would be possible. :-( > > 2009/11/6 Anton Krasovsky <anton.krasovsky@...> >> >> 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 >> >> Regards, >> Anton >> >> ________________________________________________________________ >> erlang-questions mailing list. See http://www.erlang.org/faq.html >> erlang-questions (at) erlang.org >> > > ________________________________________________________________ erlang-questions mailing list. See http://www.erlang.org/faq.html erlang-questions (at) erlang.org |
| Free embeddable forum powered by Nabble | Forum Help |