From: Stefan Eissing Date: Sun, 19 Mar 2017 10:31:48 +0000 (+0000) Subject: On the trunk: X-Git-Tag: 2.5.0-alpha~545 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d645af686df80564a0144a6e0f98d65b748855f1;p=thirdparty%2Fapache%2Fhttpd.git On the trunk: mod_http2: ripped out H2SessionExtraFiles directive, removed super special sender pool handling in bucket beams. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1787604 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index bf9f760a1eb..ad2dbdbac2f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_http2: obsoleted option H2SessionExtraFiles, will be ignored and + just log a warning. [Stefan Eissing] + *) mod_autoindex: Add IndexOptions UseOldDateFormat to allow the date format from 2.2 in the Last Modified column. PR60846. [Hank Ibell ] diff --git a/docs/manual/mod/mod_http2.xml b/docs/manual/mod/mod_http2.xml index 63bcf9f74ba..1f4b7e5de3f 100644 --- a/docs/manual/mod/mod_http2.xml +++ b/docs/manual/mod/mod_http2.xml @@ -138,17 +138,6 @@ Protocols h2 h2c http/1.1 the connection will buffer this amount of data and then suspend the H2Worker.

-

- If you serve a lot of static files, H2SessionExtraFiles - is of interest. This tells the server how many file handles per - HTTP/2 connection it is allowed to waste for better performance. Because - when a request produces a static file as the response, the file handle - gets passed around and is buffered and not the file contents. That allows - to serve many large files without wasting memory or copying data - unnecessarily. However file handles are a limited resource for a process, - and if too many are used this way, requests may fail under load as - the amount of open handles has been exceeded. -

Multiple Hosts and Misdirected Requests @@ -680,47 +669,6 @@ H2MaxWorkerIdleSeconds 20 - - H2SessionExtraFiles - Number of Extra File Handles - H2SessionExtraFiles n - - server config - virtual host - - -

- This directive sets maximum number of extra file handles - a HTTP/2 session is allowed to use. A file handle is counted as - extra when it is transferred from a h2 worker thread to - the main HTTP/2 connection handling. This commonly happens when - serving static files. -

- Depending on the processing model configured on the server, the - number of connections times number of active streams may exceed - the number of file handles for the process. On the other hand, - converting every file into memory bytes early results in too - many buffer writes. This option helps to mitigate that. -

- The number of file handles used by a server process is then in - the order of: -

-
-                (h2_connections * extra_files) + (h2_max_worker)
-            
- Example - -H2SessionExtraFiles 10 - - -

- If nothing is configured, the module tries to make a conservative - guess how many files are safe to use. This depends largely on the - MPM chosen. -

