Erlang进程自动被杀死

时间:2015-12-31 12:13:46

标签: erlang

我正在学习erlang,并且正在尝试编写一个简单的客户端 - 服务器程序。

服务器代码如下:

<default>

    <receive channel="channel-1" >
        <command name="AAR">
        </command>
        <action>
            <store name="HbH" entity="HbH-id"></store>
            <store name="E2E" entity="EtE-id"></store>
            <store name="sid" entity="Session-Id"></store>
        </action>
    </receive>
    <send channel="channel-1" >
        <action>
            <restore name="HbH" entity="HbH-id"></restore>
            <restore name="E2E" entity="EtE-id"></restore>
            <restore name="sid" entity="Session-Id"></restore>
        </action>
        <command name="AAA">
            <avp name="Session-Id" value="$(sid)" type="string"></avp>
            <avp name="Result-Code" value="2001" type="number"></avp>
            <avp name="Reply-Message" value="Success" type="string"></avp>

        </command>
    </send>
</default>

<default>

    <receive channel="channel-1" >
        <command name="PUR">
        </command>
        <action>
            <store name="HbH" entity="HbH-id"></store>
            <store name="E2E" entity="EtE-id"></store>
            <store name="sid" entity="Session-Id"></store>
        </action>
    </receive>
    <send channel="channel-1" >
        <action>
            <restore name="HbH" entity="HbH-id"></restore>
            <restore name="E2E" entity="EtE-id"></restore>
            <restore name="sid" entity="Session-Id"></restore>
        </action>
        <command name="PUA">
            <avp name="Session-Id" value="$(sid)" type="string"></avp>
            <avp name="Result-Code" value="2001" type="number"></avp>
            <avp name="Reply-Message" value="Success" type="string"></avp>

        </command>
    </send>
</default>

从另一个erlang脚本

生成服务器如下
-module(frequency_server).
-author("Saurav Prakash").

%% API
-export([init/0]).

init() ->
  Frequencies = [1,2,3,4],
  listen(Frequencies),
  io:format("Server leaving init...~n").

listen(Frequencies) ->
  io:format("Server inside init...~n"),
  receive
    {allocate, Pid} ->
      io:format("Request for allocation from ~w~n", [Pid]),
      if
        length(Frequencies) > 0 ->
          Frequency_Selected = random:uniform(length(Frequencies)),
          io:format("Freq selected is ~w~n", Frequency_Selected),
          Pid ! {ok, Frequency_Selected},
          listen(lists:delete(Frequency_Selected, Frequencies));
        true ->
          io:format("Not available freq...~n"),
          Pid ! {error, "Not Available"}
     end;
   {deallocate, Frequency, Pid} ->
     io:format("deallocation request...~n"),
     listen([Frequency | Frequencies])
  end,
  io:format("Server dying...~n").

但是我发现只要服务器在listen()内部,它就会执行 register(server, spawn(frequency_server, init, [])), io:format("server registered with ~w~n", [whereis(server)]). 并被杀死。

可能是什么问题?

3 个答案:

答案 0 :(得分:1)

由于第20行上的io:format/2调用不正确,进程被终止。io:format/2的参数应该在列表中,所以:

io:format("Freq selected is ~w~n", Frequency_Selected),

应改为:

io:format("Freq selected is ~w~n", [Frequency_Selected]),

但是你也有其他问题,比如代码分配频率的方式。它通过根据可用频率列表的长度选择一个随机数,然后从列表中删除该数字来实现。仅当频率列表是1-N范围N,其中[1]是列表的长度或特殊情况[4]时才有效。但是这段代码允许列表成为random:uniform(length([4])) - 当它具有该值时,由于调用Frequencies,这种方法每次都会选择频率1,即使另一个进程已经分配了频率1,频率4仍然可用。代码应该在考虑分配之前检查所选数字是否在列表中。另一个问题是,取消分配频率不会检查当前是否分配频率,这允许呼叫者重复解除分配相同的频率,从而不止一次将该频率添加回2%列表。 / p>

答案 1 :(得分:1)

我在一个干净的Erlang shell中检查了你的代码并且它没有被杀死并等待传入​​的消息。也许还有一些其他隐藏的活动或环境条件是造成问题的原因。

环境条件:

