Erlang (programming language)/Tutorials/Trap exit

From Citizendium
< Erlang (programming language)‎ | Tutorials
Revision as of 13:58, 24 July 2008 by imported>Eric Evers (New page: =Trapping Exit Signals= Trapping Exit Signals is one of the most elegant parts of erlang. Under certain conditions we can cause the error message of a crashing process to be turned into a...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Trapping Exit Signals

Trapping Exit Signals is one of the most elegant parts of erlang. Under certain conditions we can cause the error message of a crashing process to be turned into a regular message to another process that is watching. In the example program we construct a monitor-worker relationship. A monitor process is watching a worker process. First we spawn the monitor, then we spawn the worker. We need to link the two processes. Then we change the process flag for trap_exit to true.

start() ->
  spawn( monitor...
  spawn( worker...
monitor() ->
  ...
  link(worker).
  process_flag(trap_exit, true).
  ...

When trap_exit==true then monitor process behaves like a system process and receives exit messages rather than exiting with its linked worker. After configuation, if the worker exits then monitor receives an {EXIT, Pid, Why} message. If the monitor wishes, it could restart the worker or do some other needed action based on the type of exit condition.

In the example code we take the log of 10, 1 and 0. Of course log(10) and log(1) have values but log(0) is undefined and causes the worker process to exit with a badarith(bad arithmatic) error.

Sample Program

%% ---
%%  trap_exit_test
%%    a simple demo of using trap_exit
%%---
-module(trap_exit_test).
-compile(export_all).

start() ->
       Pid = spawn(trap_exit_test, worker, []),
       register(work, Pid),
       spawn(trap_exit_test, monitor, [Pid]),
       work ! {log,10}, sleep(1000),
       work ! {log,1},	 sleep(1000),
       work ! {log,0}.
monitor(Pid) ->
       link(Pid),
       process_flag(trap_exit, true),
       receive
               {'EXIT', _Pid, Why} ->
                       io:format("worker exit: ~w  
                                  ~n",[Why]),
                       exit(monitor_normal_exit)
       end,
       monitor(Pid).

worker() ->
       receive
              {log, Arg} ->
                       Output = math:log(Arg),
                       io:format("log of ~w = ",[Arg]),
                       io:format("~w ~n",[Output])
       after 5000 -> 
              exit(time_out)
       end,
       worker().
sleep(T) ->
       receive
       after T -> ok
       end.

Sample Output

1> c(trap_exit_test).
{ok,trap_exit_test}

2> trap_exit_test:start().
log of 10 = 2.30259 
log of 1 = 0.00000e+0 

=ERROR REPORT==== 12-Jul-2008::10:40:53 ===
Error in process <0.37.0> with exit value:  
{badarith,[{math,log,[0]},{trap_exit_test,worker,0}]}

worker exit:  
{badarith,[{math,log,[0]},{trap_exit_test,worker,0}]} 
{log,0}