dovecot-2.2: lib-http: Fixed detecting disconnection when ioloop...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Oct 4 14:33:37 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/77c4b78a4fa2
changeset: 17882:77c4b78a4fa2
user: Stephan Bosch <stephan at rename-it.nl>
date: Sat Oct 04 17:32:48 2014 +0300
description:
lib-http: Fixed detecting disconnection when ioloop is running only intermittently.
This fix only applies to ioloops created and run by lib-http itself.
diffstat:
src/lib-http/http-client-connection.c | 60 +++++++++++++++++++++++++---------
src/lib-http/http-client-private.h | 1 +
src/lib-http/http-client-request.c | 30 ++++++++++-------
3 files changed, 62 insertions(+), 29 deletions(-)
diffs (138 lines):
diff -r 4f175c27bea5 -r 77c4b78a4fa2 src/lib-http/http-client-connection.c
--- a/src/lib-http/http-client-connection.c Sat Oct 04 17:32:48 2014 +0300
+++ b/src/lib-http/http-client-connection.c Sat Oct 04 17:32:48 2014 +0300
@@ -58,23 +58,6 @@
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) <
- conn->client->set.max_pipelined_requests);
-}
-
bool http_client_connection_is_idle(struct http_client_connection *conn)
{
return (conn->to_idle != NULL);
@@ -174,6 +157,48 @@
http_client_connection_unref(_conn);
}
+bool http_client_connection_is_ready(struct http_client_connection *conn)
+{
+ int ret;
+
+ 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;
+ }
+
+ if (!conn->connected || conn->output_locked ||
+ conn->close_indicated || conn->tunneling ||
+ http_client_connection_count_pending(conn) >=
+ conn->client->set.max_pipelined_requests)
+ return FALSE;
+
+ if (conn->last_ioloop != NULL && conn->last_ioloop != current_ioloop) {
+ conn->last_ioloop = current_ioloop;
+ /* Active ioloop is different from what we saw earlier;
+ we may have missed a disconnection event on this connection.
+ Verify status by reading from connection. */
+ if ((ret=i_stream_read(conn->conn.input)) < 0) {
+ int stream_errno = conn->conn.input->stream_errno;
+
+ i_assert(ret != -2);
+ i_assert(conn->conn.input->stream_errno != 0 || conn->conn.input->eof);
+ http_client_connection_abort_temp_error(&conn,
+ HTTP_CLIENT_REQUEST_ERROR_CONNECTION_LOST,
+ t_strdup_printf("Connection lost: read(%s) failed: %s",
+ i_stream_get_name(conn->conn.input),
+ stream_errno != 0 ?
+ i_stream_get_error(conn->conn.input) :
+ "EOF"));
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
static void
http_client_connection_idle_timeout(struct http_client_connection *conn)
{
@@ -802,6 +827,7 @@
{
/* connected */
conn->connected = TRUE;
+ conn->last_ioloop = current_ioloop;
if (conn->to_connect != NULL &&
(conn->ssl_iostream == NULL ||
ssl_iostream_is_handshaked(conn->ssl_iostream)))
diff -r 4f175c27bea5 -r 77c4b78a4fa2 src/lib-http/http-client-private.h
--- a/src/lib-http/http-client-private.h Sat Oct 04 17:32:48 2014 +0300
+++ b/src/lib-http/http-client-private.h Sat Oct 04 17:32:48 2014 +0300
@@ -131,6 +131,7 @@
struct http_client_request *pending_request;
struct istream *incoming_payload;
struct io *io_req_payload;
+ struct ioloop *last_ioloop;
/* requests that have been sent, waiting for response */
ARRAY_TYPE(http_client_request) request_wait_list;
diff -r 4f175c27bea5 -r 77c4b78a4fa2 src/lib-http/http-client-request.c
--- a/src/lib-http/http-client-request.c Sat Oct 04 17:32:48 2014 +0300
+++ b/src/lib-http/http-client-request.c Sat Oct 04 17:32:48 2014 +0300
@@ -792,21 +792,27 @@
o_stream_get_name(output),
o_stream_get_error(output));
ret = -1;
- }
+ } else {
+ http_client_request_debug(req, "Sent header");
- http_client_request_debug(req, "Sent header");
-
- if (ret >= 0 && req->payload_output != NULL) {
- if (!req->payload_sync) {
- if (http_client_request_send_more(req, error_r) < 0)
- ret = -1;
+ if (req->payload_output != NULL) {
+ if (!req->payload_sync) {
+ if (http_client_request_send_more(req, error_r) < 0)
+ ret = -1;
+ } else {
+ http_client_request_debug(req, "Waiting for 100-continue");
+ conn->output_locked = TRUE;
+ }
} else {
- http_client_request_debug(req, "Waiting for 100-continue");
- conn->output_locked = TRUE;
+ req->state = HTTP_REQUEST_STATE_WAITING;
+ conn->output_locked = FALSE;
}
- } else {
- req->state = HTTP_REQUEST_STATE_WAITING;
- conn->output_locked = FALSE;
+ if (ret >= 0 && o_stream_flush(output) < 0) {
+ *error_r = t_strdup_printf("flush(%s) failed: %s",
+ o_stream_get_name(output),
+ o_stream_get_error(output));
+ ret = -1;
+ }
}
o_stream_uncork(output);
return ret;
More information about the dovecot-cvs
mailing list