gen_tcp:connect 将在使用 supervisor 时关闭

Posted

技术标签:

【中文标题】gen_tcp:connect 将在使用 supervisor 时关闭【英文标题】:gen_tcp:connect will close when using supervisor 【发布时间】:2021-03-02 13:29:36 【问题描述】:

当我直接运行 gen_server 时,我有一个连接到 tcp 端口的简单 gen_server:

erl -noshell -s ttest start

它工作正常,但是当我运行时:

erl -noshell -s tt_sup start_link

连接将立即关闭,如果我取消与主管的链接,它将起作用:

erl -noshell -s tt_sup start_shell

如何使用主管运行我的简单 gen_tcp:connect (gen_server)?

主管:

-module(tt_sup).
-behaviour(supervisor).
-export([init/1, start_link/0, start_shell/0]).

start_link() ->
    io:format("Supervisor started with PID~p~n", [self()]),
    ok, Pid = supervisor:start_link(tt_sup, []),
    io:format("Supervisor PID=~p~n", [Pid]),
    ok, Pid.

start_shell() ->
    io:format("Supervisor started with PID~p~n", [self()]),
    ok, Pid = supervisor:start_link(tt_sup, []),
    io:format("Supervisor PID=~p~n", [Pid]),
    unlink(Pid),
    ok, Pid.

init(_Args) ->
    SupFlags = #strategy => one_for_one,
    Child = [#id => ttest, start => ttest, start, [],
               restart => permanent, shutdown => brutal_kill,
               type => worker, modules => [ttest]],
    ok, SupFlags, Child.

gen_server:

-module(ttest).
-export([start/0,init/1,handle_cast/2,handle_call/3,handle_info/2,terminate/2,connect/1]).
-behaviour(gen_server).



start() ->

       io:format("gen_server start id is ~p~n",[self()]),
       ok,Pid = gen_server:start_link(local,ttest,ttest,[],[]),
       io:format("gen_server id is ~p~n",[Pid]),
       connect(Pid),
       ok,Pid.



init(_Args) ->
        io:format("init id is ~p~n",[self()]),
        ok,[].       
handle_call(tcp,Socket,Bin,_From,States) ->
        reply,States,States.
handle_info(tcp,Socket,Bin,States) ->
        io:format("got info msg"),
        noreply,States.

handle_cast(send,Msg,States) ->
        reply,States.

connect(I) ->
    io:format("connect id is ~p~n",[self()]),
    ok,Socket =gen_tcp:connect("localhost",6000,[binary,active,true]),
    gen_tcp:controlling_process(Socket,I).



terminate(shutdown, State) ->
    io:format("terminating"),
    ok.

【问题讨论】:

【参考方案1】:

运行-s 的进程在没有更多代码要执行时以normal 退出。主管接收到该信号,由于它来自其父级,因此它退出(不管它是 normal),如 gen_server:terminate/2 中所述(supervisors 是 gen_servers 和 trap_exit 活动):

即使 gen_server 进程不是监督树的一部分,如果它从其父进程接收到“退出”消息,也会调用此函数。原因与“退出”消息中的相同。

我没有测试过你的代码,但是如果你在你的gen_server 中添加一个process_flag(trap_exit, true),你肯定会复制这种行为。

【讨论】:

是的,如果我将process_flag(trap_exit, true)添加到gen_server init,也会一样,我应该如何启动supervisor? @Geo-7 如果你想创建一个具有适当 OTP 监督树的生产级项目,你应该使用它创建一个应用程序和一个发布,检查 learnyousomeerlang.com/… 和 learnyousomeerlang.com/release-is-the-word (learnyousomeerlang是极好的参考)。如果你想让它尽快运行,只需在tt_sup:start_link 返回之前添加一个timer:sleep(infinity)

以上是关于gen_tcp:connect 将在使用 supervisor 时关闭的主要内容,如果未能解决你的问题,请参考以下文章

在 Elixir 中设置 gen_tcp 的参数

erlang/elixir gen_tcp connect - 不连接但telnet wil

SUPEE 6788 和密码重置(空白页)

sh Magento SUPEE-9767 Checkout表格主题补丁

Magento模板发行管理面板中SUPEE补丁

Android java.lang.NoSuchFieldError: No static field xxx of type I in class Lcom/XX/R$id; or its supe