[erlang-questions] Re: TCP port sends EXIT message
Per Andersson
avtobiff@REDACTED
Wed Dec 22 12:20:41 CET 2010
Hi!
On Wed, Dec 15, 2010 at 9:00 PM, Matthias Lang <matthias@REDACTED> 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