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

Reply via email to