Erlang.Правильный способ остановить процесс - PullRequest
11 голосов
/ 01 ноября 2011

Добрый день, у меня есть следующие настройки для моей маленькой службы:

-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).

....

А вот выдержка из репла:

(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 ]

20 голосов
/ 01 ноября 2011

Не будучи программистом Erlang и просто из документации exit ( здесь ), я бы сказал, что exit требует идентификатор процесса в качестве первого аргумента, в то время как вы передаете атом ( ?SERVER) к нему.

Попробуйте

exit(whereis(?SERVER), ok).

вместо этого (whereis возвращает идентификатор процесса, связанный с именем, см. здесь )

4 голосов
/ 02 ноября 2011

Вам нужно изменить вызов на exit/2, как указал @MartinStettner. Причина, по которой процесс все равно останавливается, заключается в том, что вы запустили его с spawn_link. Ваш процесс затем связывается с процессом оболочки. Когда вы вызвали mrtask_net:stop(), ошибка вызвала сбой процесса оболочки, который затем вызвал сбой вашего процесса, когда они были связаны. Затем автоматически запускается новый процесс оболочки, чтобы вы могли продолжать работу с оболочкой. Как правило, вы хотите запустить свои серверы с spawn_link, но это может привести к путанице, когда вы тестируете их из оболочки, и они просто «случайно» умирают.

2 голосов
/ 02 ноября 2011

Я бы предложил вам придерживаться 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...