From 5cc9e2004ec79fe19ffd75254fd882f9aee7c9a9 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Wed, 10 Feb 2016 15:10:51 +0000 Subject: [PATCH] giving write operations a chance after a max of 64k has been read, not entering async keepalive before first request is seen git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1729624 13f79535-47bb-0310-9956-ffa450edef68 --- modules/http2/h2_conn_io.c | 6 +++--- modules/http2/h2_session.c | 32 +++++++++++++++++--------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/modules/http2/h2_conn_io.c b/modules/http2/h2_conn_io.c index b8ce2c0eb14..4a8375b9401 100644 --- a/modules/http2/h2_conn_io.c +++ b/modules/http2/h2_conn_io.c @@ -44,7 +44,7 @@ */ #define WRITE_SIZE_MAX (TLS_DATA_MAX - 100) -#define WRITE_BUFFER_SIZE (8*WRITE_SIZE_MAX) +#define WRITE_BUFFER_SIZE (5*WRITE_SIZE_MAX) apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c, const h2_config *cfg, @@ -249,13 +249,13 @@ apr_status_t h2_conn_io_write(h2_conn_io *io, "h2_conn_io: buffering %ld bytes", (long)length); if (!APR_BRIGADE_EMPTY(io->output)) { - status = h2_conn_io_flush_int(io, 0, 0); + status = h2_conn_io_pass(io, 0); } while (length > 0 && (status == APR_SUCCESS)) { apr_size_t avail = io->bufsize - io->buflen; if (avail <= 0) { - h2_conn_io_flush_int(io, 1, 0); + h2_conn_io_pass(io, 0); } else if (length > avail) { memcpy(io->buffer + io->buflen, buf, avail); diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c index 0d94e05aae7..0eb68a54bee 100644 --- a/modules/http2/h2_session.c +++ b/modules/http2/h2_session.c @@ -1538,13 +1538,13 @@ static apr_status_t h2_session_receive(void *ctx, const char *data, return APR_SUCCESS; } -static apr_status_t h2_session_read(h2_session *session, int block, int loops) +static apr_status_t h2_session_read(h2_session *session, int block) { apr_status_t status, rstatus = APR_EAGAIN; conn_rec *c = session->c; - int i; + apr_off_t read_start = session->io.bytes_read; - for (i = 0; i < loops; ++i) { + while (1) { /* H2_IN filter handles all incoming data against the session. * We just pull at the filter chain to make it happen */ status = ap_get_brigade(c->input_filters, @@ -1569,7 +1569,7 @@ static apr_status_t h2_session_read(h2_session *session, int block, int loops) case APR_TIMEUP: return status; default: - if (!i) { + if (session->io.bytes_read == read_start) { /* first attempt failed */ if (APR_STATUS_IS_ETIMEDOUT(status) || APR_STATUS_IS_ECONNABORTED(status) @@ -1596,6 +1596,12 @@ static apr_status_t h2_session_read(h2_session *session, int block, int loops) if (!is_accepting_streams(session)) { break; } + if ((session->io.bytes_read - read_start) > (64*1024)) { + /* read enough in one go, give write a chance */ + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, c, + "h2_session(%ld): read 64k, returning", session->id); + break; + } } return rstatus; } @@ -1785,7 +1791,9 @@ static void h2_session_ev_no_io(h2_session *session, int arg, const char *msg) /* When we have no streams, no task event are possible, * switch to blocking reads */ transit(session, "no io", H2_SESSION_ST_IDLE); - session->idle_until = apr_time_now() + session->s->keep_alive_timeout; + session->idle_until = (session->requests_received? + session->s->keep_alive_timeout : + session->s->timeout) + apr_time_now(); } } else if (!h2_stream_set_has_unsubmitted(session->streams) @@ -1991,7 +1999,7 @@ apr_status_t h2_session_process(h2_session *session, int async) no_streams = h2_stream_set_is_empty(session->streams); update_child_status(session, (no_streams? SERVER_BUSY_KEEPALIVE : SERVER_BUSY_READ), "idle"); - if (async && !session->r) { + if (async && !session->r && session->requests_received && no_streams) { ap_log_cerror( APLOG_MARK, APLOG_TRACE1, status, c, "h2_session(%ld): async idle, nonblock read", session->id); /* We do not return to the async mpm immediately, since under @@ -2003,13 +2011,7 @@ apr_status_t h2_session_process(h2_session *session, int async) * time here for the next frame to arrive, before handing * it to keep_alive processing of the mpm. */ - if (no_streams) { - status = h2_session_read(session, 0, 20); - } - else { - h2_filter_cin_timeout_set(session->cin, session->s->timeout); - status = h2_session_read(session, 1, 20); - } + status = h2_session_read(session, 0); if (status == APR_SUCCESS) { have_read = 1; @@ -2035,7 +2037,7 @@ apr_status_t h2_session_process(h2_session *session, int async) /* We wait in smaller increments, using a 1 second timeout. * That gives us the chance to check for MPMQ_STOPPING often. */ h2_filter_cin_timeout_set(session->cin, apr_time_from_sec(1)); - status = h2_session_read(session, 1, 10); + status = h2_session_read(session, 1); if (status == APR_SUCCESS) { have_read = 1; dispatch_event(session, H2_SESSION_EV_DATA_READ, 0, NULL); @@ -2061,7 +2063,7 @@ apr_status_t h2_session_process(h2_session *session, int async) case H2_SESSION_ST_REMOTE_SHUTDOWN: if (nghttp2_session_want_read(session->ngh2)) { h2_filter_cin_timeout_set(session->cin, session->s->timeout); - status = h2_session_read(session, 0, 20); + status = h2_session_read(session, 0); if (status == APR_SUCCESS) { have_read = 1; dispatch_event(session, H2_SESSION_EV_DATA_READ, 0, NULL); -- 2.47.3