erlang进程环中的初始进程不会退出

时间:2013-04-30 05:14:42

标签: erlang

我写了以下代码:

-module(ring).

-export([start/3]).

start(1, 1, Message) -> %special case, no new processes to be launched
    io:format(" Start/3, branch 1~n~n"),
    loop(self(), 1, 1),
    self() ! Message,
    self() ! {self(), quit};
start(1, MsgNum, Message) when MsgNum > 1 -> %first process, register self, launch next, send message, loop
    io:format(" Start/3 branch 2, ProcNum: ~b, MsgNum: ~b, process: ~p~n~n", [1, MsgNum, self()]),
    register(process_1, self()),
    self() ! {self(), Message},
    NextPid = spawn(ring, start, [2, MsgNum, Message]),
    NextPid ! {self(), Message},
    loop(NextPid, 1, MsgNum);
start(MsgNum, MsgNum, _) when MsgNum >= 1 ->    %last process, don't start new process, quit master, run loop
    io:format(" Start/3 branch 3, MsgNum = ProcNum = ~b, process: ~p~n~n", [MsgNum, self()]),
    process_1 ! {self(), quit},
    loop(process_1, MsgNum, MsgNum);
start(ProcNum, MsgNum, Message) when ProcNum >= 1 -> %everything else, start next process, send it a message, start loop
    io:format(" Start/3 branch 4, ProcNum: ~b, MsgNum: ~b, process: ~p~n~n", [ProcNum, MsgNum, self()]),
    NextPid = spawn(ring, start, [ProcNum + 1, MsgNum, Message]),
    NextPid ! {self(), Message},
    loop(NextPid, ProcNum, MsgNum).

loop(NextPid, ProcNum, MsgNum) ->
    receive
        {Sender, quit} -> % send quit to next process in queue, then terminate with 'ok'
        io:format(" Sender: ~p  Quitting process ~p Next: ~p~n~n", [Sender, self(), NextPid]),
        NextPid ! {self(), quit},
        ok; 
    {Sender, Msg} -> % print message and wait for next message
        io:format(" Message: ~w~n  procNum: ~b msgNum: ~b sender: ~p self: ~p  next: ~p~n~n", [Msg, ProcNum, MsgNum, Sender, self(), NextPid]),
        loop(NextPid, ProcNum, MsgNum); 
    _ ->  %flush garbage, should never get here...
        io:format(" Oops. Received someting unexpected")
    end.

我希望这段代码能够启动一系列进程,每个进程都应该打印一条消息,然后礼貌地退出。例如,如果我运行ring:start(1,3,hola),我希望看到三个进程,三个消息和三个退出。它几乎可以工作,除了初始进程没有终止,如在这个shell会话中所见:

Eshell V5.10.1  (abort with ^G)
1> c(ring).
{ok,ring}
2> processes().
[<0.0.0>,<0.3.0>,<0.6.0>,<0.7.0>,<0.9.0>,<0.10.0>,<0.11.0>,
 <0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,<0.16.0>,<0.17.0>,
 <0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,<0.22.0>,<0.23.0>,
 <0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,<0.28.0>,<0.32.0>]
3> ring:start(1,3,hola).
 Start/3 branch 2, ProcNum: 1, MsgNum: 3, process: <0.32.0>

 Message: hola
  procNum: 1 msgNum: 3 sender: <0.32.0> self: <0.32.0>  next: <0.41.0>

 Start/3 branch 4, ProcNum: 2, MsgNum: 3, process: <0.41.0>

 Message: hola
  procNum: 2 msgNum: 3 sender: <0.32.0> self: <0.41.0>  next: <0.42.0>

 Start/3 branch 3, MsgNum = ProcNum = 3, process: <0.42.0>

 Message: hola
  procNum: 3 msgNum: 3 sender: <0.41.0> self: <0.42.0>  next: process_1

 Sender: <0.42.0>  Quitting process <0.32.0> Next: <0.41.0>

 Sender: <0.32.0>  Quitting process <0.41.0> Next: <0.42.0>

 Sender: <0.41.0>  Quitting process <0.42.0> Next: process_1

ok
4> processes().
[<0.0.0>,<0.3.0>,<0.6.0>,<0.7.0>,<0.9.0>,<0.10.0>,<0.11.0>,
 <0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,<0.16.0>,<0.17.0>,
 <0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,<0.22.0>,<0.23.0>,
 <0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,<0.28.0>,<0.32.0>]

我为长代码/日志块道歉,但我认为这很清楚start / 3导致启动三个进程(&lt; 0.32.0&gt;,&lt; 0.41.0&gt;,&lt; 0.42 .0&gt;),并且每个打印一条消息,并且每个消息都接收它的退出消息。然而,当完成所有操作时,初始过程(&lt; 0.32.0&gt;)仍在运行。我的理解是,一旦没有更多的代码要运行,进程就应该终止 - 第一个进程是否存在阻止其终止的特殊内容?

提前致谢。

1 个答案:

答案 0 :(得分:4)

您的函数start / 3不会启动您调用'initial'的过程。相反,该函数在已存在的进程中运行。这是erlang shell的过程,你正在使用它。它的pid <0.32.0&gt;。仔细查看函数processes()的第一次调用的输出:

2> processes().
[<0.0.0>,<0.3.0>,<0.6.0>,<0.7.0>,<0.9.0>,<0.10.0>,<0.11.0>,
 <0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>,<0.16.0>,<0.17.0>,
 <0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>,<0.22.0>,<0.23.0>,
 <0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>,<0.28.0>,<0.32.0>]

列表中的最后一个pid是&lt; 0.32.0&gt;。因此,当您调用start / 3时,它将在该过程中运行,当它从循环退出时,过程&lt; 0.32.0&gt;将不会完成 - 它将只返回到erlang shell并等待下一个命令。