Third-party send to active and passive TCP sockets

Per Hedeland <>
Tue Oct 26 14:18:29 CEST 1999


Jim Larson <> wrote:
>I've noticed some interesting behavior regarding which processes
>can use the gen_tcp:send() call to send data over a TCP socket.
>
>A single process P can open the socket, send data with gen_tcp:send(),
>and receive the reply in either active or passive mode.
>
>A process P can open the socket and spawn a child C1, and make C1
>the controlling process of the socket with gen_tcp:controlling_process().
>P can then call gen_tcp:send() to send data, and C1 can receive
>the reply[1] in either active or passive mode.
>
>However, if P forks off a second child C2 which is dedicated to
>sending data with gen_tcp:send(), this works in active mode but
>doesn't in passive mode - C2's call to gen_tcp:send() never returns.
>
>Is this behavior deliberate and correct?

At least partly, I think:-) - i.e. my understanding is that you're not
supposed to be able to what you want to do, but you're not supposed to
be able to do some of the things you actually manage to do, either.:-)
I believe the problem is that these lines from the gen_udp(3) man page:

     If any of the following functions are called with  a  Socket
     that was not opened by the calling process, they will return
     {error,  not_owner}.  The  ownership  of  a  Socket  can  be
     transferred to another process with controlling_process/2.

- or words to that effect:-) - should also be in the corresponding place
in the gen_tcp(3) man page, but aren't. I.e. only the controlling
process can (or at least is allowed to:-) send/recv on the socket, which
unfortunately precludes having separate reader and writer processes.

I.e. the bug(s) you're seeing (apart from the documentation) would be
that your process P can use send after giving away the control, and that
C2 hangs rather than getting an error.

>For what it's worth, I'm trying to implement a gen_server module
>that implements the client-side logic of a popular RPC package,
>using TCP as a transport protocol.  The data rates may be intense,
>so to avoid running the socket open-loop, I'm trying to have
>dedicated input and output processes to read from and write to
>(respectively) the passive socket.  The parent process "P" above
>is the server process, and should never block, thus shouldn't do
>I/O with a passive socket directly.

Hmm, if the input process is just going to turn around and do a
'Server ! Packet' when the recv() returns, I think you might just as
well (or better) use active mode with the server as controlling process
- the input process is effectively an "activifier" anyway then.

>[1]: You have to do an interesting little dance when you do this,
>since the child can't call gen_tcp:recv() until it is the controlling
>process, and it can't be made the controlling process until the
>parent has spawned it to get the Pid and called
>gen_tcp:controlling_process():

Well, yes, but having to synchronize with the spawned child for some
reason or another isn't all that uncommon...

--Per Hedeland




More information about the erlang-questions mailing list