aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES7
-rw-r--r--RELEASE-NOTES3
-rw-r--r--lib/multi.c31
-rw-r--r--lib/url.c22
-rw-r--r--lib/url.h4
5 files changed, 45 insertions, 22 deletions
diff --git a/CHANGES b/CHANGES
index 67dd1d73a..c052fc8bf 100644
--- a/CHANGES
+++ b/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)
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 41408de0c..c41776500 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -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)
diff --git a/lib/multi.c b/lib/multi.c
index b82be6245..ccccf7e8f 100644
--- a/lib/multi.c
+++ b/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) {
+
+ /* 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) {
- /* Curl_done() clears the conn->data field to lose the association
- between the easy handle and the connection
+ /* Curl_done() clears the conn->data field to lose the association
+ between the easy handle and the connection
- 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);
+ 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;
+ 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
diff --git a/lib/url.c b/lib/url.c
index 6bb3e3ee7..9037bf920 100644
--- a/lib/url.c
+++ b/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 &&
diff --git a/lib/url.h b/lib/url.h
index 229f40866..8ca70a850 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -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);