Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R15B03中的Erlang退出/2错误_Erlang_Erlang Shell - Fatal编程技术网

R15B03中的Erlang退出/2错误

R15B03中的Erlang退出/2错误,erlang,erlang-shell,Erlang,Erlang Shell,短拷贝自: exit(Pid,原因)->true 类型: Pid=Pid() 原因=term() 向进程Pid发送带有退出原因的退出信号 如果原因是除normal或kill之外的任何术语,则以下行为适用: 如果Pid未捕获退出,则Pid本身将以退出原因reason退出。如果Pid正在捕获退出,则退出信号将转换为消息{'exit',From,Reason},并传递到Pid的消息队列From是发送退出信号的进程的pid。另请参见过程标志/2 如果Reason是原子normal,Pid将不会退出。如果

短拷贝自:

exit(Pid,原因)->true

类型:

Pid=
Pid()
原因=
term()

向进程
Pid
发送带有退出原因的退出信号

如果原因是除
normal
kill
之外的任何术语,则以下行为适用:

如果
Pid
未捕获退出,则
Pid
本身将以退出原因
reason
退出。如果
Pid
正在捕获退出,则退出信号将转换为消息
{'exit',From,Reason}
,并传递到
Pid
的消息队列
From
是发送退出信号的进程的pid。另请参见
过程标志/2

如果
Reason
是原子
normal
Pid
将不会退出。如果正在捕获退出,则退出信号将转换为消息
{'exit',From,normal}
,并传递到其消息队列

如果
Reason
是原子
kill
,也就是说,如果调用
exit(Pid,kill)
,将向
Pid
发送一个不可跟踪的退出信号,该退出信号将无条件退出,退出原因
已被杀死

当使用
self()
作为
Pid
normal
作为
原因时,我正在玩弄
exit/2
函数及其行为

Erlang R15B03 (erts-5.9.3) [source] [64-bit] [smp:8:8] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.3  (abort with ^G)
1> self().
<0.32.0>
2> exit(self(), normal).
** exception exit: normal
3> self().
<0.35.0>
Erlang R15B03(erts-5.9.3)[源代码][64位][smp:8:8][异步线程:0][hipe][内核轮询:false] Eshell V5.9.3(使用^G中止) 1> self()。 2> 退出(self(),正常)。 **异常退出:正常 3> self()。
是否应该只向shell进程发送一条“正常”退出消息,因此没有理由退出

同样地:

4> spawn(fun() -> receive Pid -> Pid ! ok end end). 
<0.38.0>
5> exit(v(4), normal).
true
6> v(4) ! self().
<0.35.0>
7> flush().
Shell got ok
ok
4>生成(fun()->接收Pid->Pid!确定结束)。
5> 出口(v(4),正常)。
真的
6> v(4)!self()。
7> 刷新()。
Shell没事了
好啊
但是:

8>生成(fun()->退出(self(),normal),接收->确定结束)。
9> 进程是否活动(v(8))。
假的

