dovecot-2.2: lib-http: client: Fixed problem occuring when a nes...

dovecot at dovecot.org dovecot at dovecot.org
Sat Oct 4 14:33:30 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/ecb0ba0ce02f
changeset: 17876:ecb0ba0ce02f
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sat Oct 04 17:30:54 2014 +0300
description:
lib-http: client: Fixed problem occuring when a nested ioloop was run inside a request callback using the same client.
If requests in the nested ioloop would use the same connection as the one
that called the callback, the requests would (in the best scenario) all be
doomed to time out.

diffstat:

 src/lib-http/http-client-connection.c |  17 +++++++++++++++--
 src/lib-http/http-client-private.h    |   1 +
 2 files changed, 16 insertions(+), 2 deletions(-)

diffs (68 lines):

diff -r dd25099bd633 -r ecb0ba0ce02f src/lib-http/http-client-connection.c
--- a/src/lib-http/http-client-connection.c	Sat Oct 04 00:29:30 2014 +0300
+++ b/src/lib-http/http-client-connection.c	Sat Oct 04 17:30:54 2014 +0300
@@ -53,13 +53,22 @@
 {
 	unsigned int pending_count = array_count(&conn->request_wait_list);
 
-	if (conn->pending_request != NULL)
+	if (conn->in_req_callback || conn->pending_request != NULL)
 		pending_count++;
 	return pending_count;
 }
 
 bool http_client_connection_is_ready(struct http_client_connection *conn)
 {
+	if (conn->in_req_callback) {
+		/* this can happen when a nested ioloop is created inside request
+		   callback. we currently don't reuse connections that are occupied
+		   this way, but theoretically we could, although that would add
+		   quite a bit of complexity.
+		 */
+		return FALSE;
+	}
+
 	return (conn->connected && !conn->output_locked &&
 		!conn->close_indicated && !conn->tunneling &&
 		http_client_connection_count_pending(conn) <
@@ -184,6 +193,7 @@
 	if (conn->connected &&
 		array_is_created(&conn->request_wait_list) &&
 		array_count(&conn->request_wait_list) == 0 &&
+		!conn->in_req_callback &&
 		conn->incoming_payload == NULL &&
 		conn->client->set.max_idle_time_msecs > 0) {
 
@@ -437,6 +447,7 @@
 	struct istream *payload;
 	bool retrying;
 
+	i_assert(!conn->in_req_callback);
 	i_assert(conn->incoming_payload == NULL);
 	i_assert(conn->pending_request == NULL);
 
@@ -459,10 +470,12 @@
 		if (conn->to_requests != NULL)
 			timeout_remove(&conn->to_requests);
 	}
-
+	
+	conn->in_req_callback = TRUE;
 	http_client_connection_ref(conn);
 	retrying = !http_client_request_callback(req, response);
 	http_client_connection_unref(&conn);
+	conn->in_req_callback = FALSE;
 	if (conn == NULL) {
 		/* the callback managed to get this connection destroyed */
 		if (!retrying)
diff -r dd25099bd633 -r ecb0ba0ce02f src/lib-http/http-client-private.h
--- a/src/lib-http/http-client-private.h	Sat Oct 04 00:29:30 2014 +0300
+++ b/src/lib-http/http-client-private.h	Sat Oct 04 17:30:54 2014 +0300
@@ -142,6 +142,7 @@
 	unsigned int output_locked:1;       /* output is locked; no pipelining */
 	unsigned int payload_continue:1;    /* received 100-continue for current
 	                                        request */
+	unsigned int in_req_callback:1;  /* performin request callback (busy) */
 };
 
 struct http_client_peer {


More information about the dovecot-cvs mailing list