例如,如果您将server名称注册到另一个进程,则再次执行此操作时会遇到以下异常:

1> register(server, spawn(fun() -> receive _ -> ok end end)).
true
2> register(server, spawn(frequency_server, init, [])),
2> io:format("server registered with ~w~n", [whereis(server)]).
Server inside init...
** exception error: bad argument
     in function  register/2
        called as register(server,<0.36.0>)

隐藏的活动:

例如,某些其他进程可能会向您已注册的server进程发送一个应该检查的终止信号。

答案 2 :(得分:1)

你的过程并没有消亡,它正在等待你告诉它的消息:

Eshell V7.2  (abort with ^G)
1> c(frequency_server).
frequency_server.erl:26: Warning: variable 'Pid' is unused
{ok,frequency_server}
2> {Pid, Ref} = spawn_monitor(frequency_server, init, []).
Server inside init...
{<0.40.0>,#Ref<0.0.2.85>}
3> Pid ! {deallocate, 5, "This part of the message is meaningless data."}.
deallocation request...
{deallocate,5,
            "This part of the message is meaningless data."}
Server inside init...
4>

请参阅?在那里,只是等待消息,以便它可以执行其令人难以置信的奇怪逻辑。

如果您有时间,可能需要阅读以下不同版本:

-module(wonky_serv).

%% API
-export([init/0]).

init() ->
    Frequencies = [1,2,3,4],
    ok = io:format("~tp ~tp: Starting with Frequencies: ~tp~n",
                   [self(), ?MODULE, Frequencies]),
    listen(Frequencies).

listen(Frequencies) ->
    ok = io:format("~tp ~tp: inside listen(~tp)~n", 
                   [self(), ?MODULE, Frequencies]),
    receive
        {allocate, Pid} ->
            {ok, NewFreqs} = allocate(Frequencies, Pid),
            listen(NewFreqs);
        {deallocate, Frequency, Pid} ->
            {ok, NewFreqs} = deallocate(Frequencies, Frequency, Pid),
            listen(NewFreqs);
        {terminate, Pid} ->
            ok = io:format("~tp ~tp: ~tp told me to terminate, so, bye!~n",
                           [self(), ?MODULE, Pid]);
        Unexpected ->
            ok = io:format("~tp ~tp: Unexpected message: ~tp~n", 
                           [self(), ?MODULE, Unexpected]),
            listen(Frequencies)
    end.

allocate([], Pid) ->
    ok = io:format("~tp ~tp: ~tp is requesting allocation, but no freqs available.~n",
                   [self(), ?MODULE, Pid]),
    {ok, []};
allocate([Alloc | Rest], Pid) ->
    ok = io:format("~tp ~tp: Allocating Freq ~tp to ~tp~n",
                   [self(), ?MODULE, Alloc, Pid]),
    {ok, Rest}.

deallocate(Freqs, Dealloc, Pid) ->
    NewFreqs = [Dealloc | Freqs],
    ok = io:format("~tp ~tp: Deallocating ~tp from ~tp~n"
                   "         Available freqs: ~tp~n",
                   [self(), ?MODULE, Dealloc, Pid, NewFreqs]),
    {ok, NewFreqs}.

以下是该版本的用法:

1> {Pid, Ref} = spawn_monitor(wonky_serv, init, []).
<0.35.0> wonky_serv: Starting with Frequencies: [1,2,3,4]
{<0.35.0>,#Ref<0.0.1.44>}
<0.35.0> wonky_serv: inside listen([1,2,3,4])
2> Pid ! {deallocate, 5, self()}.
<0.35.0> wonky_serv: Deallocating 5 from <0.33.0>
         Available freqs: [5,1,2,3,4]
{deallocate,5,<0.33.0>}
<0.35.0> wonky_serv: inside listen([5,1,2,3,4])
3> Pid ! {allocate, self()}.
<0.35.0> wonky_serv: Allocating Freq 5 to <0.33.0>
{allocate,0.33.0>}
<0.35.0> wonky_serv: inside listen([1,2,3,4])
4> Pid ! {terminate, self()}.
<0.35.0> wonky_serv: <0.33.0> told me to terminate, so, bye!
{terminate,<0.33.0>}
5> flush().
Shell got {'DOWN',#Ref<0.0.1.44>,process,<0.35.0>,normal}
ok
6>