二郎。正确的方法来停止进程

时间:2011-11-01 17:39:24

标签: erlang

美好的一天,我为我的小服务设置了以下设置:

-module(mrtask_net).

-export([start/0, stop/0, listen/1]).

-define(SERVER, mrtask_net).

start() ->
    Pid = spawn_link(fun() -> ?MODULE:listen(4488) end),
    register(?SERVER, Pid),
    Pid.

stop() ->
    exit(?SERVER, ok).

....

这是repl摘录:

(emacs@rover)83> mrtask_net:start().
<0.445.0>
(emacs@rover)84> mrtask_net:stop().
** exception error: bad argument
     in function  exit/2
        called as exit(mrtask_net,ok)
     in call from mrtask_net:stop/0
(emacs@rover)85> 

如您所见,停止进程会产生错误,但进程正在停止。 这个错误意味着什么以及如何使事情变得干净?

3 个答案:

答案 0 :(得分:20)

不是Erlang程序员而只是来自exithere)的文档,我会说,exit需要一个进程ID作为第一个参数,而你正在传递一个原子(?SERVER)到它。

尝试

exit(whereis(?SERVER), ok).

而是(whereis返回与名称相关联的进程ID,请参阅here

答案 1 :(得分:4)

您需要将调用更改为exit/2,如@MartinStettner所指出的那样。无论如何,该过程停止的原因是您已使用spawn_link启动它。然后,您的进程将链接到shell进程。当您调用mrtask_net:stop()时,错误导致shell进程崩溃,从而导致进程在链接时崩溃。然后会自动启动一个新的shell进程,以便您可以继续使用shell。您通常希望使用spawn_link启动服务器,但是当您从shell测试它们时它们可能会导致混淆,并且它们只是“发生”死亡。

答案 2 :(得分:2)

我建议你坚持使用OTP。它确实给你带来了很多好处(我几乎无法想象OTP无益的情况)。

所以,如果你想在OTP中停止进程,你应该为gen_server执行类似的操作:

% process1.erl
% In case you get cast message {stopme, Message}
handle_cast({stopme, Message}, State) ->
    % you will stop
    {stop, normal, State}
handle_cast(Msg, State) ->
    % do your stuff here with msg
    {noreply, State}.

% process2.erl
% Here the code to stop process1
gen_server:cast(Pid, {stopme, "It's time to stop!"}),

您可以在此处找到更多相关信息:http://www.erlang.org/doc/man/gen_server.html