简体   繁体   中英

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]).

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)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM