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:
erl -noshell -s tt_sup start_shell
How could I run my simple gen_tcp:connect (gen_server) with supervisor ?
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}}.
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.
The process that runs the -s
exits with normal
when it has no more code to execute. The supervisor receives that signal and since it's from its parent, it exits (regardless of it being normal
), as explained in gen_server:terminate/2 (supervisor
s are gen_server
s with trap_exit
active):
Even if the gen_server process is not part of a supervision tree, this function is called if it receives an 'EXIT' message from its parent. Reason is the same as in the 'EXIT' message.
I haven't tested your code, but if you add a process_flag(trap_exit, true)
to your gen_server
, you'll surely replicate this behaviour.