[erlang-questions] Good Explanation of gen_tcp:listen ({active, true}) ?

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Thu Dec 25 03:17:16 CET 2014

Hi Stephane,

The process which calls `gen_tcp:accept(LSock)` becomes what is called the
"controlling process" of the socket. It will receive data on the socket as
messages in the form {tcp, Socket, Data}. Strictly speaking the _Socket is
not needed for you to receive active messages like this. But you can't tell
different sockets apart from each other. And worse, since you have no
reference to the socket, you can't close the socket and you can't change
it's properties. The only way to close the socket is by terminating the
(worker) process who is the controller. There are no other ways around
this. And usually, I would call this way of coding rather bad style.

There is no function `supervisor:start_child/0` so your friends code will
not work, but will fail. There has to be something intricate going on here
if the code works. Usually, you arrange it such that the right process is
the one calling accept, so the right process becomes the controller. Or you
give away control by calling the gen_tcp call to change the controlling
process to another. However, when doing so, care must be taken since the
listen socket is active by default, so a race might occur where the wrong
process ends up with a message.

Finally, I would recommend your friend to use {active, once} semantics
instead of {active, true} since it removes the situation where a fast peer
can outrun your Erlang code. Instead, the principles of flow control will
be invoked by TCP once the receiver window fills up, allowing you to handle
data at the pace your system can digest.

On Tue Dec 23 2014 at 9:02:45 PM Stéphane Wirtel <stephane@REDACTED> wrote:

> Hi all,
> In an example from a friend, I see this code.
> For the listener
> ```
> {ok, ListeningSocket} = gen_tcp:listen(2525, [{active, true}])
> ```
> And for each worker, there is part in the code of the supervisor.
> ```
> {ok, _Socket} = gen_tcp:accept(ListeningSocket)
> supervisor.start_child()
> ```
> the code executes a new worker for this client, but I don't understand
> how the child process can handle the new client connection,
> because he does not pass the _Socket variable to supervisor.start_child.
> Do you have a good explanation of this magic thing ?
> Thank you,
> Stephane
> --
> Stéphane Wirtel - http://wirtel.be - @matrixise
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20141225/16a43465/attachment.htm>

More information about the erlang-questions mailing list