[erlang-questions] Re: TCP port sends EXIT message

Per Andersson <>
Wed Dec 22 12:20:41 CET 2010


Hi!

On Wed, Dec 15, 2010 at 9:00 PM, Matthias Lang <> wrote:
> On Wednesday, December 15, Per Andersson wrote:
>
>> I realized that this happened because the acceptor is shutdown after it
>> calls controlling_process. I, erroneously, thought that controlling_process
>> would actually transfer all control and ownership of the socket to a new
>> process. This does not seem to be the case, the docs state only that the
>> new owner will receive messages.
>
> gen_tcp:controlling_process() transfers both "control" (who receives
> messages) and "ownership" (which process is linked to the port).
>
> I took a guess at what you were trying to do and wrote a minimal,
> self-contained example that compiles. The socket does not die
> when the process which originally owned it died:

If I use a similar protocol that you wrote in your example it works
like a charm.
I.e. link the processes and put the FSM in a WAIT_FOR_KILL state and then
send a kill message when the socket is passed to the new process.

I tried just adding a short sleep but the FSM still killed the socket when
it died. Why?


Best,
Per

> -module(per_a).
> -export([go/0]).
>
> go() ->
>  erlang:process_flag(trap_exit, true),
>  {ok, L} = gen_tcp:listen(5555, [{active, false}, {reuseaddr, true}]),
>  spawn(fun connect/0),
>  Self = self(),
>  Acceptor_pid = spawn_link(fun() -> acceptor(L, Self) end),
>  receive
>    {Acceptor_pid, Socket} ->
>       exit(Acceptor_pid, kill),
>       receive
>         {'EXIT', Acceptor_pid, _} -> ok
>       end,
>       io:fwrite("This process is ~p\n", [self()]),
>       io:fwrite("The acceptor pid, ~p is now dead (process_info=~p)\n",
>         [Acceptor_pid, erlang:process_info(Acceptor_pid)]),
>       io:fwrite("The socket is still alive (port_info=~p)\n",
>         [erlang:port_info(Socket)]),
>       {ok, Data} = gen_tcp:recv(Socket, 0),
>       io:fwrite("Here's some freshly received socket data: ~p\n", [Data]),
>       gen_tcp:close(Socket),
>       gen_tcp:close(L)
>   end.
>
> connect() ->
>  {ok, S} = gen_tcp:connect(localhost, 5555, []),
>  ok = gen_tcp:send(S, "hello world\n"),
>  Ref = make_ref(), receive Ref -> done end. % hang forever
>
> acceptor(L, Parent) ->
>  {ok, S} = gen_tcp:accept(L),
>  ok = gen_tcp:controlling_process(S, Parent),
>  Parent ! {self(), S},
>  Ref = make_ref(), receive Ref -> done end. % hang forever
>
> --------------------
> Here's the output:
>
>  | 2> per_a:go().
>  | This process is <0.31.0>
>  | The acceptor pid, <0.39.0> is now dead (process_info=undefined)
>  | The socket is still alive (port_info=[{name,"tcp_inet"},
>  |                                       {links,[<0.31.0>]},
>  |                                       {id,2046},
>  |                                       {connected,<0.31.0>},
>  |                                       {input,0},
>  |                                       {output,0}])
>  | Here's some freshly received socket data: "hello world\n"
>  |
>
> The question now is: what are you doing differently?  Can you post a
> minimal, self-contained example which compiles, runs and demonstrates
> the socket dying unexpectedly?
>
> Matt
>


More information about the erlang-questions mailing list