From: Stefan Eissing Date: Fri, 29 Jan 2016 14:17:12 +0000 (+0000) Subject: removed experimental++ H2* timeout directives, instead using normal Timeout and KeepA... X-Git-Tag: 2.5.0-alpha~2251 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c80274fdca567cee2b7d93b92f5b5106bc8c5dab;p=thirdparty%2Fapache%2Fhttpd.git removed experimental++ H2* timeout directives, instead using normal Timeout and KeepAliveTimeout only git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1727590 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/docs/manual/mod/mod_http2.xml b/docs/manual/mod/mod_http2.xml index e16f158e125..ad1a887733f 100644 --- a/docs/manual/mod/mod_http2.xml +++ b/docs/manual/mod/mod_http2.xml @@ -766,99 +766,4 @@ H2PushPriority text/css interleaved # weight 256 default - - H2Timeout - Timeout (in seconds) for HTTP/2 connections - H2Timeout seconds - H2Timeout 5 - - server config - virtual host - - Available in version 2.4.19 and later. - - -

- This directive sets the timeout for read/write operations on - connections where HTTP/2 is negotiated. This can be used server wide or for specific - VirtualHosts. -

-

- This directive is similar to the - Timeout, but - applies only to HTTP/2 connections. -

-

- A value of 0 enforces no timeout. -

-
-
- - - H2KeepAliveTimeout - Timeout (in seconds) for idle HTTP/2 connections - H2KeepAliveTimeout seconds - - server config - virtual host - - Available in version 2.4.19 and later. - - -

- This directive sets the timeout for read/write operations on - idle connections where HTTP/2 is negotiated. This can be used server wide or for specific - VirtualHosts. -

-

- This directive is similar to the - KeepAliveTimeout, but - applies only to HTTP/2 connections. A HTTP/2 connection is considered - idle when no streams are open, e.g. no requests are ongoing. -

-

- By default, for non-async MPMs (prefork, worker) the keepalive timeout - will be the same as H2Timeout. For async MPMs, the keepalive handling for - HTTP/1 connections applies as no special action is taken. -

-
-
- - - H2StreamTimeout - Timeout (in seconds) for idle HTTP/2 connections - H2StreamTimeout seconds - H2StreamTimeout 0 - - server config - virtual host - - Available in version 2.4.19 and later. - - -

- This directive sets the timeout for read/write operations on - HTTP/2 streams, e.g. individual requests. This can be used server wide or for specific - VirtualHosts. -

-

- Due to the nature of HTTP/2, which sends multiple requests over a single - connection and has priority scheduling, individual streams might not - see input for much longer times than HTTP/1.1 requests would. -

-

- A value of 0 enforces no timeout, so could wait on chances to receive - input or write data indefinitely. This expose a server to - risks of thread exhaustion. -

-

- Depending on your handling of pushed streams, - priorities and general responsiveness, a site might need to increase - this value. For example, if you PUSH a large resource before - the requested one, the initial stream will not write until the - pushed resource is fully sent. -

