cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: Connection killed right after connect, Expire Cleared / Curl Error 56

From: Daniel Stenberg <daniel_at_haxx.se>
Date: Fri, 8 Oct 2010 22:37:31 +0200 (CEST)

On Fri, 8 Oct 2010, m0n0 wrote:

> 1. The TCP connection is established in non-blocking mode.
> 2. Curl_socket_ready returns success.
> 3. Curl enters some recv functions which says: "nono, the socket is not
> connected" - so Curl_socket_ready failed to verify that the connection is
> established.
> I'm not saying that it's an "bug" within Curl_socket_ready, but it returns
> success...

For non-blocking connections, the POSIX rule is that when that socket turns
writable, the connection is complete. That's just how things work and we have
to abide to those rules.

> 4. I assume that curl verifies the connection by checking if sending data to
> the socket would block.

Not exactly. After doing a non-blocking connect and the socket turned
writable, the lib/connect.c:verifyconnect() function is called and that will
query the TCP/IP stack by asking for the SO_ERROR variable from the SOL_SOCKET
using getsockopt() just to make sure there was no error signalled.

This too is necessary for the connection to be verified as connected after
having turned writable.

As you can see in that function, we have some precautions for platform-
specific behaviors too.

> If that's true, that means cURL assumes that also recv can be entered,
> altough it just checked if sending would block.

The socket turned writable and the getsockopt() check are the only checks done
and those are enough proof that the connection phase is completed.

Before that, recv() will not be called since the connection isn't completed
yet and it wouldn't make sense. But OTOH, doing recv() on the non-blocking
non-connected socket wouldn't return anything either.

> Here is an part of waitconnect() from select.c:
> /* now select() until we get connect or timeout */
> rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)(timeout_msec>1000?
> 1000:timeout_msec));
>
> To me it seem like Curl_socket_ready is just checking if data can be send.

That's correct.

> I assume that the FreeMiNT kernel says: "Ok to send data", but when you try
> to recv data, it fails, because connection setup isn't finished.

Then the FreeMiNT kernel is not POSIX compliant and wrong. Which of course
seems a bit unexpected as well given your previous explanations.

It MUST mark the socket as writable when the TCP connection is complete and it
can't set it writable before it is so. At least not without also signalling an
error as described above.

> Which is perfectly fine with non-blocking sockets.

No, it's most certainly not.

> I'm not quite sure, but I wouldn't describe this behavior as an bug.

If that is truly what happens, then I claim it is a socket API bug.

> What do you say about that? Wouldn't you say that it is an assumption by
> curl? Why does it enter the recv function, yes - send wouldn't block, but
> does this mean it's OK to call recv? :)

Well, first it doesn't "enter recv()" immediately just because the socket
turned writable. If you're talking HTTP, libcurl first sent a big request to
the socket (since it said the connection was complete) and _then_ it starts to
recv() from the socket as soon as the socket claims to be readable.

I must remind you that curl and libcurl run on MANY operating systems without
any major problems so such a basic flaw seems unlikely in my eyes. I don't
rule out the ability of a curl bug, but I think it is more subtle than that if
this truly is one.

-- 
  / daniel.haxx.se
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html
Received on 2010-10-08