aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/multi.c38
-rw-r--r--lib/multiif.h3
-rw-r--r--lib/url.c30
-rw-r--r--lib/urldata.h3
4 files changed, 47 insertions, 27 deletions
diff --git a/lib/multi.c b/lib/multi.c
index 244994cfe..9d596401a 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -172,6 +172,8 @@ static bool multi_conn_using(struct Curl_multi *multi,
struct SessionHandle *data);
static void singlesocket(struct Curl_multi *multi,
struct Curl_one_easy *easy);
+static void add_closure(struct Curl_multi *multi,
+ struct SessionHandle *data);
/* always use this function to change state, to make debugging easier */
static void multistate(struct Curl_one_easy *easy, CURLMstate state)
@@ -539,17 +541,28 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
we need to add this handle to the list of "easy handles kept around for
nice connection closures".
*/
- if(multi_conn_using(multi, easy->easy_handle))
+ if(multi_conn_using(multi, easy->easy_handle)) {
/* There's at least one connection using this handle so we must keep
this handle around. We also keep the connection cache pointer
pointing to the shared one since that will be used on close as
well. */
easy->easy_handle->state.shared_conn = multi;
- else
- if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI)
- /* if this was using the shared connection cache we clear the pointer
- to that */
- easy->easy_handle->state.connc = NULL;
+
+ /* this handle is still being used by a shared connection cache and
+ thus we leave it around for now */
+ add_closure(multi, easy->easy_handle);
+ }
+
+ if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI) {
+ /* if this was using the shared connection cache we clear the pointer
+ to that since we're not part of that handle anymore */
+ easy->easy_handle->state.connc = NULL;
+
+ /* and modify the connectindex since this handle can't point to the
+ connection cache anymore */
+ if(easy->easy_conn)
+ easy->easy_conn->connectindex = -1;
+ }
/* change state without using multistate(), only to make singlesocket() do
what we want */
@@ -1320,15 +1333,20 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
/* go over all connections that have close actions */
for(i=0; i< multi->connc->num; i++) {
if(multi->connc->connects[i] &&
- multi->connc->connects[i]->protocol & PROT_CLOSEACTION)
+ multi->connc->connects[i]->protocol & PROT_CLOSEACTION) {
Curl_disconnect(multi->connc->connects[i]);
+ multi->connc->connects[i] = NULL;
+ }
}
/* now walk through the list of handles we kept around only to be
able to close connections "properly" */
cl = multi->closure;
while(cl) {
cl->easy_handle->state.shared_conn = NULL; /* no more shared */
- Curl_close(cl->easy_handle); /* close handle */
+ if(cl->easy_handle->state.closed)
+ /* close handle only if curl_easy_cleanup() already has been called
+ for this easy handle */
+ Curl_close(cl->easy_handle);
n = cl->next;
free(cl);
cl= n;
@@ -1780,8 +1798,8 @@ static bool multi_conn_using(struct Curl_multi *multi,
/* add the given data pointer to the list of 'closure handles' that are
kept around only to be able to close some connections nicely */
-void Curl_multi_add_closure(struct Curl_multi *multi,
- struct SessionHandle *data)
+static void add_closure(struct Curl_multi *multi,
+ struct SessionHandle *data)
{
int i;
struct closure *cl = (struct closure *)calloc(sizeof(struct closure), 1);
diff --git a/lib/multiif.h b/lib/multiif.h
index 45b3d2032..800aa0f5d 100644
--- a/lib/multiif.h
+++ b/lib/multiif.h
@@ -32,9 +32,6 @@ void Curl_multi_rmeasy(void *multi, CURL *data);
bool Curl_multi_canPipeline(struct Curl_multi* multi);
-void Curl_multi_add_closure(struct Curl_multi *multi,
- struct SessionHandle *data);
-
/* the write bits start at bit 16 for the *getsock() bitmap */
#define GETSOCK_WRITEBITSTART 16
diff --git a/lib/url.c b/lib/url.c
index 50390108f..968421079 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -269,29 +269,31 @@ CURLcode Curl_close(struct SessionHandle *data)
the multi handle, since that function uses the magic
field! */
- if(data->state.connc && (data->state.connc->type == CONNCACHE_PRIVATE)) {
- /* close all connections still alive that are in the private connection
- cache, as we no longer have the pointer left to the shared one. */
- close_connections(data);
+ if(data->state.connc) {
- /* free the connection cache if allocated privately */
- Curl_rm_connc(data->state.connc);
- }
+ if(data->state.connc->type == CONNCACHE_PRIVATE) {
+ /* close all connections still alive that are in the private connection
+ cache, as we no longer have the pointer left to the shared one. */
+ close_connections(data);
- if ( ! (data->share && data->share->hostcache) ) {
- if ( !Curl_global_host_cache_use(data)) {
- Curl_hash_destroy(data->dns.hostcache);
+ /* free the connection cache if allocated privately */
+ Curl_rm_connc(data->state.connc);
}
}
if(data->state.shared_conn) {
- /* this handle is still being used by a shared connection cache and thus
- we leave it around for now */
- Curl_multi_add_closure(data->state.shared_conn, data);
-
+ /* marked to be used by a pending connection so we can't kill this handle
+ just yet */
+ data->state.closed = TRUE;
return CURLE_OK;
}
+ if ( ! (data->share && data->share->hostcache) ) {
+ if ( !Curl_global_host_cache_use(data)) {
+ Curl_hash_destroy(data->dns.hostcache);
+ }
+ }
+
/* Free the pathbuffer */
Curl_safefree(data->reqdata.pathbuffer);
Curl_safefree(data->reqdata.proto.generic);
diff --git a/lib/urldata.h b/lib/urldata.h
index d90c6cd08..875dd0032 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1053,6 +1053,9 @@ struct UrlState {
must keep it around and add it to the list of handles to kill once all
its connections are gone */
void *shared_conn;
+ bool closed; /* set to TRUE when curl_easy_cleanup() has been called on this
+ handle, but it is kept around as mentioned for
+ shared_conn */
};