-
-
- diff --git a/modules/http2/h2_config.c b/modules/http2/h2_config.c index 31307e641f1..dfab2d79df7 100644 --- a/modules/http2/h2_config.c +++ b/modules/http2/h2_config.c @@ -59,9 +59,6 @@ static h2_config defconf = { 1, /* TLS cooldown secs */ 1, /* HTTP/2 server push enabled */ NULL, /* map of content-type to priorities */ - -1, /* connection timeout */ - -1, /* keepalive timeout */ - 0, /* stream timeout */ 256, /* push diary size */ }; @@ -96,9 +93,6 @@ static void *h2_config_create(apr_pool_t *pool, conf->tls_cooldown_secs = DEF_VAL; conf->h2_push = DEF_VAL; conf->priorities = NULL; - conf->h2_timeout = DEF_VAL; - conf->h2_keepalive = DEF_VAL; - conf->h2_stream_timeout = DEF_VAL; conf->push_diary_size = DEF_VAL; return conf; @@ -145,9 +139,6 @@ void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv) else { n->priorities = add->priorities? add->priorities : base->priorities; } - n->h2_timeout = H2_CONFIG_GET(add, base, h2_timeout); - n->h2_keepalive = H2_CONFIG_GET(add, base, h2_keepalive); - n->h2_stream_timeout = H2_CONFIG_GET(add, base, h2_stream_timeout); n->push_diary_size = H2_CONFIG_GET(add, base, push_diary_size); return n; @@ -191,12 +182,6 @@ apr_int64_t h2_config_geti64(const h2_config *conf, h2_config_var_t var) return H2_CONFIG_GET(conf, &defconf, tls_cooldown_secs); case H2_CONF_PUSH: return H2_CONFIG_GET(conf, &defconf, h2_push); - case H2_CONF_TIMEOUT_SECS: - return H2_CONFIG_GET(conf, &defconf, h2_timeout); - case H2_CONF_KEEPALIVE_SECS: - return H2_CONFIG_GET(conf, &defconf, h2_keepalive); - case H2_CONF_STREAM_TIMEOUT_SECS: - return H2_CONFIG_GET(conf, &defconf, h2_stream_timeout); case H2_CONF_PUSH_DIARY_SIZE: return H2_CONFIG_GET(conf, &defconf, push_diary_size); default: @@ -496,42 +481,6 @@ static const char *h2_conf_set_tls_cooldown_secs(cmd_parms *parms, return NULL; } -static const char *h2_conf_set_timeout(cmd_parms *parms, - void *arg, const char *value) -{ - h2_config *cfg = (h2_config *)h2_config_sget(parms->server); - (void)arg; - cfg->h2_timeout = (int)apr_atoi64(value); - if (cfg->h2_timeout < 0) { - return "value must be >= 0"; - } - return NULL; -} - -static const char *h2_conf_set_keepalive(cmd_parms *parms, - void *arg, const char *value) -{ - h2_config *cfg = (h2_config *)h2_config_sget(parms->server); - (void)arg; - cfg->h2_keepalive = (int)apr_atoi64(value); - if (cfg->h2_keepalive < 0) { - return "value must be >= 0"; - } - return NULL; -} - -static const char *h2_conf_set_stream_timeout(cmd_parms *parms, - void *arg, const char *value) -{ - h2_config *cfg = (h2_config *)h2_config_sget(parms->server); - (void)arg; - cfg->h2_stream_timeout = (int)apr_atoi64(value); - if (cfg->h2_stream_timeout < 0) { - return "value must be >= 0"; - } - return NULL; -} - static const char *h2_conf_set_push_diary_size(cmd_parms *parms, void *arg, const char *value) { @@ -587,12 +536,6 @@ const command_rec h2_cmds[] = { RSRC_CONF, "off to disable HTTP/2 server push"), AP_INIT_TAKE23("H2PushPriority", h2_conf_add_push_priority, NULL, RSRC_CONF, "define priority of PUSHed resources per content type"), - AP_INIT_TAKE1("H2Timeout", h2_conf_set_timeout, NULL, - RSRC_CONF, "read/write timeout (seconds) for HTTP/2 connections"), - AP_INIT_TAKE1("H2KeepAliveTimeout", h2_conf_set_keepalive, NULL, - RSRC_CONF, "timeout (seconds) for idle HTTP/2 connections, no streams open"), - AP_INIT_TAKE1("H2StreamTimeout", h2_conf_set_stream_timeout, NULL, - RSRC_CONF, "read/write timeout (seconds) for HTTP/2 streams"), AP_INIT_TAKE1("H2PushDiarySize", h2_conf_set_push_diary_size, NULL, RSRC_CONF, "size of push diary"), AP_END_CMD diff --git a/modules/http2/h2_config.h b/modules/http2/h2_config.h index a40bb83c026..92b222f9f7b 100644 --- a/modules/http2/h2_config.h +++ b/modules/http2/h2_config.h @@ -39,9 +39,6 @@ typedef enum { H2_CONF_TLS_WARMUP_SIZE, H2_CONF_TLS_COOLDOWN_SECS, H2_CONF_PUSH, - H2_CONF_TIMEOUT_SECS, - H2_CONF_KEEPALIVE_SECS, - H2_CONF_STREAM_TIMEOUT_SECS, H2_CONF_PUSH_DIARY_SIZE, } h2_config_var_t; @@ -70,9 +67,6 @@ typedef struct h2_config { int h2_push; /* if HTTP/2 server push is enabled */ struct apr_hash_t *priorities;/* map of content-type to h2_priority records */ - int h2_timeout; /* timeout for http/2 connections */ - int h2_keepalive; /* timeout for idle connections, no streams */ - int h2_stream_timeout; /* timeout for http/2 streams, slave connections */ int push_diary_size; /* # of entries in push diary */ } h2_config; diff --git a/modules/http2/h2_io.c b/modules/http2/h2_io.c index 5a20a7ed0a8..07953d18996 100644 --- a/modules/http2/h2_io.c +++ b/modules/http2/h2_io.c @@ -102,12 +102,13 @@ apr_status_t h2_io_in_shutdown(h2_io *io) } -void h2_io_signal_init(h2_io *io, h2_io_op op, int timeout_secs, apr_thread_cond_t *cond) +void h2_io_signal_init(h2_io *io, h2_io_op op, apr_interval_time_t timeout, + apr_thread_cond_t *cond) { io->timed_op = op; io->timed_cond = cond; - if (timeout_secs > 0) { - io->timeout_at = apr_time_now() + apr_time_from_sec(timeout_secs); + if (timeout > 0) { + io->timeout_at = apr_time_now() + timeout; } else { io->timeout_at = 0; diff --git a/modules/http2/h2_io.h b/modules/http2/h2_io.h index fc09cef6660..acaa56fcb7d 100644 --- a/modules/http2/h2_io.h +++ b/modules/http2/h2_io.h @@ -100,7 +100,7 @@ int h2_io_in_has_eos_for(h2_io *io); int h2_io_out_has_data(h2_io *io); void h2_io_signal(h2_io *io, h2_io_op op); -void h2_io_signal_init(h2_io *io, h2_io_op op, int timeout_secs, +void h2_io_signal_init(h2_io *io, h2_io_op op, apr_interval_time_t timeout, struct apr_thread_cond_t *cond); void h2_io_signal_exit(h2_io *io); apr_status_t h2_io_signal_wait(struct h2_mplx *m, h2_io *io); diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c index 21201852889..b2374da9079 100644 --- a/modules/http2/h2_mplx.c +++ b/modules/http2/h2_mplx.c @@ -129,7 +129,8 @@ static void h2_mplx_destroy(h2_mplx *m) * than protecting a shared h2_session one with an own lock. */ h2_mplx *h2_mplx_create(conn_rec *c, apr_pool_t *parent, - const h2_config *conf, + const h2_config *conf, + apr_interval_time_t stream_timeout, h2_workers *workers) { apr_status_t status = APR_SUCCESS; @@ -164,12 +165,11 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr_pool_t *parent, m->stream_ios = h2_io_set_create(m->pool); m->ready_ios = h2_io_set_create(m->pool); m->stream_max_mem = h2_config_geti(conf, H2_CONF_STREAM_MAX_MEM); + m->stream_timeout = stream_timeout; m->workers = workers; m->tx_handles_reserved = 0; m->tx_chunk_size = 4; - - m->stream_timeout_secs = h2_config_geti(conf, H2_CONF_STREAM_TIMEOUT_SECS); } return m; } @@ -416,7 +416,7 @@ apr_status_t h2_mplx_in_read(h2_mplx *m, apr_read_type_e block, if (io && !io->orphaned) { H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_in_read_pre"); - h2_io_signal_init(io, H2_IO_READ, m->stream_timeout_secs, iowait); + h2_io_signal_init(io, H2_IO_READ, m->stream_timeout, iowait); status = h2_io_in_read(io, bb, -1, trailers); while (APR_STATUS_IS_EAGAIN(status) && !is_aborted(m, &status) @@ -657,7 +657,7 @@ static apr_status_t out_write(h2_mplx *m, h2_io *io, &m->tx_handles_reserved); /* Wait for data to drain until there is room again or * stream timeout expires */ - h2_io_signal_init(io, H2_IO_WRITE, m->stream_timeout_secs, iowait); + h2_io_signal_init(io, H2_IO_WRITE, m->stream_timeout, iowait); while (status == APR_SUCCESS && !APR_BRIGADE_EMPTY(bb) && iowait diff --git a/modules/http2/h2_mplx.h b/modules/http2/h2_mplx.h index f3edc513561..4948af920df 100644 --- a/modules/http2/h2_mplx.h +++ b/modules/http2/h2_mplx.h @@ -78,7 +78,7 @@ struct h2_mplx { struct apr_thread_cond_t *join_wait; apr_size_t stream_max_mem; - int stream_timeout_secs; + apr_interval_time_t stream_timeout; apr_pool_t *spare_pool; /* spare pool, ready for next io */ struct h2_workers *workers; @@ -101,6 +101,7 @@ struct h2_mplx { */ h2_mplx *h2_mplx_create(conn_rec *c, apr_pool_t *master, const struct h2_config *conf, + apr_interval_time_t stream_timeout, struct h2_workers *workers); /** diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c index 1d88904dfa7..b22e5153133 100644 --- a/modules/http2/h2_session.c +++ b/modules/http2/h2_session.c @@ -817,15 +817,7 @@ static h2_session *h2_session_create_int(conn_rec *c, session->max_stream_count = h2_config_geti(session->config, H2_CONF_MAX_STREAMS); session->max_stream_mem = h2_config_geti(session->config, H2_CONF_STREAM_MAX_MEM); - session->timeout_secs = h2_config_geti(session->config, H2_CONF_TIMEOUT_SECS); - if (session->timeout_secs <= 0) { - session->timeout_secs = apr_time_sec(session->s->timeout); - } - session->keepalive_secs = h2_config_geti(session->config, H2_CONF_KEEPALIVE_SECS); - if (session->keepalive_secs <= 0) { - session->keepalive_secs = apr_time_sec(session->s->keep_alive_timeout); - } - + status = apr_thread_cond_create(&session->iowait, session->pool); if (status != APR_SUCCESS) { return NULL; @@ -834,7 +826,8 @@ static h2_session *h2_session_create_int(conn_rec *c, session->streams = h2_stream_set_create(session->pool, session->max_stream_count); session->workers = workers; - session->mplx = h2_mplx_create(c, session->pool, session->config, workers); + session->mplx = h2_mplx_create(c, session->pool, session->config, + session->s->timeout, workers); h2_mplx_set_consumed_cb(session->mplx, update_window, session); @@ -898,12 +891,9 @@ static h2_session *h2_session_create_int(conn_rec *c, if (APLOGcdebug(c)) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(03200) - "session(%ld) created, timeout=%d, keepalive_timeout=%d, " - "max_streams=%d, stream_mem=%d, push_diary(type=%d,N=%d)", - session->id, session->timeout_secs, session->keepalive_secs, - (int)session->max_stream_count, (int)session->max_stream_mem, - session->push_diary->dtype, - (int)session->push_diary->N); + "session(%ld) created, max_streams=%d, stream_mem=%d, push_diary(type=%d,N=%d)", + session->id, (int)session->max_stream_count, (int)session->max_stream_mem, + session->push_diary->dtype, (int)session->push_diary->N); } } return session; @@ -1844,7 +1834,7 @@ 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->keepalive_remain = session->keepalive_secs; + session->keepalive_until = apr_time_now() + session->s->keep_alive_timeout; } } else if (!h2_stream_set_has_unsubmitted(session->streams) @@ -1853,7 +1843,7 @@ static void h2_session_ev_no_io(h2_session *session, int arg, const char *msg) * new output data from task processing, * switch to blocking reads. */ transit(session, "no io", H2_SESSION_ST_IDLE); - session->keepalive_remain = session->keepalive_secs; + session->keepalive_until = apr_time_now() + session->s->keep_alive_timeout; } else { /* Unable to do blocking reads, as we wait on events from @@ -2062,19 +2052,11 @@ apr_status_t h2_session_process(h2_session *session, int async) dispatch_event(session, H2_SESSION_EV_DATA_READ, 0, NULL); } else if (APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status)) { - if (--session->keepalive_remain <= 0) { + if (apr_time_now() > session->keepalive_until) { dispatch_event(session, H2_SESSION_EV_CONN_TIMEOUT, 0, NULL); } else { status = APR_EAGAIN; - ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, c, - "h2_session(%ld): idle, conn->timeout=%d/%d" - ", conn->keepalive=%d/%d", - session->id, - (int)session->timeout_secs, - (int)apr_time_sec(session->s->timeout), - (int)session->keepalive_secs, - (int)apr_time_sec(session->s->keep_alive_timeout)); goto out; } } @@ -2098,7 +2080,7 @@ apr_status_t h2_session_process(h2_session *session, int async) /* nothing to read */ } else if (APR_STATUS_IS_TIMEUP(status)) { - if (--session->keepalive_remain <= 0) { + if (apr_time_now() > session->keepalive_until) { dispatch_event(session, H2_SESSION_EV_CONN_TIMEOUT, 0, "timeout"); } /* continue keepalive handling */ @@ -2114,7 +2096,7 @@ apr_status_t h2_session_process(h2_session *session, int async) case H2_SESSION_ST_LOCAL_SHUTDOWN: case H2_SESSION_ST_REMOTE_SHUTDOWN: if (nghttp2_session_want_read(session->ngh2)) { - h2_filter_cin_timeout_set(session->cin, session->timeout_secs); + h2_filter_cin_timeout_set(session->cin, session->s->timeout); status = h2_session_read(session, 0, 10); if (status == APR_SUCCESS) { have_read = 1; @@ -2184,8 +2166,7 @@ apr_status_t h2_session_process(h2_session *session, int async) session->start_wait = apr_time_now(); update_child_status(session, SERVER_BUSY_READ, "wait"); } - else if (apr_time_sec(apr_time_now() - session->start_wait) - >= session->timeout_secs) { + else if ((apr_time_now() - session->start_wait) >= session->s->timeout) { /* waited long enough */ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_TIMEUP, c, "h2_session: wait for data"); diff --git a/modules/http2/h2_session.h b/modules/http2/h2_session.h index 02e5e9c63fe..bdf815df1af 100644 --- a/modules/http2/h2_session.h +++ b/modules/http2/h2_session.h @@ -112,10 +112,8 @@ typedef struct h2_session { apr_size_t max_stream_count; /* max number of open streams */ apr_size_t max_stream_mem; /* max buffer memory for a single stream */ - int timeout_secs; /* connection timeout (seconds) */ - int keepalive_secs; /* connection idle timeout (seconds) */ - int keepalive_remain; /* remaining seconds of keepalive */ apr_time_t start_wait; /* Time we started waiting for sth. to happen */ + apr_time_t keepalive_until; /* Time when we stop keeing an idle conn alive */ apr_pool_t *pool; /* pool to use in session handling */ apr_bucket_brigade *bbtmp; /* brigade for keeping temporary data */