簡體   English   中英

產生和接收的erlang種族條件

[英]erlang race condition of spawn and receive

我正在用書學習erlang,在第13章中,第一個練習是編寫函數my_spawn,該函數在生成的消息崩潰/退出時捕獲退出消息。

-module(my_spawn1).
-compile(export_all).

my_spawn(Mod,Func,Args) ->
    {M1, S1, Mi1} = os:timestamp(),
    Pid = spawn(Mod,Func,Args),
    lib_misc:on_exit(Pid, fun(Why) ->
                  {M2,S2,Mi2} = os:timestamp(),
                  ElapsedTime = (M2 - M1) * 1000000 + (S2 - S1) * 1000 + (Mi2-Mi1),
                  io:format("~p died with:~p~n consume time:~p(ms)", [Pid,Why,ElapsedTime]),
              end),
    Pid.

我的困惑是,如果在spawn_monitor之后完成了Mod:Func(Args) ,但是lib_misc:on_exit(...)尚未設置,那么退出消息將會丟失,真的嗎?

如果正確,那么如何解決這種情況?

[帕斯卡編輯]

我添加了lib_misc:on_exit / 2的代碼

on_exit(Pid, Fun) ->
    spawn(fun() -> 
          process_flag(trap_exit, true), %% <label id="code.onexit1"/>
          link(Pid),                     %% <label id="code.onexit2"/>
          receive
              {'EXIT', Pid, Why} ->      %% <label id="code.onexit3"/>
              Fun(Why)   %% <label id="code.onexit4"/>
          end
      end).

不,該消息(如所有消息)將排隊。 但是,如果接收該消息的進程死亡,則其郵箱將丟失。

如果A確實執行spawn_monitor來生成B,並且B立即死亡,則保證A收到DOWN消息。 但是,如果A也死了,那么A的消息隊列中的所有內容都會丟失。

函數on_exit要做的第一件事是生成一個將process_flag trap_exit設置為true的進程,因此該進程被“保護”免於崩潰,並且將接收類型為{'EXIT', Pid, Why}

在下一行中,它嘗試將自身鏈接到Pid; 可能有2種情況:

  • 如果Pid不存在(值錯誤,已經死了……),那么on_exit進程將收到消息{'EXIT', Pid, noproc} ,並調用F(noproc)。
  • 如果Pid存在,則on_exit進程將等待接收,直到該進程Pid由於某種原因死亡。 on_exit將收到{'EXIT', Pid, Reason}並致電F(原因)。

我不明白您為什么談論spawn_monitor,在您的情況下沒有使用它。 無論如何,如果在on_exit函數中用monitor(process,Pid)替換link(Pid),則甚至不需要使用trap_exit,因為如果Pid死了,監視功能也不會崩潰。 在所有情況下,它都返回消息{'DOWN',MonitorReference,process,Pid,Reason} on_exit可以這樣修改:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM