注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Code@Pig Home

喜欢背着一袋Code傻笑的Pig .. 忧美.欢笑.记忆.忘却 .之. 角落

 
 
 

日志

 
 

[每日一Errr~lang] process die & error handling  

2010-03-02 09:03:04|  分类: lang_erlang |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
各位观众早上好,欢迎收看《每日一Errr~lang》节目。近日KKTV在装修新的办公楼,加上工作人员欢度元宵佳节,工作难免懈怠,两日没有制作节目了。在此深表歉意。

上一期我们介绍了 erlang process 的诞生与发展,本期我们将重点讨论 erlang process 死亡的过程。

erlang process 最大的好处,就是当一个 process 死亡时,可以给另一个 process 发送 exit signal。
只要通过 link(Pid),可将"调用 link(Pid) 的 process"和 Pid 两者连接起来,无论谁死亡,都会给另一方发 signal。
下面来看看在各种 exit 情况下,process 的行为。

normal exit (normal termination)
一个 process 正常执行完自己的逻辑而退出,称为 normal exit。如果 bar 不是 trap exit,则 normal exit 情况下不会给 bar 发 exit signal。
-------------------------------------------------
-module(normaldie).
-export([foo/0, bar/1]).

foo() ->
    receive
    after timer:seconds(10) -> true
    end,
    io:format("foo exit~n").

bar(Pid) ->
    link(Pid),
    receive
        Any ->
            io:format("recv ~p~n", [Any])
    end.
-------------------------------------------------
1> c(normaldie).
{ok,normaldie}
2> Pid1 = spawn(fun normaldie:foo/0).
<0.38.0>
3> Pid2 = spawn(normaldie, bar, [Pid1]).
<0.40.0>
foo exit
4> is_process_alive(Pid1).
false
5> is_process_alive(Pid2).
true
-------------------------------------------------

如果 bar 设置了 trap exit 则 foo 退出时,会给 bar 发送 exit signal。即使是 normal exit 也会发。
格式:{'EXIT', Pid, Why}, Pid 是死亡的 process id, Why 就是为啥死亡了。
-------------------------------------------------
-module(trapdie).
-export([foo/0, bar/1]).

foo() ->
    receive
    after timer:seconds(10) -> true
    end,
    io:format("foo exit~n").

bar(Pid) ->
    process_flag(trap_exit, true),
    link(Pid),
    loopbar(Pid).

loopbar(Pid) ->
    receive
        {'EXIT', Pid, Why} ->
            io:format("~p died with: ~p~n", [Pid, Why])
    end,
    loopbar(Pid).
-------------------------------------------------
1> c(trapdie).
{ok,trapdie}
2> Pid1 = spawn(fun trapdie:foo/0).
<0.38.0>
3> Pid2 = spawn(trapdie, bar, [Pid1]).
<0.40.0>
foo exit
<0.38.0> died with: normal
4> is_process_alive(Pid1).
false
5> is_process_alive(Pid2).
true
-------------------------------------------------

non-normal exit
异常退出,如果 bar 没有 trap exit,则 bar 不会收到 exit signal,且会被强制退出。
-------------------------------------------------
-module(nonnormal).
-export([foo/0, bar/1]).

foo() ->
    Val = receive
        {divide, N} ->
            1/N
    end,
    io:format("foo exit = ~p~n", [Val]).

bar(Pid) ->
    % process_flag(trap_exit, true),
    link(Pid),
    loopbar(Pid).

loopbar(Pid) ->
    receive
        {'EXIT', Pid, Why} ->
            io:format("~p died with: ~p~n", [Pid, Why])
    end,
    loopbar(Pid).
-------------------------------------------------
1> c(nonnormal).
{ok,nonnormal}
2> Pid1 = spawn(fun nonnormal:foo/0).
<0.38.0>
3> Pid2 = spawn(nonnormal, bar, [Pid1]).
<0.40.0>
4> Pid1 ! {divide, 0}.
{divide,0}

=ERROR REPORT==== 2-Mar-2010::08:28:56 ===
Error in process <0.38.0> with exit value: {badarith,[{nonnormal,foo,0}]}

