繁体   English   中英

在shell中运行语句会产生不同的输出

[英]Running statements in shell gives different output

简单的代码:

-module(on_exit).
-export([on_exit/2, test/0]).

on_exit(Pid, Fun) ->
    spawn(fun() ->
                  Ref = erlang:monitor(process, Pid),
                  receive
                      {'DOWN', Ref, process, Pid, Why} ->
                          Fun(Why)
                  end
          end).

test() ->
    Fun1 = fun() -> receive Msg -> list_to_atom(Msg) end end,
    Pid1 = spawn(Fun1),

    Fun2 = fun(Why) -> io:format("~w died with error: ~w~n", [Pid1, Why]) end,
    _Pid2 = spawn(on_exit, on_exit, [Pid1, Fun2]),

    Pid1 ! hello.

在外壳中:

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

2> on_exit:test().
<0.39.0> died with error: noproc
hello

3> 
=ERROR REPORT==== 9-Apr-2017::05:16:54 ===
Error in process <0.39.0> with exit value: {badarg,[{erlang,list_to_atom,[hello],[]},{on_exit,'-test/0-fun-0-',0,[{file,"on_exit.erl"},{line,14}]}]}

预期产量:

5> Pid1 ! hello.
<0.35.0> died with error: {badarg,[{erlang,list_to_atom,[hello],[]}]}
hello

6> 
=ERROR REPORT==== 9-Apr-2017::05:15:47 ===
Error in process <0.35.0> with exit value: {badarg,[{erlang,list_to_atom,[hello],[]}]}

实际上,如果将test()中的每一行都粘贴到shell中,我将看到预期的输出。 当我在函数中运行相同的行时,为什么会出现noproc(无进程)错误?

文档

12.8显示器

监视器的替代方法是链接。 进程Pid1可以通过调用BIF erlang:monitor(process,Pid2)为Pid2创建监视器。 该函数返回参考Ref。

如果Pid2因退出原因Reason终止,则会向Pid1发送“ DOWN”消息:

 {'DOWN', Ref, process, Pid2, Reason} 

如果Pid2不存在,则会立即发送“ DOWN”消息,并将Reason设置为noproc

您的代码包含一个竞争条件spawn是异步的,并且可能在生成该进程之前返回,并且您可能最终在on_exit:on_exit/2开始监视它之前发送并崩溃了Pid1 ,这导致erlang:monitor/2调用立即向呼叫者发送noproc消息:

1> Pid = spawn(fun() -> ok end).
<0.59.0>
2> erlang:monitor(process, Pid).
#Ref<0.0.1.106>
3> flush().
Shell got {'DOWN',#Ref<0.0.1.106>,process,<0.59.0>,noproc}
ok

该代码在Shell中运行良好,可能是因为Erlang VM在外壳中执行某些事情的速度比编译该代码时慢,但是不能保证此行为。 这是经典的比赛条件。

Erlang为此提供了一个解决方案: erlang:spawn_monitor/{1,3} 保证在生成此功能后便会立即连接显示器。 您必须重新排列代码才能使用它,而不是spawn/3 + erlang:monitor/1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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