gen_tcp:connect will close when using supervisor.
Karl Velicka
karolis.velicka@REDACTED
Fri Nov 20 10:01:39 CET 2020
Hi,
I ran your program with a small difference and found some threads to pull
on. I added process_flag(trap_exit, true), to ttest:init. Running `erl
-noshell -s ttest start` now gives different output, and the other side of
the socket gets closed:
gen_server start id is <0.9.0>
connect id is <0.78.0>
init id is <0.78.0>
gen_server id is <0.78.0>
=ERROR REPORT==== 20-Nov-2020::08:46:30.930438 ===
** Generic server ttest terminating
** Last message in was {'EXIT',<0.9.0>,normal}
** When Server state == []
** Reason for termination ==
** {function_clause,[{ttest,terminate,
[normal,[]],
[{file,"ttest.erl"},{line,29}]},
{gen_server,try_terminate,3,
[{file,"gen_server.erl"},{line,718}]},
{gen_server,terminate,10,
[{file,"gen_server.erl"},{line,903}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,226}]}]}
=CRASH REPORT==== 20-Nov-2020::08:46:30.954039 ===
crasher:
initial call: ttest:init/1
pid: <0.78.0>
registered_name: ttest
exception error: no function clause matching ttest:terminate(normal,[])
(ttest.erl, line 29)
in function gen_server:try_terminate/3 (gen_server.erl, line 718)
in call from gen_server:terminate/10 (gen_server.erl, line 903)
ancestors: [<0.9.0>]
message_queue_len: 0
messages: []
links: [#Port<0.6>]
dictionary: []
trap_exit: true
status: running
heap_size: 4185
stack_size: 28
reductions: 6011
neighbours:
The reason why this particular error gets printed is somewhat accidental,
but the key bit is "** Last message in was {'EXIT',<0.9.0>,normal}" - this
suggests that the process that was starting your gen_server (<0.9.0>) has
itself exited with the reason `normal`, presumably right after running the
function specified by the `-s` flag.
There's two key things to note here:
* a supervisor itself is implemented as a gen_server that traps exits. That
is, it will notice any exit signal sent to it (barring `kill` perhaps?),
and react to it
* normally (i.e. in absence of trap_exit), when two processes are linked an
one of them exits with the reason `normal`, the other one does _not_exit
The result of this is that the supervisor you're starting notices <0.9.0>
exiting and exits itself, whereas your gen_server does not. This also
explains why starting the supervisor and unlinking it also seemingly fixes
the problem - in that case the exit signal of <0.9.0> never reaches the
supervisor as there's no link by the time it exits (which seems to be right
after tt_sup:start_link/start_shell returns).
The solution I'd suggest is making a rudimentary application (
https://erlang.org/doc/design_principles/applications.html) containing your
module and supervisor, or simply continue with the `unlink` solution if
you're just messing around with some non-serious code.
Hope that helps!
Karl
On Wed, 18 Nov 2020 at 23:27, George Hope <george@REDACTED> wrote:
> I have a simple gen_server which connects to a tcp port, when I run
> gen_server directly:
> erl -noshell -s ttest start
> it works fine, But when I run:
> erl -noshell -s tt_sup start_link
> the connection will be closed instantly, it will work if I unlink the
> supervisor.
> How could I run my simple gen_server with supervisor ?
>
>
> -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}}.
>
>
> -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.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20201120/6f982404/attachment.htm>
More information about the erlang-questions
mailing list