Erlang/OTP Forums

Author Message

<  Erlang questions mailing list  ~  When to catch (was: Module config data and functional progra

Guest
Posted: Sun Sep 04, 2011 1:31 am Reply with quote
Guest
This was an earlier thread of mine that inspired a new question.

As the months go by I'm getting more comfortable with "let it crash"
as an idea and seeing its benefits. But it occurs to me: surely there
are exceptions. Or rather: in order for "let it crash" to work at one
level of abstraction or functionality, there must be actual
crash-handling code at a level beneath it. In Erlang, this seems to
often involve letting individual processes crash and their supervisors
react accordingly. But perhaps that's not always the right answer. So
my question is:

When is "catch" the right tool for the job? In the example below,
Ejabberd's "hooks" handlers use catch when calling functions in
foreign modules that are (probably) not critical path to whatever it's
doing. That seems like a pretty decent case to me. Would you agree?
What are some cases common in Erlang where exceptions need to be
caught and handled (or ignored) within a single process?

dan

On Fri, Apr 22, 2011 at 1:30 PM, Per Melin <per.melin@gmail.com> wrote:
> On Fri, Apr 22, 2011 at 4:32 PM, Daniel Dormont
> <dan@greywallsoftware.com> wrote:
>> It also occurs to me that switching to gen_server would offer another advantage in that it would be easy to recover from crashes in my own code. If I were not to do that though, is the recommended practice just to put a 'catch' call around code that might break?
>
> I don't have enough context, but it sounds absolutely unnecessary to
> create a gen_server for this.
>
> I would consider it ejabberd's responsibility to handle any crashes in
> your code. They have asked you for a callback function and they must
> consider that it may break. And they are in a better position than you
> to know how to proceed from a crash here. I did have a look in
> ejabberd_hooks and they do catch exits from your function. Let it
> crash.
>
> I'm hesitant to touch the question of what is recommended practice
> since this is the kind of thread where Dr Richard O'Keefe usually
> comments after a while and turns everyone that posted before him into
> fools.
>
_______________________________________________
erlang-questions mailing list
erlang-questions@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
Post received from mailinglist
Guest
Posted: Sun Sep 04, 2011 6:34 am Reply with quote
Guest
How expensive is the state of the process to re-create? If it's super expensive, "let it crash" may not be the right choice.
Then again, if the reason you crash is that the state has gotten somehow corrupted, then crashing might be the only way to "clean it out."
And, on the third hand, when you've sufficiently hardened your application so that remote connection action cannot disturb it in unintended ways, no matter what crap gets thrown at it, then "let it crash" doesn't matter, because you won't crash anyway Smile
 
Really, I find crash-and-restart to be fine for things that really only happens once in a blue moon. For anything that's a little more common -- unexpected remote connection disconnect, bad input data or unexpected message sequencing, for example, those really are design goals of the system. If all that crashes is the connection of the badly behaving user, then that's a fine way to disconnect that user. If it's further into the core of the application, perhaps not so.
 
Sincerely,
 
jw

--
Americans might object: there is no way we would sacrifice our living standards for the benefit of people in the rest of the world. Nevertheless, whether we get there willingly or not, we shall soon have lower consumption rates, because our present rates are unsustainable.




On Sat, Sep 3, 2011 at 6:31 PM, Daniel Dormont <dan@greywallsoftware.com (dan@greywallsoftware.com)> wrote:
Quote:
This was an earlier thread of mine that inspired a new question.

As the months go by I'm getting more comfortable with "let it crash"
as an idea and seeing its benefits. But it occurs to me: surely there
are exceptions. Or rather: in order for "let it crash" to work at one
level of abstraction or functionality, there must be actual
crash-handling code at a level beneath it. In Erlang, this seems to
often involve letting individual processes crash and their supervisors
react accordingly. But perhaps that's not always the right answer. So
my question is:

When is "catch" the right tool for the job? In the example below,
Ejabberd's "hooks" handlers use catch when calling functions in
foreign modules that are (probably) not critical path to whatever it's
doing. That seems like a pretty decent case to me. Would you agree?
What are some cases common in Erlang where exceptions need to be
caught and handled (or ignored) within a single process?

dan

On Fri, Apr 22, 2011 at 1:30 PM, Per Melin <per.melin@gmail.com (per.melin@gmail.com)> wrote:
> On Fri, Apr 22, 2011 at 4:32 PM, Daniel Dormont
> <dan@greywallsoftware.com (dan@greywallsoftware.com)> wrote:
>> It also occurs to me that switching to gen_server would offer another advantage in that it would be easy to recover from crashes in my own code. If I were not to do that though, is the recommended practice just to put a 'catch' call around code that might break?
>
> I don't have enough context, but it sounds absolutely unnecessary to
> create a gen_server for this.
>
> I would consider it ejabberd's responsibility to handle any crashes in
> your code. They have asked you for a callback function and they must
> consider that it may break. And they are in a better position than you
> to know how to proceed from a crash here. I did have a look in
> ejabberd_hooks and they do catch exits from your function. Let it
> crash.
>
> I'm hesitant to touch the question of what is recommended practice
> since this is the kind of thread where Dr Richard O'Keefe usually
> comments after a while and turns everyone that posted before him into
> fools.
>
_______________________________________________
erlang-questions mailing list
erlang-questions@erlang.org (erlang-questions@erlang.org)
http://erlang.org/mailman/listinfo/erlang-questions



Post received from mailinglist
steved
Posted: Sun Sep 04, 2011 11:54 pm Reply with quote
User Joined: 29 Apr 2008 Posts: 78
On Sep 3, 8:31
View user's profile Send private message
Guest
Posted: Mon Sep 05, 2011 5:43 pm Reply with quote
Guest
On 09/04/2011 03:31 AM, Daniel Dormont wrote:
> This was an earlier thread of mine that inspired a new question.
>
> As the months go by I'm getting more comfortable with "let it crash"
> as an idea and seeing its benefits. But it occurs to me: surely there
> are exceptions. Or rather: in order for "let it crash" to work at one
> level of abstraction or functionality, there must be actual
> crash-handling code at a level beneath it. In Erlang, this seems to
> often involve letting individual processes crash and their supervisors
> react accordingly. But perhaps that's not always the right answer. So
> my question is:
>
> When is "catch" the right tool for the job? In the example below,
> Ejabberd's "hooks" handlers use catch when calling functions in
> foreign modules that are (probably) not critical path to whatever it's
> doing. That seems like a pretty decent case to me. Would you agree?
> What are some cases common in Erlang where exceptions need to be
> caught and handled (or ignored) within a single process?

Another use:

You should catch when you run foreign code from the same process.
Examples of this include gen_server, gen_fsm and friends. The gen_server
code will call functions defined in your module, which can crash.
gen_server will catch exceptions to print a meaningful error and cleanup.

--
Lo
Guest
Posted: Tue Sep 06, 2011 8:25 am Reply with quote
Guest
I just thought of another rule:

"Never return a false answer" - so the answer to "when should I let it crash" is

"you should should crash if the alternative to crashing is to return a
false answer"

Often I use the rule "you should crash if you don't know what to do".

All of this is motivated by some code I saw long, long ago. I was
reading some code.

It read (something like):

f(...) ->
...;
f(X) ->
io:format("I don't know what to do in function f X=~p~n", [X]).

Now f was a function of type int() -> int().

The last clause, however returns the atom 'ok' (this is what io:format returns).

f now produces a type incorrect return value (ie it lies about it's
type) - this will cause something else to
crash somewhere else - but we don't want the program to crash
"somewhere else" we want it to crash
*immediately* so we can debug the original error and not the knock-on
error caused by it crashing
"somewhere else".

If you *omit* the last clause of f this is exactly what will happen.

if you want *force* the programmers attention to this error then write
the last clause as exit({an_informative_tuple})

If when you wrote the program you didn't know what to do at this point
in the code - then no amount of catching
in the world will help - all you can do is report the error and return
to some stable state.

This situation occurs extremely often in programming - as you write
code you get to points where
you don't know what to do this is due to bad specifications and
incomplete understanding of the problem.
Programming *is* the art of understanding a problem - once you have
complete understood the problem
the program is in a sense "written" (at least in your head) - it
remains to type it into the machine.
Thus when the problem is not solved you will often not know what to do.

You should always crash immediate to draw attention to the problem and
not make matters worse
(that's while you are developing) - when you ship the product you
change strategy. Add a top level catch
and hide the error from the user - put as much debugging info as
possible in some error log and
tell the developer - try to return the system to a stable state.

Basically, functions should "never lie" ie if they say they are going
to do something
they should do what then say and nothing else - they should crash
rather than lie. This is the programmatic
version of "do no evil".

Hope that helps

/Joe








On Sun, Sep 4, 2011 at 3:31 AM, Daniel Dormont <dan@greywallsoftware.com> wrote:
> This was an earlier thread of mine that inspired a new question.
>
> As the months go by I'm getting more comfortable with "let it crash"
> as an idea and seeing its benefits. But it occurs to me: surely there
> are exceptions. Or rather: in order for "let it crash" to work at one
> level of abstraction or functionality, there must be actual
> crash-handling code at a level beneath it. In Erlang, this seems to
> often involve letting individual processes crash and their supervisors
> react accordingly. But perhaps that's not always the right answer. So
> my question is:
>
> When is "catch" the right tool for the job? In the example below,
> Ejabberd's "hooks" handlers use catch when calling functions in
> foreign modules that are (probably) not critical path to whatever it's
> doing. That seems like a pretty decent case to me. Would you agree?
> What are some cases common in Erlang where exceptions need to be
> caught and handled (or ignored) within a single process?
>
> dan
>
> On Fri, Apr 22, 2011 at 1:30 PM, Per Melin <per.melin@gmail.com> wrote:
>> On Fri, Apr 22, 2011 at 4:32 PM, Daniel Dormont
>> <dan@greywallsoftware.com> wrote:
>>> It also occurs to me that switching to gen_server would offer another advantage in that it would be easy to recover from crashes in my own code. If I were not to do that though, is the recommended practice just to put a 'catch' call around code that might break?
>>
>> I don't have enough context, but it sounds absolutely unnecessary to
>> create a gen_server for this.
>>
>> I would consider it ejabberd's responsibility to handle any crashes in
>> your code. They have asked you for a callback function and they must
>> consider that it may break. And they are in a better position than you
>> to know how to proceed from a crash here. I did have a look in
>> ejabberd_hooks and they do catch exits from your function. Let it
>> crash.
>>
>> I'm hesitant to touch the question of what is recommended practice
>> since this is the kind of thread where Dr Richard O'Keefe usually
>> comments after a while and turns everyone that posted before him into
>> fools.
>>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@erlang.org
> http://erlang.org/mailman/listinfo/erlang-questions
>
_______________________________________________
erlang-questions mailing list
erlang-questions@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
Post received from mailinglist
uwiger
Posted: Tue Sep 06, 2011 8:47 am Reply with quote
User Joined: 03 Jul 2006 Posts: 604 Location: Sweden
On 6 Sep 2011, at 10:24, Joe Armstrong wrote:
Quote:
Programming *is* the art of understanding a problem - once you have
complete understood the problem
the program is in a sense "written" (at least in your head) - it
remains to type it into the machine.
Thus when the problem is not solved you will often not know what to do.


I completely agree. This also leads into the domain of "accidental complexity", where the answer to why you don't know what to do in a particular spot in your code, may well be that you shouldn't ever get there in the first place. The solution then could be to choose a simpler (or more adequate) overall approach.


This is very easy to fall into in concurrency programming, and I have given some examples, e.g. in my EUC 2005 talk [1], and later in the Death by Accidental Complexity talk [2]. This comment is an example similar to Joe's, but where the authors eventually figured out what to do - even if it was a "false answer":


%%
View user's profile Send private message Visit poster's website

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum