- Igor Novoseltsev filed bug #2351645

(http://curl.haxx.se/bug/view.cgi?id=2351645) that identified a problem with
  the multi interface that occured if you removed an easy handle while in
  progress and the handle was used in a HTTP pipeline.
This commit is contained in:
Daniel Stenberg 2008-12-03 15:20:27 +00:00
parent 4ee27b4594
commit 479ddb1fee
5 changed files with 45 additions and 22 deletions

View file

@ -620,22 +620,27 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
}
/* we must call Curl_done() here (if we still "own it") so that we don't
leave a half-baked one around */
if(easy->easy_conn &&
(easy->easy_conn->data == easy->easy_handle)) {
if(easy->easy_conn) {
/* Curl_done() clears the conn->data field to lose the association
between the easy handle and the connection
/* we must call Curl_done() here (if we still "own it") so that we don't
leave a half-baked one around */
if (easy->easy_conn->data == easy->easy_handle) {
Note that this ignores the return code simply because there's nothing
really useful to do with it anyway! */
(void)Curl_done(&easy->easy_conn, easy->result, premature);
/* Curl_done() clears the conn->data field to lose the association
between the easy handle and the connection
if(easy->easy_conn)
/* the connection is still alive, set back the association to enable
the check below to trigger TRUE */
easy->easy_conn->data = easy->easy_handle;
Note that this ignores the return code simply because there's
nothing really useful to do with it anyway! */
(void)Curl_done(&easy->easy_conn, easy->result, premature);
if(easy->easy_conn)
/* the connection is still alive, set back the association to enable
the check below to trigger TRUE */
easy->easy_conn->data = easy->easy_handle;
}
else
/* Clear connection pipelines, if Curl_done above was not called */
Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
}
/* If this easy_handle was the last one in charge for one or more

View file

@ -2359,6 +2359,20 @@ int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
return 0;
}
/* remove the specified connection from all (possible) pipelines and related
queues */
void Curl_getoff_all_pipelines(struct SessionHandle *data,
struct connectdata *conn)
{
if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) &&
conn->readchannel_inuse)
conn->readchannel_inuse = FALSE;
if(Curl_removeHandleFromPipeline(data, conn->send_pipe) &&
conn->writechannel_inuse)
conn->writechannel_inuse = FALSE;
Curl_removeHandleFromPipeline(data, conn->pend_pipe);
}
#if 0 /* this code is saved here as it is useful for debugging purposes */
static void Curl_printPipeline(struct curl_llist *pipeline)
{
@ -4548,13 +4562,7 @@ CURLcode Curl_done(struct connectdata **connp,
Curl_expire(data, 0); /* stop timer */
if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) &&
conn->readchannel_inuse)
conn->readchannel_inuse = FALSE;
if(Curl_removeHandleFromPipeline(data, conn->send_pipe) &&
conn->writechannel_inuse)
conn->writechannel_inuse = FALSE;
Curl_removeHandleFromPipeline(data, conn->pend_pipe);
Curl_getoff_all_pipelines(data, conn);
if(conn->bits.done ||
(conn->send_pipe->size + conn->recv_pipe->size != 0 &&

View file

@ -69,6 +69,10 @@ CURLcode Curl_addHandleToPipeline(struct SessionHandle *handle,
struct curl_llist *pipeline);
int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
struct curl_llist *pipeline);
/* remove the specified connection from all (possible) pipelines and related
queues */
void Curl_getoff_all_pipelines(struct SessionHandle *data,
struct connectdata *conn);
void Curl_close_connections(struct SessionHandle *data);