Third-party send to active and passive TCP sockets

Jim Larson jim@REDACTED
Sun Oct 24 01:27:42 CEST 1999


I'm running open-source Erlang 47.4.1 on FreeBSD 2.2.8.

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? I've tried to read through
the code for gen_tcp.erl, inet_tcp.erl, and inet_drv.c, but I can't
see where the difference in behavior comes up.

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.

Thanks in advance,

Jim


[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():

Parent:
	{ok, Socket} = gen_tcp:connect(...),
	Child = spawn(...),
	gen_tcp:controlling_process(Socket, Child),
	Child ! go_ahead,		% Signal the child
	gen_tcp:send(Socket, ...)

Child:
	%% Can't recv immediately - must wait for signal from parent.
	receive
		go_ahead -> true	% We're now the controlling process
	end,
	case gen_tcp:recv(Socket, 0) of ...

This might be worth a footnote in the documentation?



More information about the erlang-questions mailing list