[erlang-questions] Can gen_tcp:close() close a socket which is still sending?

3 views
Skip to first unread message

John Haugeland

unread,
Jun 13, 2009, 9:08:45 PM6/13/09
to Erlang Users' List
I have a defect that I don't fully understand. When I dispatch
something by gen_tcp:send(...), I follow through with :close().
However, there's a sporadic pattern of the data getting cut off early.
If I inject a delay between them, the problem disappears.

This seems to imply that :close() can close a socket which is still
sending data. That isn't what I would have expected by comparison
from other languages, so I'm not entirely convinced I've understood
this correctly.

Is it safe to call :close() immediately after a large :send()? If
not, what does one do instead?

________________________________________________________________
erlang-questions mailing list. See http://www.erlang.org/faq.html
erlang-questions (at) erlang.org

Tony Rogvall

unread,
Jun 14, 2009, 6:03:52 AM6/14/09
to John Haugeland, Erlang Users' List
There are two buffers between you and the wire. First there is the
Socket/Port buffer and
then there is the operating system socket buffer.

When you send data from Erlang the data that could not be transmitted
directly is
queued for delivery when more kernel buffer space is available.

After you issue a gen_tcp:close then if the server side is really slow
and do not process any data for
more than 5 seconds then the socket is closed any way.
My guess is that you send some buffer that is queued in the operating
system buffer and then
you call close. What happens then is up to the tcp implementation. Are
you using Windows ?

The "safe" way to terminate a sending socket is to use shutdown(S,
write) and then wait
for the server side to close the connection.
The shutdown interface will also wait until all data queued in the
Port/socket is written to the
operating system socket before issuing the low level shutdown.

Hope this will lead you forward.

/Tony

John Haugeland

unread,
Jun 14, 2009, 1:31:05 PM6/14/09
to Tony Rogvall, Erlang Users' List
> After you issue a gen_tcp:close then if the server side is really slow and
> do not process any data for more than 5 seconds then the socket is closed any way.

It's lightning fast by design. Having Erlang's excellent mature
timeslicer to work with has made it borderline trivial to make a
webserver that's fast enough to send Marty McFly back in time.

You heard me: my webserver goes 88 miles an hour.

> My guess is that you send some buffer that is queued in the operating system
> buffer and then you call close.

Well right now I'm just testing over localhost. Same machine for
server and client.

> What happens then is up to the tcp implementation. Are you
> using Windows ?

This happens both under Vista Home Premium 64 and Gentoo 64.

> The "safe" way to terminate a sending socket is to use shutdown(S, write)
> and then wait for the server side to close the connection.

This here may be exactly what I need to know. To check, first,
though: in context, erlang _is_ the server side. Does that change
things? The client is any web browser. I apologize for having been
unclear.

> The shutdown interface will also wait until all data queued in the
> Port/socket is written to the
> operating system socket before issuing the low level shutdown.

See, that's what I would have expected. Windows doesn't close sockets
with outbound data on them, when you're writing C/C++. That right
there is a big part of why I'm worried I haven't yet correctly
diagnosed the problem.

> Hope this will lead you forward.

I suspect it has, but my being unclear about Erlang's role as a server
suggests I need to make sure I didn't actually present a wrong
situation for advice first.

Tony Rogvall

unread,
Jun 14, 2009, 6:48:29 PM6/14/09
to John Haugeland, Erlang Users' List
>
>> The "safe" way to terminate a sending socket is to use shutdown(S,
>> write)
>> and then wait for the server side to close the connection.
>
> This here may be exactly what I need to know. To check, first,
> though: in context, erlang _is_ the server side. Does that change
> things? The client is any web browser. I apologize for having been
> unclear.
>
>

Then perhaps you should check the exit_on_close option in the inet
module.
If the client uses shutdown you will be able to write data to the
client and
then close after this is done.

/Tony

John Haugeland

unread,
Jun 14, 2009, 10:26:28 PM6/14/09
to Tony Rogvall, Erlang Users' List
The client will not shut down.

The issue is that, conceptually, what needs to happen is the server
should provide a response then drop as soon as its response is
completely dispatched. Erlang is not waiting for the other side to
close. Erlang is completely in control here. The desired behavior is
solely guided by when that gen_tcp:send(...) is complete.

It's a webserver. The client doesn't close the connection.

________________________________________________________________

Tony Rogvall

unread,
Jun 15, 2009, 3:52:27 AM6/15/09
to John Haugeland, Erlang Users' List
So what happens if you use shutdown write?
Use ethereal or tcpdump to get a trace!

/Tony

Reply all
Reply to author
Forward
0 new messages