maoyi
maoyi

Reputation: 453

catch badarg error in the supervisor function

Here I have a program that does some simple mathematical operations. The program is running with a supervisor.

However sometimes the program would crash as I run it. Especially when I first time run calc_sup_start_link() and then some times with calc_test(). Anyone has any idea ? The program is as follows:

calc_sup_start_link() ->
  spawn_link(fun calc_sup/0).


calc_sup() ->
  process_flag(trap_exit, true),
  {ok, _Pid} = calc_start_link(),
  receive
    {'EXIT', _From, normal} ->
      ok;
    {'EXIT', _From, _Reason} ->
    calc_sup() % Crash: restart
  end.


calc_start_link() ->
  S = spawn_link(fun calc_loop/0),
  register(calc, S),
  {ok, S}


calc_loop() ->
  receive
    {add, P, A, B} ->
      P ! {add_reply, A + B},
      calc_loop();
    {mul, P, A, B} ->
      {_, _, N} = now(),
      if N rem 5 =/= 0 -> ok end,
      P ! {mul_reply, A * B},
      calc_loop()
  end.


calc_add(A, B) ->
  calc ! {add, self(), A, B},
  receive
    {add_reply, C} -> C
  end.


calc_mul(A, B) ->
  calc ! {mul, self(), A, B},
  receive
    {mul_reply, C} -> C
  end.


calc_client(X, Y, Z) ->
  Q = calc_mul(X, Y),
  timer:sleep(500),
  R = calc_add(Q, 3),
  timer:sleep(500),
  calc_mul(R, Z).


calc_test() ->
  io:format("Running calc_client(2, 4, 5)~n"),
  R = calc_client(2, 4, 5),
  io:format("calc_client(2, 4, 5) returned ~p~n", [R]).

Upvotes: 1

Views: 134

Answers (2)

kevin
kevin

Reputation: 168

if your write tail recursion all by yourself, the better way is always call external functions(for the code only save two version in memory).

like this : change calc_loop() to ?MODULE:calc_loop().

it will always call the newest version of code.

http://www.erlang.org/doc/reference_manual/code_loading.html#id88331

Upvotes: 0

Pascal
Pascal

Reputation: 14042

I think it crash in this bloc:

calc_loop() ->
  receive
    {add, P, A, B} ->
      P ! {add_reply, A + B},
      calc_loop();
    {mul, P, A, B} ->
      {_, _, N} = now(),
      if N rem 5 =/= 0 -> ok end, %% if doesn't work as in C or java !!!
      P ! {mul_reply, A * B},
      calc_loop()
  end.

in fact if N is a multiple of 5, (N rem 5) == 0 and there is no branch to evaluate the result of if, and in erlang all the statement have to return a value. You can verify in the shell:

1> if ((11 rem 5) =/= 0) -> ok end.
ok
2> if ((10 rem 5) =/= 0) -> ok end.
** exception error: no true branch found when evaluating an if expression
3> if ((10 rem 5) =/= 0) -> ok; true -> false end.
false
4> 

In your case you should write:

calc_loop() ->
  receive
    {add, P, A, B} ->
      P ! {add_reply, A + B},
      calc_loop();
    {mul, P, A, B} ->
      {_, _, N} = now(),
      case (N rem 5)  of 
         0 -> P ! {mul_reply, A * B},
              calc_loop();
         _ -> ok
       end
  end.

this will perform the multiplication and loop if N is multiple of 5; and it will terminate with reason normal in other cases (I am not sure it is what you want to do since the if expression is not complete)

Upvotes: 1

Related Questions