-
-
- H2SerializeHeaders Serialize Request/Response Processing Switch diff --git a/modules/http2/h2_bucket_beam.c b/modules/http2/h2_bucket_beam.c index 53cc36f46fa..16f0a049d79 100644 --- a/modules/http2/h2_bucket_beam.c +++ b/modules/http2/h2_bucket_beam.c @@ -484,16 +484,14 @@ static apr_status_t beam_send_cleanup(void *data) static void beam_set_send_pool(h2_bucket_beam *beam, apr_pool_t *pool) { - if (beam->send_pool == pool || - (beam->send_pool && pool - && apr_pool_is_ancestor(beam->send_pool, pool))) { - /* when sender is same or sub-pool of existing, stick - * to the the pool we already have. */ - return; + if (beam->send_pool != pool) { + if (beam->send_pool && beam->send_pool != beam->pool) { + pool_kill(beam, beam->send_pool, beam_send_cleanup); + beam_send_cleanup(beam); + } + beam->send_pool = pool; + pool_register(beam, beam->send_pool, beam_send_cleanup); } - pool_kill(beam, beam->send_pool, beam_send_cleanup); - beam->send_pool = pool; - pool_register(beam, beam->send_pool, beam_send_cleanup); } static apr_status_t beam_cleanup(void *data) @@ -893,10 +891,8 @@ apr_status_t h2_beam_send(h2_bucket_beam *beam, /* Called from the sender thread to add buckets to the beam */ if (enter_yellow(beam, &bl) == APR_SUCCESS) { + ap_assert(beam->send_pool); r_purge_sent(beam); - if (sender_bb && !beam->send_pool) { - beam_set_send_pool(beam, sender_bb->p); - } if (beam->aborted) { move_to_hold(beam, sender_bb); diff --git a/modules/http2/h2_config.c b/modules/http2/h2_config.c index 0adc5528521..66e61558a31 100644 --- a/modules/http2/h2_config.c +++ b/modules/http2/h2_config.c @@ -53,7 +53,6 @@ static h2_config defconf = { -1, /* alt-svc max age */ 0, /* serialize headers */ -1, /* h2 direct mode */ - -1, /* # session extra files */ 1, /* modern TLS only */ -1, /* HTTP/1 Upgrade support */ 1024*1024, /* TLS warmup size */ @@ -88,7 +87,6 @@ static void *h2_config_create(apr_pool_t *pool, conf->alt_svc_max_age = DEF_VAL; conf->serialize_headers = DEF_VAL; conf->h2_direct = DEF_VAL; - conf->session_extra_files = DEF_VAL; conf->modern_tls_only = DEF_VAL; conf->h2_upgrade = DEF_VAL; conf->tls_warmup_size = DEF_VAL; @@ -130,7 +128,6 @@ static void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv) n->alt_svc_max_age = H2_CONFIG_GET(add, base, alt_svc_max_age); n->serialize_headers = H2_CONFIG_GET(add, base, serialize_headers); n->h2_direct = H2_CONFIG_GET(add, base, h2_direct); - n->session_extra_files = H2_CONFIG_GET(add, base, session_extra_files); n->modern_tls_only = H2_CONFIG_GET(add, base, modern_tls_only); n->h2_upgrade = H2_CONFIG_GET(add, base, h2_upgrade); n->tls_warmup_size = H2_CONFIG_GET(add, base, tls_warmup_size); @@ -194,8 +191,6 @@ apr_int64_t h2_config_geti64(const h2_config *conf, h2_config_var_t var) return H2_CONFIG_GET(conf, &defconf, h2_upgrade); case H2_CONF_DIRECT: return H2_CONFIG_GET(conf, &defconf, h2_direct); - case H2_CONF_SESSION_FILES: - return H2_CONFIG_GET(conf, &defconf, session_extra_files); case H2_CONF_TLS_WARMUP_SIZE: return H2_CONFIG_GET(conf, &defconf, tls_warmup_size); case H2_CONF_TLS_COOLDOWN_SECS: @@ -336,13 +331,11 @@ static const char *h2_conf_set_alt_svc_max_age(cmd_parms *parms, static const char *h2_conf_set_session_extra_files(cmd_parms *parms, void *arg, const char *value) { - h2_config *cfg = (h2_config *)h2_config_sget(parms->server); - apr_int64_t max = (int)apr_atoi64(value); - if (max < 0) { - return "value must be a non-negative number"; - } - cfg->session_extra_files = (int)max; + /* deprecated, ignore */ (void)arg; + (void)value; + ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, parms->pool, /* NO LOGNO */ + "H2SessionExtraFiles is obsolete and will be ignored"); return NULL; } @@ -638,7 +631,7 @@ const command_rec h2_cmds[] = { AP_INIT_TAKE1("H2Direct", h2_conf_set_direct, NULL, RSRC_CONF, "on to enable direct HTTP/2 mode"), AP_INIT_TAKE1("H2SessionExtraFiles", h2_conf_set_session_extra_files, NULL, - RSRC_CONF, "number of extra file a session might keep open"), + RSRC_CONF, "number of extra file a session might keep open (obsolete)"), AP_INIT_TAKE1("H2TLSWarmUpSize", h2_conf_set_tls_warmup_size, NULL, RSRC_CONF, "number of bytes on TLS connection before doing max writes"), AP_INIT_TAKE1("H2TLSCoolDownSecs", h2_conf_set_tls_cooldown_secs, NULL, diff --git a/modules/http2/h2_config.h b/modules/http2/h2_config.h index 1f2fe309d0a..9b38b8660cb 100644 --- a/modules/http2/h2_config.h +++ b/modules/http2/h2_config.h @@ -33,7 +33,6 @@ typedef enum { H2_CONF_ALT_SVC_MAX_AGE, H2_CONF_SER_HEADERS, H2_CONF_DIRECT, - H2_CONF_SESSION_FILES, H2_CONF_MODERN_TLS_ONLY, H2_CONF_UPGRADE, H2_CONF_TLS_WARMUP_SIZE, @@ -67,7 +66,6 @@ typedef struct h2_config { int serialize_headers; /* Use serialized HTTP/1.1 headers for processing, better compatibility */ int h2_direct; /* if mod_h2 is active directly */ - int session_extra_files; /* # of extra files a session may keep open */ int modern_tls_only; /* Accept only modern TLS in HTTP/2 connections */ int h2_upgrade; /* Allow HTTP/1 upgrade to h2/h2c */ apr_int64_t tls_warmup_size; /* Amount of TLS data to send before going full write size */ diff --git a/modules/http2/h2_conn.c b/modules/http2/h2_conn.c index 220387db2b9..4576a2c548f 100644 --- a/modules/http2/h2_conn.c +++ b/modules/http2/h2_conn.c @@ -103,7 +103,7 @@ apr_status_t h2_conn_child_init(apr_pool_t *pool, server_rec *s) { const h2_config *config = h2_config_sget(s); apr_status_t status = APR_SUCCESS; - int minw, maxw, max_tx_handles, n; + int minw, maxw; int max_threads_per_child = 0; int idle_secs = 0; @@ -129,28 +129,10 @@ apr_status_t h2_conn_child_init(apr_pool_t *pool, server_rec *s) maxw = minw; } - /* How many file handles is it safe to use for transfer - * to the master connection to be streamed out? - * Is there a portable APR rlimit on NOFILES? Have not - * found it. And if, how many of those would we set aside? - * This leads all into a process wide handle allocation strategy - * which ultimately would limit the number of accepted connections - * with the assumption of implicitly reserving n handles for every - * connection and requiring modules with excessive needs to allocate - * from a central pool. - */ - n = h2_config_geti(config, H2_CONF_SESSION_FILES); - if (n < 0) { - max_tx_handles = maxw * 2; - } - else { - max_tx_handles = maxw * n; - } - ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s, - "h2_workers: min=%d max=%d, mthrpchild=%d, tx_files=%d", - minw, maxw, max_threads_per_child, max_tx_handles); - workers = h2_workers_create(s, pool, minw, maxw, max_tx_handles); + "h2_workers: min=%d max=%d, mthrpchild=%d", + minw, maxw, max_threads_per_child); + workers = h2_workers_create(s, pool, minw, maxw); idle_secs = h2_config_geti(config, H2_CONF_MAX_WORKER_IDLE_SECS); h2_workers_set_max_idle_secs(workers, idle_secs); @@ -317,6 +299,8 @@ conn_rec *h2_slave_create(conn_rec *master, int slave_id, apr_pool_t *parent) c->bucket_alloc = apr_bucket_alloc_create(pool); c->data_in_input_filters = 0; c->data_in_output_filters = 0; + /* prevent mpm_event from making wrong assumptions about this connection, + * like e.g. using its socket for an async read check. */ c->clogging_input_filters = 1; c->log = NULL; c->log_id = apr_psprintf(pool, "%ld-%d", diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c index b8244b0a772..d0a69403720 100644 --- a/modules/http2/h2_mplx.c +++ b/modules/http2/h2_mplx.c @@ -140,41 +140,9 @@ static void stream_input_consumed(void *ctx, } } -static int can_beam_file(void *ctx, h2_bucket_beam *beam, apr_file_t *file) +static int can_always_beam_file(void *ctx, h2_bucket_beam *beam, apr_file_t *file) { - h2_mplx *m = ctx; - if (m->tx_handles_reserved > 0) { - --m->tx_handles_reserved; - ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, m->c, - "h2_stream(%ld-%d,%s): beaming file, tx_avail %d", - m->id, beam->id, beam->tag, m->tx_handles_reserved); - return 1; - } - ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, m->c, - "h2_stream(%ld-%d,%s): can_beam_file denied", - m->id, beam->id, beam->tag); - return 0; -} - -static void check_tx_reservation(h2_mplx *m) -{ - if (m->tx_handles_reserved <= 0) { - m->tx_handles_reserved += h2_workers_tx_reserve(m->workers, - H2MIN(m->tx_chunk_size, h2_ihash_count(m->streams))); - } -} - -static void check_tx_free(h2_mplx *m) -{ - if (m->tx_handles_reserved > m->tx_chunk_size) { - apr_size_t count = m->tx_handles_reserved - m->tx_chunk_size; - m->tx_handles_reserved = m->tx_chunk_size; - h2_workers_tx_free(m->workers, count); - } - else if (m->tx_handles_reserved && h2_ihash_empty(m->streams)) { - h2_workers_tx_free(m->workers, m->tx_handles_reserved); - m->tx_handles_reserved = 0; - } + return 1; } static void stream_joined(h2_mplx *m, h2_stream *stream) @@ -183,10 +151,6 @@ static void stream_joined(h2_mplx *m, h2_stream *stream) h2_ihash_remove(m->shold, stream->id); h2_ihash_add(m->spurge, stream); - if (stream->input) { - m->tx_handles_reserved += h2_beam_get_files_beamed(stream->input); - } - m->tx_handles_reserved += h2_beam_get_files_beamed(stream->output); } static void stream_cleanup(h2_mplx *m, h2_stream *stream) @@ -297,9 +261,6 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr_pool_t *parent, m->last_limit_change = m->last_idle_block = apr_time_now(); m->limit_change_interval = apr_time_from_msec(200); - m->tx_handles_reserved = 0; - m->tx_chunk_size = 4; - m->spare_slaves = apr_array_make(m->pool, 10, sizeof(conn_rec*)); m->ngn_shed = h2_ngn_shed_create(m->pool, m->c, m->max_streams, @@ -402,7 +363,6 @@ static void purge_streams(h2_mplx *m) while (!h2_ihash_iter(m->spurge, stream_destroy_iter, m)) { /* repeat until empty */ } - check_tx_free(m); } } @@ -533,10 +493,6 @@ void h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait) m->id, (int)h2_ihash_count(m->shold)); h2_ihash_iter(m->shold, unexpected_stream_iter, m); } - /*ap_assert(h2_ihash_empty(m->shold));*/ - - /* 5. return any file resources allocated */ - check_tx_free(m); leave_mutex(m, acquired); @@ -593,7 +549,6 @@ static apr_status_t out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam) { apr_status_t status = APR_SUCCESS; h2_stream *stream = h2_ihash_get(m->streams, stream_id); - apr_size_t beamed_count; if (!stream || !stream->task) { return APR_ECONNABORTED; @@ -609,15 +564,8 @@ static apr_status_t out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam) h2_beam_on_consumed(stream->output, NULL, stream_output_consumed, stream); 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) { - m->tx_handles_reserved -= beamed_count; - } - else { - m->tx_handles_reserved = 0; - } if (!stream->task->output.copy_files) { - h2_beam_on_file_beam(stream->output, can_beam_file, m); + h2_beam_on_file_beam(stream->output, can_always_beam_file, m); } /* time to protect the beam against multi-threaded use */ @@ -625,7 +573,6 @@ static apr_status_t out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam) /* we might see some file buckets in the output, see * if we have enough handles reserved. */ - check_tx_reservation(m); check_data_for(m, stream->id); return status; } @@ -778,7 +725,6 @@ static h2_task *next_stream_task(h2_mplx *m) stream = h2_ihash_get(m->streams, sid); if (stream) { conn_rec *slave, **pslave; - int new_conn = 0; pslave = (conn_rec **)apr_array_pop(m->spare_slaves); if (pslave) { @@ -786,7 +732,6 @@ static h2_task *next_stream_task(h2_mplx *m) } else { slave = h2_slave_create(m->c, stream->id, m->pool); - new_conn = 1; } slave->sbh = m->c->sbh; @@ -796,9 +741,8 @@ static h2_task *next_stream_task(h2_mplx *m) m->c->keepalives++; apr_table_setn(slave->notes, H2_TASK_ID_NOTE, stream->task->id); - if (new_conn) { - h2_slave_run_pre_connection(slave, ap_get_conn_socket(slave)); - } + h2_slave_run_pre_connection(slave, ap_get_conn_socket(slave)); + if (sid > m->max_stream_started) { m->max_stream_started = sid; } @@ -806,7 +750,7 @@ static h2_task *next_stream_task(h2_mplx *m) if (stream->input) { 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_on_file_beam(stream->input, can_always_beam_file, m); h2_beam_mutex_enable(stream->input); } diff --git a/modules/http2/h2_mplx.h b/modules/http2/h2_mplx.h index 992c24cbe4e..db40037aee6 100644 --- a/modules/http2/h2_mplx.h +++ b/modules/http2/h2_mplx.h @@ -101,8 +101,6 @@ struct h2_mplx { apr_array_header_t *spare_slaves; /* spare slave connections */ struct h2_workers *workers; - int tx_handles_reserved; - int tx_chunk_size; h2_mplx_consumed_cb *input_consumed; void *input_consumed_ctx; diff --git a/modules/http2/h2_workers.c b/modules/http2/h2_workers.c index cbaf1bcb36d..e0f4308816c 100644 --- a/modules/http2/h2_workers.c +++ b/modules/http2/h2_workers.c @@ -258,8 +258,7 @@ static apr_status_t workers_pool_cleanup(void *data) } h2_workers *h2_workers_create(server_rec *s, apr_pool_t *server_pool, - int min_workers, int max_workers, - apr_size_t max_tx_handles) + int min_workers, int max_workers) { apr_status_t status; h2_workers *workers; @@ -283,9 +282,6 @@ h2_workers *h2_workers_create(server_rec *s, apr_pool_t *server_pool, workers->max_workers = max_workers; workers->max_idle_secs = 10; - workers->max_tx_handles = max_tx_handles; - workers->spare_tx_handles = workers->max_tx_handles; - apr_threadattr_create(&workers->thread_attr, workers->pool); if (ap_thread_stacksize != 0) { apr_threadattr_stacksize_set(workers->thread_attr, @@ -305,11 +301,6 @@ h2_workers *h2_workers_create(server_rec *s, apr_pool_t *server_pool, if (status == APR_SUCCESS) { status = apr_thread_cond_create(&workers->mplx_added, workers->pool); } - if (status == APR_SUCCESS) { - status = apr_thread_mutex_create(&workers->tx_lock, - APR_THREAD_MUTEX_DEFAULT, - workers->pool); - } if (status == APR_SUCCESS) { status = h2_workers_start(workers); } @@ -324,31 +315,33 @@ h2_workers *h2_workers_create(server_rec *s, apr_pool_t *server_pool, apr_status_t h2_workers_register(h2_workers *workers, struct h2_mplx *m) { apr_status_t status = apr_thread_mutex_lock(workers->lock); - if (status == APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_TRACE3, status, workers->s, - "h2_workers: register mplx(%ld), idle=%d", - m->id, workers->idle_workers); - if (in_list(workers, m)) { - status = APR_EAGAIN; - } - else { - H2_MPLX_LIST_INSERT_TAIL(&workers->mplxs, m); - ++workers->mplx_count; - status = APR_SUCCESS; - } - - if (workers->idle_workers > 0) { - apr_thread_cond_signal(workers->mplx_added); - } - else if (status == APR_SUCCESS - && workers->worker_count < workers->max_workers) { - ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, workers->s, - "h2_workers: got %d worker, adding 1", - workers->worker_count); - add_worker(workers); - } - apr_thread_mutex_unlock(workers->lock); + if (status != APR_SUCCESS) { + return status; + } + + ap_log_error(APLOG_MARK, APLOG_TRACE3, status, workers->s, + "h2_workers: register mplx(%ld), idle=%d", + m->id, workers->idle_workers); + if (in_list(workers, m)) { + status = APR_EAGAIN; } + else { + H2_MPLX_LIST_INSERT_TAIL(&workers->mplxs, m); + ++workers->mplx_count; + status = APR_SUCCESS; + } + + if (workers->idle_workers > 0) { + apr_thread_cond_signal(workers->mplx_added); + } + else if (status == APR_SUCCESS + && workers->worker_count < workers->max_workers) { + ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, workers->s, + "h2_workers: got %d worker, adding 1", + workers->worker_count); + add_worker(workers); + } + apr_thread_mutex_unlock(workers->lock); return status; } @@ -377,32 +370,3 @@ void h2_workers_set_max_idle_secs(h2_workers *workers, int idle_secs) workers->max_idle_secs = idle_secs; } -apr_size_t h2_workers_tx_reserve(h2_workers *workers, apr_size_t count) -{ - apr_status_t status = apr_thread_mutex_lock(workers->tx_lock); - if (status == APR_SUCCESS) { - count = H2MIN(workers->spare_tx_handles, count); - workers->spare_tx_handles -= count; - ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, workers->s, - "h2_workers: reserved %d tx handles, %d/%d left", - (int)count, (int)workers->spare_tx_handles, - (int)workers->max_tx_handles); - apr_thread_mutex_unlock(workers->tx_lock); - return count; - } - return 0; -} - -void h2_workers_tx_free(h2_workers *workers, apr_size_t count) -{ - apr_status_t status = apr_thread_mutex_lock(workers->tx_lock); - if (status == APR_SUCCESS) { - workers->spare_tx_handles += count; - ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, workers->s, - "h2_workers: freed %d tx handles, %d/%d left", - (int)count, (int)workers->spare_tx_handles, - (int)workers->max_tx_handles); - apr_thread_mutex_unlock(workers->tx_lock); - } -} - diff --git a/modules/http2/h2_workers.h b/modules/http2/h2_workers.h index b96cff3613d..dee733baebb 100644 --- a/modules/http2/h2_workers.h +++ b/modules/http2/h2_workers.h @@ -41,9 +41,6 @@ struct h2_workers { int idle_workers; int max_idle_secs; - apr_size_t max_tx_handles; - apr_size_t spare_tx_handles; - unsigned int aborted : 1; apr_threadattr_t *thread_attr; @@ -55,8 +52,6 @@ struct h2_workers { struct apr_thread_mutex_t *lock; struct apr_thread_cond_t *mplx_added; - - struct apr_thread_mutex_t *tx_lock; }; @@ -64,8 +59,7 @@ struct h2_workers { * threads. */ h2_workers *h2_workers_create(server_rec *s, apr_pool_t *pool, - int min_size, int max_size, - apr_size_t max_tx_handles); + int min_size, int max_size); /** * Registers a h2_mplx for task scheduling. If this h2_mplx runs