5> is_process_alive(Pid1).
false
6> is_process_alive(Pid2).
false
-------------------------------------------------

如果打开 bar 的 trap exit,则结果是这样:
-------------------------------------------------
1> c(nonnormal).
{ok,nonnormal}
2> Pid1 = spawn(fun nonnormal:foo/0).
<0.38.0>
3> Pid2 = spawn(nonnormal, bar, [Pid1]).
<0.40.0>
4> Pid1 ! {divide, 0}.

=ERROR REPORT==== 2-Mar-2010::08:31:01 ===
Error in process <0.38.0> with exit value: {badarith,[{nonnormal,foo,0}]}

<0.38.0> died with: {badarith,[{nonnormal,foo,0}]}
{divide,0}
5> is_process_alive(Pid1).
false
6> is_process_alive(Pid2).
true
-------------------------------------------------

我们还可以通过调用 exit(Why) 直接退出 process。
-------------------------------------------------
-module(forceexit).
-export([foo/0, bar/1]).

foo() ->
    receive
    after timer:seconds(15) -> true
    end,
    io:format("foo exit~n"),
    exit({badarith,[{nonnormal,foo,0}]}).

bar(Pid) ->
    process_flag(trap_exit, true),
    link(Pid),
    loopbar(Pid).

loopbar(Pid) ->
    receive
        {'EXIT', Pid, Why} ->
            io:format("~p died with: ~p~n", [Pid, Why])
    end,
    loopbar(Pid).
-------------------------------------------------
1> c(forceexit).
{ok,forceexit}
2> Pid1 = spawn(fun forceexit:foo/0).
<0.38.0>
3> Pid2 = spawn(forceexit, bar, [Pid1]).
<0.40.0>
foo exit
<0.38.0> died with: {badarith,[{nonnormal,foo,0}]}
4> is_process_alive(Pid1).
false
5> is_process_alive(Pid2).
true
-------------------------------------------------

kill exit
这又可分两种情况讨论,情况一:
   <1> foo 被 kill
   <2> bar 没有开启 trap exit
   <3> foo, bar 都挂了,则 barbar 收到 killed
-------------------------------------------------
-module(killdie).
-export([foo/0, bar/1, barbar/1]).

foo() ->
    receive
    after timer:seconds(20) -> true
    end,
    io:format("foo exit~n"),
    exit(kill).

bar(Pid) ->
    % process_flag(trap_exit, true),
    link(Pid),
    loopbar(Pid).

barbar(Pid) ->
    process_flag(trap_exit, true),
    link(Pid),
    loopbar(Pid).

loopbar(Pid) ->
    receive
        {'EXIT', Pid, Why} ->
            io:format("I'm ~p, ~p died with: ~p~n", [self(), Pid, Why])
    end,
    loopbar(Pid).
-------------------------------------------------
1> c(killdie).
{ok,killdie}
2> Pid1 = spawn(fun killdie:foo/0).
<0.38.0>
3> Pid2 = spawn(killdie, bar, [Pid1]).
<0.40.0>
4> Pid3 = spawn(killdie, barbar, [Pid2]).
<0.42.0>
foo exit
I'm <0.42.0>, <0.40.0> died with: killed
-------------------------------------------------

情况二:
   <1> foo 被 kill
   <2> bar 开启 trap exit
   <3> foo 挂了,bar 收到 kill
-------------------------------------------------
1> c(killdie).
{ok,killdie}
2> Pid1 = spawn(fun killdie:foo/0).
<0.38.0>
3> Pid2 = spawn(killdie, bar, [Pid1]).
<0.40.0>
4> Pid3 = spawn(killdie, barbar, [Pid2]).
<0.42.0>
foo exit
I'm <0.40.0>, <0.38.0> died with: kill
-------------------------------------------------

情况一、二的区别,就在于 {'EXIT', Pid, Why} 中的 Why 是 kill 还是 killed。很细微的差别,具体用于啥地方呢?主持人我也还没研究出来,呵呵。

本期节目到此结束,不知道各位观众看懂了么~
  评论这张
 
阅读(808)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017