catching errors from linked processes: simplest way?
Chris Pressey
cpressey@REDACTED
Tue Apr 22 22:35:16 CEST 2003
On Tue, 22 Apr 2003 08:30:14 +0200
Lennart Öhman <lennart.ohman@REDACTED> wrote:
> Hi
>
> Chris Pressey wrote:
> > OK, so, I'm actually trying to write 'aggressively simple' code now,
>
> Good! :-)
>
> The "aggressive way" when having several processes is to have one (or
> possibly several if it is a complicated system) process which
> supervises the other(s). In this way you move all the error handling,
> if you need it at all, away from the code implementing the logic.
>
> You should then try to write the code in a way that the logic works
> fine without the supervision (during normal input). The supervision is
> then only an add-on to provide robustness.
>
> /Lennart
OK! I wrote a supervisor process to catch errors from both the client
and the server, and it works fairly well.
However, I got to another sticking point. I have several functions that
only make sense under a certain condition, let's call it A. The
functions used to look like this:
foo(A, B) ->
case A of
true ->
bar(B);
false ->
{error, only_applies_under_condition_a}
end.
Now, they look like this:
foo(A, B) ->
A = true, bar(B).
which is *much* easier to read. :)
However, the error message has gone from a nice, informative one, to the
generic {badmatch, true}, which is not all that great (I'd like to be
able to give the (probably non-Erlang-literate) user a message as to
exactly why it crashed.)
I can think of two ways to handle this: either translate the error in
the client, or translate the error in the supervisor.
If I do the translation in the client, I would have:
foo(A, B) ->
case A of
true ->
bar(B);
false ->
throw(only_applies_under_condition_a)
end.
which is hardly any improvement over the original.
If I do the translation in the supervisor, I would have something like:
process_flag(trap_exits, true),
receive
...
{'EXIT', Client, {{badmatch, true}, [{module,foo,2} | Tail]}} ->
io:fwrite("Client code violated condition A~n");
...
end.
This is worrisome.
First, if I change the implementation of the client, say if I move what
foo does to another function, then I have to change the supervisor code
to reflect it.
Second, the supervisor is inferring (guessing!) that condition A was
violated because it knows that it's the only one in foo. If there were
two or more invariants in foo, it wouldn't know which one was violated.
I guess the underlying 'problem' is that there's no way (that I'm aware
of) to pass along some state when an error occurs, without causing that
error yourself. I think such a thing would be really very handy,
especially when I consider things like encountering an error when
parsing a text file - you would want the supervisor to know which line,
column, and token you choked on.
Or is this just 'too aggressive'? It seems there is a time and place
for error return values instead of crashing, and this may be it.
-Chris
More information about the erlang-questions
mailing list