为什么在Erlang中加载热代码后为什么没有任何终端输出?

时间:2018-11-19 12:31:23

标签: erlang

在尝试了解如何使用服务器和热代码加载时,我偶然发现了一个问题,并将其简化为以下代码:

server.erl

-module(server).
-export([start/0, connect/1]).

start() ->
    {ok, Listen} = gen_tcp:listen(8080, [binary, {packet, raw}, {active, true}]),
    spawn(?MODULE, connect, [Listen]).

connect(Listen) ->
    {ok, Socket} = gen_tcp:accept(Listen),
    spawn(?MODULE, connect, [Listen]),
    loop(Socket).

loop(Socket) ->
    receive
        {tcp, Socket, Data} ->
            io:format("1st version received ~p~n", [Data]),
            loop(Socket);
        {tcp_closed, Socket} ->
            io:format("socket closed~n")
    end.

client.erl

-module(client).
-export([request/0]).

request() ->
    {ok, Socket} = gen_tcp:connect("localhost", 8080, [{packet, raw}, binary]),
    gen_tcp:send(Socket, <<"Hello">>).

启动服务器并发送请求会创建预期的输出。

1> server:start().
<0.62.0>
2> client:request().
ok
1st version received <<"Hello">>

在将format语句更改为“第二版”之后,编译并加载代码并执行两个请求(因为在更改之前已生成了当前等待连接的connect / 1进程),结果仍然符合预期。

3> c(server).       
{ok,server}
4> client:request().
ok
1st version received <<"Hello">>
5> client:request().
ok
2nd version received <<"Hello">>

但是,在连续两次编译并加载代码之后,尽管服务器显然仍在运行,但由于gen_tcp:connect返回了一个套接字,因此终端上不再输出任何输出。

6> c(server).
{ok,server}
7> c(server).
{ok,server}
8> client:request().
ok

我怀疑这种行为与erlang杀死具有两个以上版本的代码的所有进程有关,但我无法真正了解此处发生的情况。 由于这是有教育意义的,所以我更想知道为什么这个精确的代码不起作用,而不是实际解决问题的方法。

谢谢

1 个答案:

答案 0 :(得分:1)

我很确定这是两个版本的限制。

如果您要确认这一点,请替换从spawn(...)spawn_link(...)的调用-如果进程终止,则外壳也会崩溃,并且您将知道它们已被杀死。

另一种测试方法是是否可以替换以下内容:

6> c(server).
{ok,server}
7> c(server).
{ok,server}
8> client:request().
ok

通过:

6> c(server).
{ok,server}
7> client:request().
ok
8> c(server).
{ok,server}
9> client:request().
ok

如果效果很好,则不同之处在于中间的消息,该消息允许代码更新为完全合格的函数调用(Module:Fun(Args))的较新代码版本,从而防止崩溃。