On 19/06/14 17:20, Daniel Stenberg wrote:
Yes, that's an unfortunate side-effect of the modified connection
cache in 7.30.0 I believe. It has been discussed before but nobody has
stepped up to do the necessary work.
I devised a patch that would reintroduce the cleanup before other
connections are established. But if you are wary about the performance
this should perhaps be configurable by a easy_setopt() directive. What
do you think?
cheers, Frank
diff --git a/lib/url.c b/lib/url.c
index 770b0cc..8e85d68 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2910,6 +2910,65 @@ find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
}
/*
+ * This function checks if given connection is dead and removes it from the
+ * connection cache if this is the case.
+ *
+ * Returns TRUE if the connection was dead and removed
+ */
+static bool RemoveConnectionIfDead(struct connectdata *check,
+ struct SessionHandle *data) {
+
+ size_t pipeLen = check->send_pipe->size + check->recv_pipe->size;
+ if (!pipeLen && !check->inuse) {
+ /* The check for a dead socket makes sense only if there are no
+ handles in pipeline and the connection isn't already marked in
+ use */
+ bool dead;
+ if (check->handler->protocol & CURLPROTO_RTSP)
+ /* RTSP is a special case due to RTP interleaving */
+ dead = Curl_rtsp_connisdead(check);
+ else
+ dead = SocketIsDead(check->sock[FIRSTSOCKET]);
+
+ if (dead) {
+ check->data = data;
+ infof(data, "Connection %ld seems to be dead!\n", check->connection_id);
+
+ /* disconnect resources */
+ Curl_disconnect(check, /* dead_connection */TRUE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/*
+ * Wrapper to use RemoveConnectionIfDead() function in Curl_conncache_foreach()
+ *
+ * Returns always 0.
+ */
+static int RemoveConnectionIfDeadWrapper(struct connectdata *check,
+ void *param) {
+
+ struct SessionHandle* data = (struct SessionHandle*)param;
+
+ RemoveConnectionIfDead(check, data);
+
+ return 0; /* continue iteration */
+}
+
+
+/*
+ * This function scans the connection cache for half-open/dead connections,
+ * closes and removes them.
+ */
+static void CleanupDeadConnections(struct SessionHandle *data) {
+
+ Curl_conncache_foreach(data->state.conn_cache, data, RemoveConnectionIfDeadWrapper);
+}
+
+/*
* Given one filled in connection struct (named needle), this function should
* detect if there already is one that has all the significant details
* exactly the same and thus should be used instead.
@@ -2973,29 +3032,10 @@ ConnectionExists(struct SessionHandle *data,
check = curr->ptr;
curr = curr->next;
- pipeLen = check->send_pipe->size + check->recv_pipe->size;
-
- if(!pipeLen && !check->inuse) {
- /* The check for a dead socket makes sense only if there are no
- handles in pipeline and the connection isn't already marked in
- use */
- bool dead;
- if(check->handler->protocol & CURLPROTO_RTSP)
- /* RTSP is a special case due to RTP interleaving */
- dead = Curl_rtsp_connisdead(check);
- else
- dead = SocketIsDead(check->sock[FIRSTSOCKET]);
-
- if(dead) {
- check->data = data;
- infof(data, "Connection %ld seems to be dead!\n",
- check->connection_id);
+ if (RemoveConnectionIfDead(check, data))
+ continue;
- /* disconnect resources */
- Curl_disconnect(check, /* dead_connection */ TRUE);
- continue;
- }
- }
+ pipeLen = check->send_pipe->size + check->recv_pipe->size;
if(canPipeline) {
/* Make sure the pipe has only GET requests */
@@ -5456,6 +5496,10 @@ static CURLcode create_conn(struct SessionHandle *data,
goto out;
}
+
+ CleanupDeadConnections(data);
+
+
/*************************************************************
* Check the current list of connections to see if we can
* re-use an already existing one or if we have to create a
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html