2011-11-01 13 views
10

Dzień dobry, mam następujące ustawienia dla mojego małego usługi:Erlang. Poprawny sposób, aby zatrzymać proces

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

.... 

A oto fragmencie repl:

([email protected])83> mrtask_net:start(). 
<0.445.0> 
([email protected])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 
([email protected])85> 

Jak widać, proces zatrzymywania wywołuje błędu, proces zatrzymuje się jednak. Co oznacza ten błąd i jak czynić rzecz czystą?

Odpowiedz

20

Nie będąc programistą Erlang i właśnie z dokumentacji exit (here), powiedziałbym, że exit wymaga identyfikatora proces jako pierwszy argument, podczas gdy jesteś przejazdem atomu (?SERVER) do niego.

Spróbuj

exit(whereis(?SERVER), ok). 

zamiast (whereis zwraca identyfikator procesu związanego z nazwy, patrz here)

+6

+1 Będąc w stanie odczytać dokumentację można być tak samo cenne, jak znajomość języka na wylot. – BRampersad

4

Musisz zmienić wywołanie exit/2 jak @MartinStettner podkreślił. Powód, dla którego proces się kończy, polega na tym, że został on uruchomiony pod numerem spawn_link. Twój proces jest następnie połączony z procesem powłoki. Kiedy zadzwoniłeś pod numer mrtask_net:stop(), błąd spowodował awarię powłoki, która spowodowała awarię twojego procesu, gdy były połączone. Nowy proces powłoki jest wtedy automatycznie uruchamiany, dzięki czemu możesz dalej pracować z powłoką. Zazwyczaj chcesz uruchamiać serwery za pomocą spawn_link, ale może to powodować zamieszanie, gdy testujesz je z powłoki i po prostu "zdarza się", że umrze.

2

Proponuję, abyś trzymał się OTP. To naprawdę daje mnóstwo korzyści (prawie nie mogę wyobrazić sobie przypadku, w którym OTP nie odnosi korzyści).

Tak więc, jeśli chcesz, aby zatrzymać proces w OTP należy zrobić coś takiego dla 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!"}), 

więcej na ten temat można znaleźć tutaj: http://www.erlang.org/doc/man/gen_server.html

Powiązane problemy