- 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

@ -6,7 +6,12 @@
Changelog
Daniel Fandrich (3 Dec 2008)
Daniel Stenberg (3 Dec 2008)
- 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.
- Pawel Kierski pointed out a mistake in the cookie code that could lead to a
bad fclose() after a fatal error had occured.
(http://curl.haxx.se/bug/view.cgi?id=2382219)

View File

@ -23,6 +23,7 @@ This release includes the following bugfixes:
o removed the default use of "Pragma: no-cache"
o fix SCP/SFTP busyloop by using a new libssh2 0.19 function
o bad fclose() after a fatal error in cookie code
o curl_multi_remove_handle() when the handle was in use in a HTTP pipeline
This release includes the following known bugs:
@ -32,6 +33,6 @@ This release would not have looked like this without help, code, reports and
advice from friends like these:
Yang Tse, Daniel Fandrich, Jim Meyering, Christian Krause, Andreas Wurf,
Markus Koetter, Josef Wolf, Vlad Grachov, Pawel Kierski
Markus Koetter, Josef Wolf, Vlad Grachov, Pawel Kierski, Igor Novoseltsev
Thanks! (and sorry if I forgot to mention someone)

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);