- 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:
Родитель
4ee27b4594
Коммит
479ddb1fee
7
CHANGES
7
CHANGES
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
31
lib/multi.c
31
lib/multi.c
|
@ -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
|
||||
|
|
22
lib/url.c
22
lib/url.c
|
@ -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 &&
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче