Hi there.
In function Curl_is_connected a connection error like
code 111 "Connection refused" will be overwritten with
code 115 "Operation now in progress".
e.g.
* About to connect() to nonitor.de port 22 (#0)
* Trying 212.1.39.66... * Connection refused
* Failed connect to nonitor.de:22; Operation now in progress
* Expire cleared
* Closing connection #0
In line 687 the correct error is grab by verifyconnect(sockfd, &error)
and the next line stores the error in data struct.
This will be overwritten at line 697 with SOCKERRNO. This is only
usefull if trynextip(..) has done s.t. on a new socket. If the
there was no next address, then the previously detected error should
not be overwritten, because SOCKERRNO will return the (outdated)
errno set by the non-blocking connect.
The simplest fix would be to call SET_SOCKERRNO(errro) after line 687:
659 /* check for connect without timeout as we want to return immediately */
660 rc = waitconnect(conn, sockfd, 0);
661
662 if(WAITCONN_CONNECTED == rc) {
663 int error;
664 if(verifyconnect(sockfd, &error)) {
665 /* we are connected, awesome! */
666 conn->bits.tcpconnect = TRUE;
667 *connected = TRUE;
668 Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
669 Curl_verboseconnect(conn);
670 Curl_updateconninfo(conn, sockfd);
671
672 return CURLE_OK;
673 }
674 /* nope, not connected for real */
675 data->state.os_errno = error;
676 infof(data, "Connection failed\n");
677 code = trynextip(conn, sockindex, connected);
678 if(code)
679 failf(data, "Failed connect to %s:%ld; %s",
680 conn->host.name, conn->port, Curl_strerror(conn, error));
681 }
682 else if(WAITCONN_TIMEOUT != rc) {
683 int error = 0;
684
685 /* nope, not connected */
686 if(WAITCONN_FDSET_ERROR == rc) {
687 (void)verifyconnect(sockfd, &error);
688 data->state.os_errno = error;
+++ SET_SOCKERRNO(error);
689 infof(data, "%s\n",Curl_strerror(conn,error));
690 }
691 else
692 infof(data, "Connection failed\n");
693
694 code = trynextip(conn, sockindex, connected);
695
696 if(code) {
697 error = SOCKERRNO;
698 data->state.os_errno = error;
699 failf(data, "Failed connect to %s:%ld; %s",
700 conn->host.name, conn->port, Curl_strerror(conn, error));
701 }
702 }
703 /*
704 * If the connection failed here, we should attempt to connect to the
"next
705 * address" for the given host.
706 */
707
708 return code;
709 }
While hacking the bug I've noticed that line 677-680 and 694-701 are same
with a small difference: In the first block the error overwritting is missing.
And the comment in line 703-706 is weird, because trynextip is already
called (unless WAITCONN_TIMEOUT).
To clean this up, I've written a patch. I hope, it breaks nothing...
Greetings,
Dirk Manske
diff --git a/lib/connect.c b/lib/connect.c
index 0495887..8a48637 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -658,9 +658,13 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* check for connect without timeout as we want to return immediately */
rc = waitconnect(conn, sockfd, 0);
+ if(WAITCONN_TIMEOUT == rc) {
+ /* not an error, but also no connection yet */
+ return code;
+ }
+ int error = 0;
if(WAITCONN_CONNECTED == rc) {
- int error;
if(verifyconnect(sockfd, &error)) {
/* we are connected, awesome! */
conn->bits.tcpconnect = TRUE;
@@ -672,38 +676,34 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return CURLE_OK;
}
/* nope, not connected for real */
- data->state.os_errno = error;
- infof(data, "Connection failed\n");
- code = trynextip(conn, sockindex, connected);
- if(code)
- failf(data, "Failed connect to %s:%ld; %s",
- conn->host.name, conn->port, Curl_strerror(conn, error));
}
- else if(WAITCONN_TIMEOUT != rc) {
- int error = 0;
-
+ else {
/* nope, not connected */
if(WAITCONN_FDSET_ERROR == rc) {
(void)verifyconnect(sockfd, &error);
- data->state.os_errno = error;
infof(data, "%s\n",Curl_strerror(conn,error));
}
else
infof(data, "Connection failed\n");
-
- code = trynextip(conn, sockindex, connected);
-
- if(code) {
- error = SOCKERRNO;
- data->state.os_errno = error;
- failf(data, "Failed connect to %s:%ld; %s",
- conn->host.name, conn->port, Curl_strerror(conn, error));
- }
}
+
/*
- * If the connection failed here, we should attempt to connect to the "next
- * address" for the given host.
+ * The connection failed here, we should attempt to connect to the "next
+ * address" for the given host. But first remember the latest error.
*/
+ if(error) {
+ data->state.os_errno = error;
+ SET_SOCKERRNO(error);
+ }
+
+ code = trynextip(conn, sockindex, connected);
+
+ if(code) {
+ error = SOCKERRNO;
+ data->state.os_errno = error;
+ failf(data, "Failed connect to %s:%ld; %s",
+ conn->host.name, conn->port, Curl_strerror(conn, error));
+ }
return code;
}
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html