【erlang ~ 4 days】 Day # 3 Error Handling

Error Handling

出处:http://www.erlang.org/course/error_handling.html

1. 定义

  a. Link 一个exit信号的双线扩散管道

  b. Exit Signal process的exit信息

  c. Error Trapping 如果接到相linked的其他process的exit signal,可以像接受消息一样对其进行处理

 

2. Exit Signals are Sent when Processes Crash

  当一个process退出的时候,exit signal会被发送给与其相link的其他process

  Dies and sends signal to linked processes

 

3. Exit Signals propagate through Links

  如果Process A异常结束,发送了异常exit signal,那么b-f都会终止~

  Exit signals propagating, A to B to C... 

4. Processes can trap exit signals

  如果p1,p2,p3三个process的link关系如下,当p1异常退出的时候,异常的exit signal会被发送到p2,p2可以处理这个exit signal,使异常不会扩散

  Process traps exit and does not propagate exit

  

  P2 has the following code:

  receive
    {'EXIT', P1, Why} ->
      ... exit signals ...
    {P3, Msg} ->
      ... normal messages ...
  end

 

5. complex exit signal propagation

  假设我们的process的link关系如下

  Bidirectional links in chain of processes

  如果一个process发生异常

  Process that traps exit stops propagation

 

6. exit signal propagation semantics

  a. 当一个process结束的的时候,它发送一个normal或者non-normal的信号给他所有的linked的process

  b. 一个process如果不trap非正常的exit signal的话,它就会die,并且向它所有的linked的process发送non-normal的exit signal

  c. BIFs 或者pattern matching出了问题,就会向其linked的process发送automatic exit signals

 

7. robust system can be made by layering

  分层可以帮助构建一个健壮的系统,level1的process负责traplevel2中的异常,level2的process负责app层的异常

  Hierarhical layered trapping - supervision

8. primitives for exit signal handling

  a. link(Pid) 简历当前process和Pid之间的一个双向的link

  b. process_flag(trap_exit, true) 将exit signal转成exit message,这些message可以被正常的receive捕获

  c. exit(Reason) 结束process并生成一个exit signal

 

9. A robust server

  top(Free, Allocated) ->
    receive
      {Pid, alloc} ->
        top_alloc(Free, Allocated, Pid);
      {Pid ,{release, Resource}} ->
        Allocated1 = delete({Resource,Pid},�Allocated),
        top([Resource|Free], Allocated1)
      end.

  top_alloc([], Allocated, Pid) ->
    Pid ! no,
    top([], Allocated);

  top_alloc([Resource|Free], Allocated, Pid) ->
    Pid ! {yes, Resource},
    top(Free, [{Resource,Pid}|Allocated]).

   

  This is the top loop of an allocator with no error recovery. Free is a list of unreserved resources. Allocated is a list of pairs {Resource, Pid} - showing which resource has been allocated to which process.

 

10. Allocator with error recovery 

  The following is a reliable server. If a client craches after it has allocated a resource and before it has released the resource, then the server will automatically release the resource.
  The server is linked to the client during the time interval when the resource is allocted. If an exit message comes from the client during this time the resource is released.

  top_recover_alloc([], Allocated, Pid) ->
    Pid ! no,
    top_recover([], Allocated);

  top_recover_alloc([Resource|Free], Allocated, Pid) ->
  %% No need to unlink.
    Pid ! {yes, Resource},
    link(Pid),
    top_recover(Free, [{Resource,Pid}|Allocated]).

  top_recover(Free, Allocated) ->
    receive
      {Pid , alloc}�->
        top_recover_alloc(Free, Allocated, Pid);
      {Pid, {release, Resource}}�->
        unlink(Pid),
        Allocated1 = delete({Resource, Pid}, Allocated),
        top_recover([Resource|Free], Allocated1);
      {'EXIT', Pid, Reason}�->
      %% No need to unlink.
        Resource = lookup(Pid, Allocated),
        Allocated1 = delete({Resource, Pid}, Allocated),
        top_recover([Resource|Free], Allocated1)
    end.

  Not done -- multiple allocation to same process. i.e. before doing the unlink(Pid) we should check to see that the process has not allocated more than one device.

11. Allocator Utilities

  delete(H, [H|T]) ->
    T;
  delete(X, [H|T]) ->
    [H|delete(X, T)].

  lookup(Pid, [{Resource,Pid}|_]) ->
    Resource;
  lookup(Pid, [_|Allocated]) ->
    lookup(Pid, Allocated).

posted @ 2013-05-05 13:49 ~嘉言懿行~~我是煲仔饭~~ 阅读(...) 评论(...) 编辑 收藏