cURL / Mailing Lists / curl-library / Single Mail

curl-library

async socket help

From: john skaller <skaller_at_users.sourceforge.net>
Date: Mon, 1 Nov 2010 04:05:27 +1100

Hi, I am wondering if any devs here would be willing
to help me figure out how to properly close an O_NONBLOCK socket.
I had a browse of libcurl, but couldn't find exactly what was done.
Forgive me, I'm not actually using libcurl (I use curl though!),
I have actually written a webserver which isn't functioning correctly.

The problem appears to be a design fault in Posix which implies
an efficient and safe webserver actually cannot be written :)

What happens: after writing the last data, shutdown() and/or
close() is called, which immediately flushes away all the stuff
just written to the socket buffers. This is either "allowed" or
"required" by Posix, depending on which bit you read.
Linux appears to do this.

My workaround for the moment is to put a delay before
the shutdown/close, but that fails the "efficient" requirement
because it unnecessarily leaves a socket handing around
for which the data may have been sent. [On my slicehost
account I had to set the delay to about 20 seconds]

SO_LINGER was somehow meant to solve this problem, but it only
works on blocking sockets.

On OSX there is a hacky but acceptable solution using SO_NWRITE
but that isn't standard and not implemented on Linux. It allows
discovering how much unwritten data there is in the buffer and
therefore in conjunction with a polling loop allows closing on
a timeout or when all the data is written or error occurs,
whichever comes first.

Switching to a blocking socket may work. According to OpenGroup,
closing a blocking socket should actually return immediately
but still try to write the buffers out, unless SO_LINGER is active
in which case it blocks.

Unfortunately, the specification is ambiguous *and* contradictory.

Says this:

 If fildes refers to a socket, close() shall cause the socket to be destroyed. If the socket is in connection-mode, and the SO_LINGER option is set for the socket with non-zero linger time, and the socket has untransmitted data, then close() shall block for up to the current linger interval until all data is transmitted.

That doesn't actually happen on Linux (when the socket is O_NONBLOCK)
AFICT anyhow :)

I've been pulling my hair out on this for 3 years or so..

How does curl close sending sockets? [I know curl uses non-blocking I/O]

--
john skaller
skaller_at_users.sourceforge.net
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html
Received on 2010-10-31