看起来Erlang shell()处理
'EXIT'
类型的
普通
消息与处理其他退出消息没有任何不同,这意味着它发送错误并重新启动shell。如果您确实想了解这一点,可以使用以下方式跟踪程序流:

  • 下载
  • 将文件名更改为
    shell2.erl
  • 打开文件并将模块名称更改为
    shell2
    。您需要这样做,因为编译器会抱怨
    shell
    位于粘性目录中
  • 启动
    erl
    提示符
  • c(shell 2[debug\u info])。
  • debugger:start()。
  • 模块->解释
    并选择shell2.erl
  • shell 2:start()。
  • 走开
    看起来Erlang shell()处理
    'EXIT'
    类型的
    normal
    消息与处理其他退出消息没有任何区别,这意味着它发送错误并重新启动shell。如果您确实想了解这一点,可以使用以下方式跟踪程序流:

  • 下载
  • 将文件名更改为
    shell2.erl
  • 打开文件并将模块名称更改为
    shell2
    。您需要这样做,因为编译器会抱怨
    shell
    位于粘性目录中
  • 启动
    erl
    提示符
  • c(shell 2[debug\u info])。
  • debugger:start()。
  • 模块->解释
    并选择shell2.erl
  • shell 2:start()。
  • 走开
    我认为可以从源代码stdlib-1.18.2/src/shell.erl中找到原因

    get_command(Prompt, Eval, Bs, RT, Ds) ->
        Parse = fun() -> exit(io:parse_erl_exprs(Prompt)) end,
        Pid = spawn_link(Parse),
        get_command1(Pid, Eval, Bs, RT, Ds).
    
    get_command1(Pid, Eval, Bs, RT, Ds) ->
        receive
        {'EXIT', Pid, Res} ->
            {Res, Eval};
        {'EXIT', Eval, {Reason,Stacktrace}} ->
                report_exception(error, {Reason,Stacktrace}, RT),
            get_command1(Pid, start_eval(Bs, RT, Ds), Bs, RT, Ds);
        {'EXIT', Eval, Reason} ->
                report_exception(error, {Reason,[]}, RT),
            get_command1(Pid, start_eval(Bs, RT, Ds), Bs, RT, Ds)
        end.
    
    report_exception(Class, Reason, RT) ->
        report_exception(Class, serious, Reason, RT).
    
    report_exception(Class, Severity, {Reason,Stacktrace}, RT) ->
        Tag = severity_tag(Severity),
        I = iolist_size(Tag) + 1,
        PF = fun(Term, I1) -> pp(Term, I1, RT) end,
        SF = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
        io:requests([{put_chars, Tag},
                     {put_chars, 
                      lib:format_exception(I, Class, Reason, Stacktrace, SF, PF)},
                     nl]).
    
    start_eval(Bs, RT, Ds) ->
        Self = self(),
        Eval = spawn_link(fun() -> evaluator(Self, Bs, RT, Ds) end), %%<========start a new shell pid
        put(evaluator, Eval),
        Eval.
    
    severity_tag(fatal)   -> <<"*** ">>;
    severity_tag(serious) -> <<"** ">>;
    severity_tag(benign)  -> <<"* ">>.
    
    get_命令(提示符、Eval、Bs、RT、Ds)->
    Parse=fun()->退出(io:Parse_erl_exprs(Prompt))结束,
    Pid=生成链接(解析),
    获取命令1(Pid、Eval、Bs、RT、Ds)。
    获取命令1(Pid、评估、Bs、RT、Ds)->
    接收
    {'EXIT',Pid,Res}->
    {Res,Eval};
    {EXIT',Eval,{resash,Stacktrace}}->
    报告异常(错误,{Reason,Stacktrace},RT),
    获取命令1(Pid,开始评估(Bs,RT,Ds),Bs,RT,Ds);
    {'EXIT',Eval,Reason}->
    报告异常(错误,{原因,[]},RT),
    获取命令1(Pid,开始评估(Bs,RT,Ds),Bs,RT,Ds)
    结束。
    报告异常(类别、原因、RT)->
    报告异常(类别、严重、原因、RT)。
    报告异常(类、严重性、{Reason、Stacktrace}、RT)->
    标签=严重性标签(严重性),
    I=iolist_尺寸(标签)+1,
    PF=乐趣(学期,I1)->pp(学期,I1,RT)结束,
    SF=fun(M,F,A)->(M=:=erl\u eval)或(M=:=?模块)结束,
    io:请求([{put_chars,Tag},
    {put_chars,
    lib:format_异常(I,Class,Reason,Stacktrace,SF,PF)},
    nl])。
    开始评估(Bs、RT、Ds)->
    Self=Self(),
    Eval=spawn_link(fun()->evaluator(Self、Bs、RT、Ds)end),%;
    严重性标签(严重)->;
    严重性标签(良性)->。
    
    对于第一种情况(向self()发送消息),信号满足第二种情况
    get_command1/5
    ,它将首先给出错误消息,并生成一个新的shell pid。请注意
    start\u eval
    功能

    对于第二种情况(将消息发送到spawn
    pid
    ),返回到关于
    exit
    函数的文章的第一部分,这是合乎逻辑的。生成的
    pid
    不会捕获退出消息,并忽略
    (正常)退出
    消息。因此,只有当您的spawn
    pid
    实际退出时,
    shell才会收到退出消息。它将进入
    get_command1/5
    的第一个条件。由于未调用
    start\u evel
    shell pid
    将保持不变

    对于你的第三个案子,我不知道为什么。我还认为
    进程是否还活着(
    
    get_command(Prompt, Eval, Bs, RT, Ds) ->
        Parse = fun() -> exit(io:parse_erl_exprs(Prompt)) end,
        Pid = spawn_link(Parse),
        get_command1(Pid, Eval, Bs, RT, Ds).
    
    get_command1(Pid, Eval, Bs, RT, Ds) ->
        receive
        {'EXIT', Pid, Res} ->
            {Res, Eval};
        {'EXIT', Eval, {Reason,Stacktrace}} ->
                report_exception(error, {Reason,Stacktrace}, RT),
            get_command1(Pid, start_eval(Bs, RT, Ds), Bs, RT, Ds);
        {'EXIT', Eval, Reason} ->
                report_exception(error, {Reason,[]}, RT),
            get_command1(Pid, start_eval(Bs, RT, Ds), Bs, RT, Ds)
        end.
    
    report_exception(Class, Reason, RT) ->
        report_exception(Class, serious, Reason, RT).
    
    report_exception(Class, Severity, {Reason,Stacktrace}, RT) ->
        Tag = severity_tag(Severity),
        I = iolist_size(Tag) + 1,
        PF = fun(Term, I1) -> pp(Term, I1, RT) end,
        SF = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
        io:requests([{put_chars, Tag},
                     {put_chars, 
                      lib:format_exception(I, Class, Reason, Stacktrace, SF, PF)},
                     nl]).
    
    start_eval(Bs, RT, Ds) ->
        Self = self(),
        Eval = spawn_link(fun() -> evaluator(Self, Bs, RT, Ds) end), %%<========start a new shell pid
        put(evaluator, Eval),
        Eval.
    
    severity_tag(fatal)   -> <<"*** ">>;
    severity_tag(serious) -> <<"** ">>;
    severity_tag(benign)  -> <<"* ">>.
    
    Eshell V5.9  (abort with ^G)
    
    If Pid is not trapping exits, Pid itself will exit with exit reason Reason.
    
    1> self().
    <0.32.0>
    2> process_flag(trap_exit, true).
    false
    3> exit(self(), normal).
    true
    4> self().
    <0.32.0>
    5> flush().             
    Shell got {'EXIT',<0.32.0>,normal}
    ok