diff --git a/lib/conncache.c b/lib/conncache.c index 5ba2368622..6fc29be4b4 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -687,6 +687,7 @@ void Curl_conn_terminate(struct Curl_easy *data, struct cpool_reaper_ctx { size_t checked; size_t reaped; + struct curltime now; }; static int cpool_reap_dead_cb(struct Curl_easy *data, @@ -697,7 +698,7 @@ static int cpool_reap_dead_cb(struct Curl_easy *data, if(!terminate) { reaper->checked++; - terminate = Curl_conn_seems_dead(conn, data); + terminate = Curl_conn_seems_dead(conn, data, &reaper->now); } if(terminate) { /* stop the iteration here, pass back the connection that was pruned */ @@ -718,17 +719,19 @@ static int cpool_reap_dead_cb(struct Curl_easy *data, void Curl_cpool_prune_dead(struct Curl_easy *data) { struct cpool *cpool = cpool_get_instance(data); - struct cpool_reaper_ctx reaper; timediff_t elapsed; if(!cpool) return; - memset(&reaper, 0, sizeof(reaper)); CPOOL_LOCK(cpool, data); elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &cpool->last_cleanup); if(elapsed >= 1000L) { + struct cpool_reaper_ctx reaper; + + memset(&reaper, 0, sizeof(reaper)); + reaper.now = *Curl_pgrs_now(data); while(cpool_foreach(data, cpool, &reaper, cpool_reap_dead_cb)) ; cpool->last_cleanup = *Curl_pgrs_now(data); diff --git a/lib/url.c b/lib/url.c index d0e0286d2f..1567d5bf3c 100644 --- a/lib/url.c +++ b/lib/url.c @@ -606,7 +606,8 @@ static bool conn_maxage(struct Curl_easy *data, * Return TRUE iff the given connection is considered dead. */ bool Curl_conn_seems_dead(struct connectdata *conn, - struct Curl_easy *data) + struct Curl_easy *data, + const struct curltime *pnow) { DEBUGASSERT(!data->conn); if(!CONN_INUSE(conn)) { @@ -614,10 +615,12 @@ bool Curl_conn_seems_dead(struct connectdata *conn, use */ bool dead; - if(conn_maxage(data, conn, *Curl_pgrs_now(data))) { + if(conn_maxage(data, conn, *pnow)) { /* avoid check if already too old */ dead = TRUE; } + else if(curlx_ptimediff_ms(pnow, &conn->lastchecked) < 1000) + dead = FALSE; else if(conn->scheme->run->connection_is_dead) { /* The protocol has a special method for checking the state of the connection. Use it to check if the connection is dead. */ @@ -625,6 +628,7 @@ bool Curl_conn_seems_dead(struct connectdata *conn, Curl_attach_connection(data, conn); dead = conn->scheme->run->connection_is_dead(data, conn); Curl_detach_connection(data); + conn->lastchecked = *pnow; } else { bool input_pending = FALSE; @@ -644,6 +648,7 @@ bool Curl_conn_seems_dead(struct connectdata *conn, dead = TRUE; } Curl_detach_connection(data); + conn->lastchecked = *pnow; } if(dead) { @@ -690,6 +695,7 @@ struct url_conn_match { struct connectdata *found; struct Curl_easy *data; struct connectdata *needle; + struct curltime now; BIT(may_multiplex); BIT(want_ntlm_http); BIT(want_proxy_ntlm_http); @@ -1172,7 +1178,7 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) if(!url_match_multiplex_limits(conn, m)) return FALSE; - if(!CONN_INUSE(conn) && Curl_conn_seems_dead(conn, m->data)) { + if(!CONN_INUSE(conn) && Curl_conn_seems_dead(conn, m->data, &m->now)) { /* remove and disconnect. */ Curl_conn_terminate(m->data, conn, FALSE); return FALSE; @@ -1227,6 +1233,7 @@ static bool url_attach_existing(struct Curl_easy *data, memset(&match, 0, sizeof(match)); match.data = data; match.needle = needle; + match.now = *Curl_pgrs_now(data); match.may_multiplex = xfer_may_multiplex(data, needle); #ifdef USE_NTLM diff --git a/lib/url.h b/lib/url.h index ebbe9d53c4..02f1bd3943 100644 --- a/lib/url.h +++ b/lib/url.h @@ -75,7 +75,8 @@ void *Curl_conn_meta_get(struct connectdata *conn, const char *key); * Return TRUE iff the given connection is considered dead. */ bool Curl_conn_seems_dead(struct connectdata *conn, - struct Curl_easy *data); + struct Curl_easy *data, + const struct curltime *pnow); /** * Perform upkeep operations on the connection. diff --git a/lib/urldata.h b/lib/urldata.h index 35d2c3f528..4666fa3658 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -305,6 +305,7 @@ struct connectdata { char *options; /* options string, allocated */ struct curltime created; /* creation time */ struct curltime lastused; /* when returned to the connection pool as idle */ + struct curltime lastchecked; /* when last checked alive status */ /* A connection can have one or two sockets and connection filters. * The protocol using the 2nd one is FTP for CONTROL+DATA sockets */