You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by jc...@apache.org on 2017/01/09 19:10:05 UTC
svn commit: r1778029 [2/2] - in
/httpd/httpd/branches/trunk-test-integration: ./ docs/ docs/manual/
docs/manual/howto/ docs/manual/mod/ docs/manual/vhosts/ modules/http2/
server/
Modified: httpd/httpd/branches/trunk-test-integration/modules/http2/h2_mplx.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/trunk-test-integration/modules/http2/h2_mplx.c?rev=1778029&r1=1778028&r2=1778029&view=diff
==============================================================================
--- httpd/httpd/branches/trunk-test-integration/modules/http2/h2_mplx.c (original)
+++ httpd/httpd/branches/trunk-test-integration/modules/http2/h2_mplx.c Mon Jan 9 19:10:05 2017
@@ -17,6 +17,7 @@
#include <stddef.h>
#include <stdlib.h>
+#include <apr_atomic.h>
#include <apr_thread_mutex.h>
#include <apr_thread_cond.h>
#include <apr_strings.h>
@@ -143,6 +144,12 @@ static void stream_output_consumed(void
}
}
+static void stream_input_ev(void *ctx, h2_bucket_beam *beam)
+{
+ h2_mplx *m = ctx;
+ apr_atomic_set32(&m->event_pending, 1);
+}
+
static void stream_input_consumed(void *ctx,
h2_bucket_beam *beam, apr_off_t length)
{
@@ -337,18 +344,18 @@ int h2_mplx_shutdown(h2_mplx *m)
return max_stream_started;
}
-static void input_consumed_signal(h2_mplx *m, h2_stream *stream)
+static int input_consumed_signal(h2_mplx *m, h2_stream *stream)
{
- if (stream->input && stream->started) {
- h2_beam_send(stream->input, NULL, 0); /* trigger updates */
+ if (stream->input) {
+ return h2_beam_report_consumption(stream->input);
}
+ return 0;
}
static int output_consumed_signal(h2_mplx *m, h2_task *task)
{
- if (task->output.beam && task->worker_started && task->assigned) {
- /* trigger updates */
- h2_beam_send(task->output.beam, NULL, APR_NONBLOCK_READ);
+ if (task->output.beam) {
+ return h2_beam_report_consumption(task->output.beam);
}
return 0;
}
@@ -438,7 +445,7 @@ static void stream_done(h2_mplx *m, h2_s
h2_stream_cleanup(stream);
m->tx_handles_reserved += h2_beam_get_files_beamed(stream->input);
- h2_beam_on_consumed(stream->input, NULL, NULL);
+ h2_beam_on_consumed(stream->input, NULL, NULL, NULL);
/* Let anyone blocked reading know that there is no more to come */
h2_beam_abort(stream->input);
/* Remove mutex after, so that abort still finds cond to signal */
@@ -711,7 +718,7 @@ static apr_status_t out_open(h2_mplx *m,
"h2_mplx(%s): out open", task->id);
}
- h2_beam_on_consumed(stream->output, stream_output_consumed, task);
+ h2_beam_on_consumed(stream->output, NULL, stream_output_consumed, task);
h2_beam_on_produced(stream->output, output_produced, m);
beamed_count = h2_beam_get_files_beamed(stream->output);
if (m->tx_handles_reserved >= beamed_count) {
@@ -785,7 +792,7 @@ apr_status_t h2_mplx_out_trywait(h2_mplx
if (m->aborted) {
status = APR_ECONNABORTED;
}
- else if (!h2_iq_empty(m->readyq)) {
+ else if (apr_atomic_read32(&m->event_pending) > 0) {
status = APR_SUCCESS;
}
else {
@@ -809,6 +816,7 @@ static void have_out_data_for(h2_mplx *m
ap_assert(m);
ap_assert(stream);
h2_iq_append(m->readyq, stream->id);
+ apr_atomic_set32(&m->event_pending, 1);
if (m->added_output) {
apr_thread_cond_signal(m->added_output);
}
@@ -847,6 +855,7 @@ apr_status_t h2_mplx_process(h2_mplx *m,
else {
h2_ihash_add(m->streams, stream);
if (h2_stream_is_ready(stream)) {
+ apr_atomic_set32(&m->event_pending, 1);
h2_iq_append(m->readyq, stream->id);
}
else {
@@ -912,7 +921,8 @@ static h2_task *next_stream_task(h2_mplx
}
h2_beam_timeout_set(stream->input, m->stream_timeout);
- h2_beam_on_consumed(stream->input, stream_input_consumed, m);
+ h2_beam_on_consumed(stream->input, stream_input_ev,
+ stream_input_consumed, m);
h2_beam_on_file_beam(stream->input, can_beam_file, m);
h2_beam_mutex_set(stream->input, beam_enter, task->cond, m);
@@ -1027,7 +1037,7 @@ static void task_done(h2_mplx *m, h2_tas
task->id);
/* more data will not arrive, resume the stream */
have_out_data_for(m, stream, 0);
- h2_beam_on_consumed(stream->output, NULL, NULL);
+ h2_beam_on_consumed(stream->output, NULL, NULL, NULL);
h2_beam_mutex_set(stream->output, NULL, NULL, NULL);
}
else {
@@ -1041,7 +1051,7 @@ static void task_done(h2_mplx *m, h2_tas
* called from a worker thread and freeing memory pools
* is only safe in the only thread using it (and its
* parent pool / allocator) */
- h2_beam_on_consumed(stream->output, NULL, NULL);
+ h2_beam_on_consumed(stream->output, NULL, NULL, NULL);
h2_beam_mutex_set(stream->output, NULL, NULL, NULL);
h2_ihash_remove(m->shold, stream->id);
h2_ihash_add(m->spurge, stream);
@@ -1351,7 +1361,12 @@ void h2_mplx_req_engine_done(h2_req_engi
* mplx master events dispatching
******************************************************************************/
-static int update_window(void *ctx, void *val)
+int h2_mplx_has_master_events(h2_mplx *m)
+{
+ return apr_atomic_read32(&m->event_pending) > 0;
+}
+
+static int report_consumption_iter(void *ctx, void *val)
{
input_consumed_signal(ctx, val);
return 1;
@@ -1367,25 +1382,29 @@ apr_status_t h2_mplx_dispatch_master_eve
h2_stream *stream;
size_t i, n;
+ if (!h2_mplx_has_master_events(m)) {
+ return APR_EAGAIN;
+ }
+
if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, m->c,
- "h2_mplx(%ld): dispatch events", m->id);
-
+ "h2_mplx(%ld): dispatch events", m->id);
+ apr_atomic_set32(&m->event_pending, 0);
/* update input windows for streams */
- h2_ihash_iter(m->streams, update_window, m);
- if (on_resume && !h2_iq_empty(m->readyq)) {
+ h2_ihash_iter(m->streams, report_consumption_iter, m);
+
+ if (!h2_iq_empty(m->readyq)) {
n = h2_iq_mshift(m->readyq, ids, H2_ALEN(ids));
for (i = 0; i < n; ++i) {
stream = h2_ihash_get(m->streams, ids[i]);
if (stream) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, m->c,
- "h2_mplx(%ld-%d): on_resume",
- m->id, stream->id);
on_resume(on_ctx, stream);
}
}
}
-
+ if (!h2_iq_empty(m->readyq)) {
+ apr_atomic_set32(&m->event_pending, 1);
+ }
leave_mutex(m, acquired);
}
return status;
@@ -1400,6 +1419,7 @@ apr_status_t h2_mplx_keep_active(h2_mplx
h2_stream *s = h2_ihash_get(m->streams, stream_id);
if (s) {
h2_iq_append(m->readyq, stream_id);
+ apr_atomic_set32(&m->event_pending, 1);
}
leave_mutex(m, acquired);
}
Modified: httpd/httpd/branches/trunk-test-integration/modules/http2/h2_mplx.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/trunk-test-integration/modules/http2/h2_mplx.h?rev=1778029&r1=1778028&r2=1778029&view=diff
==============================================================================
--- httpd/httpd/branches/trunk-test-integration/modules/http2/h2_mplx.h (original)
+++ httpd/httpd/branches/trunk-test-integration/modules/http2/h2_mplx.h Mon Jan 9 19:10:05 2017
@@ -67,6 +67,7 @@ struct h2_mplx {
APR_RING_ENTRY(h2_mplx) link;
+ unsigned int event_pending;
unsigned int aborted : 1;
unsigned int need_registration : 1;
@@ -222,6 +223,12 @@ void h2_mplx_set_consumed_cb(h2_mplx *m,
typedef apr_status_t stream_ev_callback(void *ctx, struct h2_stream *stream);
/**
+ * Check if the multiplexer has events for the master connection pending.
+ * @return != 0 iff there are events pending
+ */
+int h2_mplx_has_master_events(h2_mplx *m);
+
+/**
* Dispatch events for the master connection, such as
± @param m the multiplexer
* @param on_resume new output data has arrived for a suspended stream
Modified: httpd/httpd/branches/trunk-test-integration/modules/http2/h2_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/trunk-test-integration/modules/http2/h2_session.c?rev=1778029&r1=1778028&r2=1778029&view=diff
==============================================================================
--- httpd/httpd/branches/trunk-test-integration/modules/http2/h2_session.c (original)
+++ httpd/httpd/branches/trunk-test-integration/modules/http2/h2_session.c Mon Jan 9 19:10:05 2017
@@ -48,6 +48,7 @@
static apr_status_t dispatch_master(h2_session *session);
+static apr_status_t h2_session_read(h2_session *session, int block);
static int h2_session_status_from_apr_status(apr_status_t rv)
{
@@ -240,17 +241,6 @@ static ssize_t send_cb(nghttp2_session *
(void)ngh2;
(void)flags;
- if (h2_conn_io_needs_flush(&session->io)) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c,
- "h2_session(%ld): blocking due to io flush",
- session->id);
- status = h2_conn_io_flush(&session->io);
- if (status != APR_SUCCESS) {
- return h2_session_status_from_apr_status(status);
- }
- return NGHTTP2_ERR_WOULDBLOCK;
- }
-
status = h2_conn_io_write(&session->io, (const char *)data, length);
if (status == APR_SUCCESS) {
return length;
@@ -569,6 +559,16 @@ static int on_frame_recv_cb(nghttp2_sess
return 0;
}
+static int h2_session_continue_data(h2_session *session) {
+ if (h2_mplx_has_master_events(session->mplx)) {
+ return 0;
+ }
+ if (h2_conn_io_needs_flush(&session->io)) {
+ return 0;
+ }
+ return 1;
+}
+
static char immortal_zeros[H2_MAX_PADLEN];
static int on_send_data_cb(nghttp2_session *ngh2,
@@ -589,17 +589,10 @@ static int on_send_data_cb(nghttp2_sessi
(void)ngh2;
(void)source;
- if (h2_conn_io_needs_flush(&session->io)) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c,
- "h2_stream(%ld-%d): blocking due to io flush",
- session->id, stream_id);
- status = h2_conn_io_flush(&session->io);
- if (status != APR_SUCCESS) {
- return h2_session_status_from_apr_status(status);
- }
+ if (!h2_session_continue_data(session)) {
return NGHTTP2_ERR_WOULDBLOCK;
}
-
+
if (frame->data.padlen > H2_MAX_PADLEN) {
return NGHTTP2_ERR_PROTO;
}
@@ -1418,8 +1411,6 @@ static apr_status_t h2_session_send(h2_s
apr_socket_timeout_set(socket, session->s->timeout);
}
- /* This sends one round of frames from every able stream, plus
- * settings etc. if accumulated */
rv = nghttp2_session_send(session->ngh2);
if (socket) {
@@ -2058,7 +2049,11 @@ static apr_status_t dispatch_master(h2_s
status = h2_mplx_dispatch_master_events(session->mplx,
on_stream_resume, session);
- if (status != APR_SUCCESS) {
+ if (status == APR_EAGAIN) {
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, session->c,
+ "h2_session(%ld): no master event available", session->id);
+ }
+ else if (status != APR_SUCCESS) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, session->c,
"h2_session(%ld): dispatch error", session->id);
dispatch_event(session, H2_SESSION_EV_CONN_ERROR,
@@ -2118,6 +2113,14 @@ apr_status_t h2_session_process(h2_sessi
case H2_SESSION_ST_IDLE:
/* make certain, we send everything before we idle */
h2_conn_io_flush(&session->io);
+ /* We trust our connection into the default timeout/keepalive
+ * handling of the core filters/mpm iff:
+ * - keep_sync_until is not set
+ * - we have an async mpm
+ * - we have no open streams to process
+ * - we are not sitting on a Upgrade: request
+ * - we already have seen at least one request
+ */
if (!session->keep_sync_until && async && !session->open_streams
&& !session->r && session->remote.emitted_count) {
if (trace) {
@@ -2126,15 +2129,6 @@ apr_status_t h2_session_process(h2_sessi
"%d streams open", session->id,
session->open_streams);
}
- /* We do not return to the async mpm immediately, since under
- * load, mpms show the tendency to throw keep_alive connections
- * away very rapidly.
- * So, if we are still processing streams, we wait for the
- * normal timeout first and, on timeout, close.
- * If we have no streams, we still wait a short amount of
- * time here for the next frame to arrive, before handing
- * it to keep_alive processing of the mpm.
- */
status = h2_session_read(session, 0);
if (status == APR_SUCCESS) {
@@ -2219,7 +2213,6 @@ apr_status_t h2_session_process(h2_sessi
dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, "error");
}
}
-
break;
case H2_SESSION_ST_BUSY:
@@ -2244,13 +2237,16 @@ apr_status_t h2_session_process(h2_sessi
}
status = dispatch_master(session);
- if (status != APR_SUCCESS) {
+ if (status != APR_SUCCESS && status != APR_EAGAIN) {
break;
}
if (nghttp2_session_want_write(session->ngh2)) {
ap_update_child_status(session->c->sbh, SERVER_BUSY_WRITE, NULL);
status = h2_session_send(session);
+ if (status == APR_SUCCESS) {
+ status = h2_conn_io_flush(&session->io);
+ }
if (status != APR_SUCCESS) {
dispatch_event(session, H2_SESSION_EV_CONN_ERROR,
H2_ERR_INTERNAL_ERROR, "writing");
Modified: httpd/httpd/branches/trunk-test-integration/modules/http2/h2_stream.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/trunk-test-integration/modules/http2/h2_stream.c?rev=1778029&r1=1778028&r2=1778029&view=diff
==============================================================================
--- httpd/httpd/branches/trunk-test-integration/modules/http2/h2_stream.c (original)
+++ httpd/httpd/branches/trunk-test-integration/modules/http2/h2_stream.c Mon Jan 9 19:10:05 2017
@@ -481,6 +481,7 @@ apr_status_t h2_stream_close_input(h2_st
APR_BRIGADE_INSERT_TAIL(tmp, b);
status = h2_beam_send(stream->input, tmp, APR_BLOCK_READ);
apr_brigade_destroy(tmp);
+ h2_beam_close(stream->input);
return status;
}
Modified: httpd/httpd/branches/trunk-test-integration/modules/http2/h2_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/trunk-test-integration/modules/http2/h2_version.h?rev=1778029&r1=1778028&r2=1778029&view=diff
==============================================================================
--- httpd/httpd/branches/trunk-test-integration/modules/http2/h2_version.h (original)
+++ httpd/httpd/branches/trunk-test-integration/modules/http2/h2_version.h Mon Jan 9 19:10:05 2017
@@ -26,7 +26,7 @@
* @macro
* Version number of the http2 module as c string
*/
-#define MOD_HTTP2_VERSION "1.8.7-DEV"
+#define MOD_HTTP2_VERSION "1.8.8-DEV"
/**
* @macro
@@ -34,7 +34,7 @@
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
-#define MOD_HTTP2_VERSION_NUM 0x010807
+#define MOD_HTTP2_VERSION_NUM 0x010808
#endif /* mod_h2_h2_version_h */
Modified: httpd/httpd/branches/trunk-test-integration/server/listen.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/trunk-test-integration/server/listen.c?rev=1778029&r1=1778028&r2=1778029&view=diff
==============================================================================
--- httpd/httpd/branches/trunk-test-integration/server/listen.c (original)
+++ httpd/httpd/branches/trunk-test-integration/server/listen.c Mon Jan 9 19:10:05 2017
@@ -146,7 +146,7 @@ static apr_status_t make_sock(apr_pool_t
#endif
#if defined(SO_REUSEPORT)
- if (ap_have_so_reuseport) {
+ if (ap_have_so_reuseport && ap_listencbratio > 0) {
int thesock;
apr_os_sock_get(&thesock, s);
if (setsockopt(thesock, SOL_SOCKET, SO_REUSEPORT,