Hello
Since my colleague Frank Meier is on vacations I continue the conversation
he startet 19th June 2014 (dead connections are not cleaned up on new
requests).
I just joined the mailing list, this is why I am not replying to the
original thread.
Frank sent a patch to fix the issue. Daniel Stenberg would like to merge
the patch but suggests to make sure the clean-up isn't done too often.
I am sending a second patch which makes sure that the clean-up is done
at most once per second.
I am also sending Frank's patch with the fixed code formatting issues.
diff --git a/lib/url.c b/lib/url.c
index 770b0cc..3630ac6 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2910,6 +2910,66 @@ 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 +3033,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 +5497,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
diff --git a/lib/conncache.h b/lib/conncache.h
index 691f061..96a0be0 100644
--- a/lib/conncache.h
+++ b/lib/conncache.h
@@ -26,6 +26,7 @@ struct conncache {
struct curl_hash *hash;
size_t num_connections;
size_t next_connection_id;
+ struct timeval last_cleanup;
};
struct conncache *Curl_conncache_init(int size);
diff --git a/lib/url.c b/lib/url.c
index 3630ac6..8fdcf29 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2962,11 +2962,18 @@ static int RemoveConnectionIfDeadWrapper(struct connectdata *check,
/*
* This function scans the connection cache for half-open/dead connections,
* closes and removes them.
+ * The cleanup is done at most once per second.
*/
static void CleanupDeadConnections(struct SessionHandle *data) {
- Curl_conncache_foreach(data->state.conn_cache, data,
- RemoveConnectionIfDeadWrapper);
+ struct timeval now = Curl_tvnow();
+ long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
+
+ if(elapsed >= 1000L) {
+ Curl_conncache_foreach(data->state.conn_cache, data,
+ RemoveConnectionIfDeadWrapper);
+ data->state.conn_cache->last_cleanup = now;
+ }
}
/*
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html