From: Stefan Eissing Date: Tue, 17 Nov 2015 14:13:19 +0000 (+0000) Subject: flushing and shutdown tuning X-Git-Tag: 2.5.0-alpha~2640 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c957f56b378257da278f2bd198ad6a31553fb8e3;p=thirdparty%2Fapache%2Fhttpd.git flushing and shutdown tuning git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1714788 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/http2/h2_conn.c b/modules/http2/h2_conn.c index 4ee4b37d4cd..663139624e2 100644 --- a/modules/http2/h2_conn.c +++ b/modules/http2/h2_conn.c @@ -174,10 +174,12 @@ apr_status_t h2_conn_process(conn_rec *c, request_rec *r) } status = h2_session_process(session); - h2_session_close(session); ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c, "h2_session(%ld): done", session->id); + h2_session_close(session); + h2_session_flush(session); + /* hereafter session might be gone */ /* Make sure this connection gets closed properly. */ ap_update_child_status_from_conn(c->sbh, SERVER_CLOSING, c); diff --git a/modules/http2/h2_conn_io.c b/modules/http2/h2_conn_io.c index 1fc7d37e9f4..7a241146f01 100644 --- a/modules/http2/h2_conn_io.c +++ b/modules/http2/h2_conn_io.c @@ -278,7 +278,7 @@ 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(io); + status = h2_conn_io_pass(io); io->unflushed = 1; } @@ -338,15 +338,15 @@ apr_status_t h2_conn_io_consider_flush(h2_conn_io *io) } len += io->buflen; if (len >= WRITE_BUFFER_SIZE) { - return h2_conn_io_flush(io); + return h2_conn_io_pass(io); } } return status; } -apr_status_t h2_conn_io_flush(h2_conn_io *io) +static apr_status_t h2_conn_io_flush_int(h2_conn_io *io, int force) { - if (io->unflushed) { + if (io->unflushed || force) { apr_status_t status; if (io->buflen > 0) { /* something in the buffer, put it in the output brigade */ @@ -356,8 +356,11 @@ apr_status_t h2_conn_io_flush(h2_conn_io *io) io->buflen = 0; } - APR_BRIGADE_INSERT_TAIL(io->output, - apr_bucket_flush_create(io->output->bucket_alloc)); + if (force) { + APR_BRIGADE_INSERT_TAIL(io->output, + apr_bucket_flush_create(io->output->bucket_alloc)); + } + /* Send it out */ status = pass_out(io->output, io); @@ -374,3 +377,12 @@ apr_status_t h2_conn_io_flush(h2_conn_io *io) return APR_SUCCESS; } +apr_status_t h2_conn_io_flush(h2_conn_io *io) +{ + return h2_conn_io_flush_int(io, 1); +} + +apr_status_t h2_conn_io_pass(h2_conn_io *io) +{ + return h2_conn_io_flush_int(io, 0); +} \ No newline at end of file diff --git a/modules/http2/h2_conn_io.h b/modules/http2/h2_conn_io.h index a0cb3977844..4406261a33b 100644 --- a/modules/http2/h2_conn_io.h +++ b/modules/http2/h2_conn_io.h @@ -63,6 +63,7 @@ apr_status_t h2_conn_io_writeb(h2_conn_io *io, apr_bucket *b); apr_status_t h2_conn_io_consider_flush(h2_conn_io *io); +apr_status_t h2_conn_io_pass(h2_conn_io *io); apr_status_t h2_conn_io_flush(h2_conn_io *io); #endif /* defined(__mod_h2__h2_conn_io__) */ diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c index 253868461b3..f318fd16a07 100644 --- a/modules/http2/h2_mplx.c +++ b/modules/http2/h2_mplx.c @@ -114,7 +114,7 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr_pool_t *parent, h2_workers *workers) APR_RING_ELEM_INIT(m, link); apr_atomic_set32(&m->refs, 1); m->c = c; - apr_pool_create_ex(&m->pool, parent, NULL, allocator); + apr_pool_create_ex(&m->pool, NULL, NULL, allocator); if (!m->pool) { return NULL; } diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c index f836c261be7..3a0415f3ff8 100644 --- a/modules/http2/h2_session.c +++ b/modules/http2/h2_session.c @@ -84,9 +84,8 @@ h2_stream *h2_session_open_stream(h2_session *session, int stream_id) return stream; } -static apr_status_t h2_session_flush(h2_session *session) +apr_status_t h2_session_flush(h2_session *session) { - session->flush = 0; return h2_conn_io_flush(&session->io); } @@ -236,72 +235,6 @@ static int on_data_chunk_recv_cb(nghttp2_session *ngh2, uint8_t flags, return 0; } -static int before_frame_send_cb(nghttp2_session *ngh2, - const nghttp2_frame *frame, - void *userp) -{ - h2_session *session = (h2_session *)userp; - (void)ngh2; - - if (session->aborted) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - /* Set the need to flush output when we have added one of the - * following frame types */ - switch (frame->hd.type) { - case NGHTTP2_RST_STREAM: - case NGHTTP2_PUSH_PROMISE: - case NGHTTP2_GOAWAY: - session->flush = 1; - break; - default: - break; - - } - if (APLOGctrace2(session->c)) { - char buffer[256]; - frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0])); - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, - "h2_session(%ld): before_frame_send %s", - session->id, buffer); - } - return 0; -} - -static int on_frame_send_cb(nghttp2_session *ngh2, - const nghttp2_frame *frame, - void *userp) -{ - h2_session *session = (h2_session *)userp; - (void)ngh2; - if (APLOGctrace2(session->c)) { - char buffer[256]; - frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0])); - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, - "h2_session(%ld): on_frame_send %s", - session->id, buffer); - } - return 0; -} - -static int on_frame_not_send_cb(nghttp2_session *ngh2, - const nghttp2_frame *frame, - int lib_error_code, void *userp) -{ - h2_session *session = (h2_session *)userp; - (void)ngh2; - - if (APLOGctrace2(session->c)) { - char buffer[256]; - - frame_print(frame, buffer, sizeof(buffer)/sizeof(buffer[0])); - ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, - "h2_session: callback on_frame_not_send error=%d %s", - lib_error_code, buffer); - } - return 0; -} - static apr_status_t stream_release(h2_session *session, h2_stream *stream, uint32_t error_code) @@ -616,9 +549,6 @@ static apr_status_t init_callbacks(conn_rec *c, nghttp2_session_callbacks **pcb) NGH2_SET_CALLBACK(*pcb, on_frame_recv, on_frame_recv_cb); NGH2_SET_CALLBACK(*pcb, on_invalid_frame_recv, on_invalid_frame_recv_cb); NGH2_SET_CALLBACK(*pcb, on_data_chunk_recv, on_data_chunk_recv_cb); - NGH2_SET_CALLBACK(*pcb, before_frame_send, before_frame_send_cb); - NGH2_SET_CALLBACK(*pcb, on_frame_send, on_frame_send_cb); - NGH2_SET_CALLBACK(*pcb, on_frame_not_send, on_frame_not_send_cb); NGH2_SET_CALLBACK(*pcb, on_stream_close, on_stream_close_cb); NGH2_SET_CALLBACK(*pcb, on_begin_headers, on_begin_headers_cb); NGH2_SET_CALLBACK(*pcb, on_header, on_header_cb); @@ -735,10 +665,6 @@ h2_session *h2_session_rcreate(request_rec *r, h2_config *config, void h2_session_cleanup(h2_session *session) { AP_DEBUG_ASSERT(session); - if (session->mplx) { - h2_mplx_release_and_join(session->mplx, session->iowait); - session->mplx = NULL; - } if (session->ngh2) { nghttp2_session_del(session->ngh2); session->ngh2 = NULL; @@ -747,6 +673,10 @@ void h2_session_cleanup(h2_session *session) apr_pool_destroy(session->spare); session->spare = NULL; } + if (session->mplx) { + h2_mplx_release_and_join(session->mplx, session->iowait); + session->mplx = NULL; + } } void h2_session_destroy(h2_session *session) @@ -764,7 +694,6 @@ void h2_session_destroy(h2_session *session) session->streams = NULL; } if (session->pool) { - apr_pool_cleanup_kill(session->pool, session, session_pool_cleanup); apr_pool_destroy(session->pool); } } @@ -774,6 +703,7 @@ void h2_session_eoc_callback(h2_session *session) { ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c, "session(%ld): cleanup and destroy", session->id); + apr_pool_cleanup_kill(session->pool, session, session_pool_cleanup); h2_session_destroy(session); } @@ -810,7 +740,6 @@ static apr_status_t h2_session_abort_int(h2_session *session, int reason) strlen(err)); nghttp2_session_send(session->ngh2); } - h2_session_flush(session); } h2_mplx_abort(session->mplx); } @@ -1033,12 +962,11 @@ apr_status_t h2_session_close(h2_session *session) } ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0,session->c, "h2_session: closing, writing eoc"); - - h2_session_cleanup(session); - h2_conn_io_writeb(&session->io, - h2_bucket_eoc_create(session->c->bucket_alloc, - session)); - return h2_session_flush(session); + + h2_session_cleanup(session); + return h2_conn_io_writeb(&session->io, + h2_bucket_eoc_create(session->c->bucket_alloc, + session)); } static ssize_t stream_data_cb(nghttp2_session *ng2s, @@ -1400,13 +1328,10 @@ apr_status_t h2_session_process(h2_session *session) } } - if (have_written) { - h2_session_flush(session); - } - if (wait_micros > 0) { ap_log_cerror( APLOG_MARK, APLOG_TRACE3, 0, session->c, "h2_session: wait for data, %ld micros", (long)(wait_micros)); + h2_conn_io_pass(&session->io); status = h2_mplx_out_trywait(session->mplx, wait_micros, session->iowait); if (status == APR_TIMEUP) { @@ -1446,7 +1371,7 @@ apr_status_t h2_session_process(h2_session *session) } if (may_block) { - h2_session_flush(session); + h2_conn_io_flush(&session->io); if (session->c->cs) { session->c->cs->state = (got_streams? CONN_STATE_HANDLER : CONN_STATE_WRITE_COMPLETION); diff --git a/modules/http2/h2_session.h b/modules/http2/h2_session.h index 377efc70b6c..052b0d7e388 100644 --- a/modules/http2/h2_session.h +++ b/modules/http2/h2_session.h @@ -59,7 +59,6 @@ struct h2_session { request_rec *r; /* the request that started this in case * of 'h2c', NULL otherwise */ int aborted; /* this session is being aborted */ - int flush; /* if != 0, flush output on next occasion */ int reprioritize; /* scheduled streams priority needs to * be re-evaluated */ apr_size_t frames_received; /* number of http/2 frames received */ @@ -156,6 +155,12 @@ apr_status_t h2_session_start(h2_session *session, int *rv); */ apr_status_t h2_session_abort(h2_session *session, apr_status_t reason, int rv); +/** + * Pass any buffered output data through the connection filters. + * @param session the session to flush + */ +apr_status_t h2_session_flush(h2_session *session); + /** * Called before a session gets destroyed, might flush output etc. */ diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c index a6be8b10ea3..ec55ceb698e 100644 --- a/modules/http2/h2_stream.c +++ b/modules/http2/h2_stream.c @@ -259,6 +259,8 @@ apr_status_t h2_stream_schedule(h2_stream *stream, int eos, { apr_status_t status; AP_DEBUG_ASSERT(stream); + AP_DEBUG_ASSERT(stream->session); + AP_DEBUG_ASSERT(stream->session->mplx); if (!output_open(stream)) { return APR_ECONNRESET;