Erlang:为什么在取消注册进程ID后我的进程仍在运行?

时间:2014-10-22 16:02:47

标签: erlang server

即使我取消注册sts,我的生成过程也不会停止。如何在不使用gen_server的情况下阻止它?

start() ->
  case whereis(sts) of
    undefined ->
      PidA = spawn(dist_erlang, init,[]),
      register(sts, PidA),
      {ok,PidA};
    _ ->
      {ok,whereis(sts)}
  end.

stop() ->
   case whereis(sts) of
     undefined -> 
        already_stopped;
     _ ->
        unregister(sts),
        stopped,
  end.

2 个答案:

答案 0 :(得分:4)

使用取消注册不会停止该过程。但是,停止该过程会取消注册。因此,不要在此处使用取消注册,而是使用erlang:exit/2

stop() ->
    case whereis(sts) of
        undefined -> 
            already_stopped;
        Pid -> 
            exit(Pid, normal), % Use whatever exit reason you want
            stopped
     end.

所有这一切,您应该真正使用OTP流程行为(如gen_server),因为它们使流程管理变得更加容易。使用OTP流程,您可以改为call进程并告诉它停止,这样当您收到回复时它已经停止。否则,您的退出消息可能需要一些时间才能通过。

答案 1 :(得分:1)

unregister不会停止此过程。它只是删除了进程id和给定原子之间的绑定。

您需要记住stop/0函数是在调用此函数的进程的上下文中运行的,而不是gen_server本身。实际上(几乎)与某个进程交互的唯一方法就是向它发送消息。因此,您可以像这样实现stop/0函数:

%% send stop message to `sts` server
stop() ->
  gen_server:cast(sts, stop). 

%% [...]


handle_cast( OtherCastMessages, State) -> 
  %% handel other cast messages ;
  %% [...] ;

%% handle stop message
handle_cast( _Message = stop, State) ->
  {stop, 
   _Reason = normal, 
   State}. % return result that stops server


%% [...]

terminate(_Reason = normal, State) ->
   %% could do some cleanup in this callback
   ok.

因此,要停止服务器,您必须从其中一个行为函数返回特殊元组。您可以阅读有关此here的更多信息。当然,触发一个行为功能,您必须使用gen_server:castgen_server:call向您的服务器发送消息(或者只发送消息并使用handle_info处理它)。使用什么是你的决定。最后调用terminate2(无论哪个回调返回带有stop atom的元组),您可以在其中对您的州进行一些清理。

当然,您可以在terminate回调中取消注册您的流程,但是当流程终止时,会自动处理取消注册。