summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2022-02-04 12:27:17 +0000
committerStefan Eissing <icing@apache.org>2022-02-04 12:27:17 +0000
commit662495f8dbabe17a6e2e2b7ae63b45c37c886268 (patch)
treea3a3ab037036e5374be27aef99a6386341e51ab4
parentdb520660a81ea34d4eed8a9069389ce566345aa2 (diff)
parentb11e669f077f1546cdb34ab2c29a4f9289365024 (diff)
downloadhttpd-662495f8dbabe17a6e2e2b7ae63b45c37c886268.tar.gz
Merge of trunk.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/trunk-ssl-handshake-nonblocking@1897761 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES6
-rw-r--r--changes-entries/ab-ssl-sense-fix.txt5
-rw-r--r--include/ap_mmn.h2
-rw-r--r--include/ap_mpm.h2
-rw-r--r--include/httpd.h3
-rw-r--r--include/scoreboard.h1
-rw-r--r--modules/generators/mod_status.c15
-rw-r--r--modules/ssl/mod_ssl.c76
-rw-r--r--modules/ssl/ssl_engine_io.c53
-rw-r--r--server/mpm/event/event.c106
-rw-r--r--support/ab.c123
-rw-r--r--test/modules/http2/test_105_timeout.py1
12 files changed, 81 insertions, 312 deletions
diff --git a/CHANGES b/CHANGES
index 044de2ae07..de3bbe22d6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,12 +1,6 @@
-*- coding: utf-8 -*-
Changes with Apache 2.5.1
- *) event: Add support for non blocking behaviour in the
- CONN_STATE_READ_REQUEST_LINE phase, in addition to the existing
- CONN_STATE_WRITE_COMPLETION phase. Add AP_MPM_CAN_AGAIN and AGAIN to
- signal to the MPM that non blocking behaviour is requested. Update
- mod_ssl to perform non blocking TLS handshakes. [Graham Leggett]
-
*) http: Enforce that fully qualified uri-paths not to be forward-proxied
have an http(s) scheme, and that the ones to be forward proxied have a
hostname, per HTTP specifications. [Ruediger Pluem, Yann Ylavic]
diff --git a/changes-entries/ab-ssl-sense-fix.txt b/changes-entries/ab-ssl-sense-fix.txt
deleted file mode 100644
index 289498c7ab..0000000000
--- a/changes-entries/ab-ssl-sense-fix.txt
+++ /dev/null
@@ -1,5 +0,0 @@
- *) ab: Respond appropriately to SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE.
- Previously the correct event was polled for, but the response to the poll
- would call write instead of read, and read instead of write. PR 55952
- [Graham Leggett]
-
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index 6060c766d7..4fda68b1b3 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -698,8 +698,6 @@
* 20210926.2 (2.5.1-dev) Add ap_post_read_request()
* 20211221.0 (2.5.1-dev) Bump PROXY_WORKER_MAX_NAME_SIZE from 256 to 384,
* add PROXY_WORKER_UDS_PATH_SIZE.
- * 20211221.1 (2.5.1-dev) Add read_line to scoreboard.
- * 20211221.2 (2.5.1-dev) Add AGAIN, AP_MPMQ_CAN_AGAIN.
* 20211221.3 (2.5.1-dev) Add ap_thread_create(), ap_thread_main_create()
* and ap_thread_current()
*
diff --git a/include/ap_mpm.h b/include/ap_mpm.h
index 82075a4488..6698d0e7c6 100644
--- a/include/ap_mpm.h
+++ b/include/ap_mpm.h
@@ -182,8 +182,6 @@ AP_DECLARE(apr_status_t) ap_os_create_privileged_process(
#define AP_MPMQ_CAN_SUSPEND 17
/** MPM supports additional pollfds */
#define AP_MPMQ_CAN_POLL 18
-/** MPM reacts to AGAIN response */
-#define AP_MPMQ_CAN_AGAIN 19
/** @} */
/**
diff --git a/include/httpd.h b/include/httpd.h
index 906bed6927..dfd0304093 100644
--- a/include/httpd.h
+++ b/include/httpd.h
@@ -465,9 +465,6 @@ AP_DECLARE(const char *) ap_get_server_built(void);
*/
#define SUSPENDED -3 /**< Module will handle the remainder of the request.
* The core will never invoke the request again, */
-#define AGAIN -4 /**< Module wants to be called again when
- * more data is availble.
- */
/** Returned by the bottom-most filter if no data was written.
* @see ap_pass_brigade(). */
diff --git a/include/scoreboard.h b/include/scoreboard.h
index b0bdc6f13b..321b32778a 100644
--- a/include/scoreboard.h
+++ b/include/scoreboard.h
@@ -148,7 +148,6 @@ struct process_score {
apr_uint32_t lingering_close; /* async connections in lingering close */
apr_uint32_t keep_alive; /* async connections in keep alive */
apr_uint32_t suspended; /* connections suspended by some module */
- apr_uint32_t read_line; /* async connections doing read line */
};
/* Scoreboard is now in 'local' memory, since it isn't updated once created,
diff --git a/modules/generators/mod_status.c b/modules/generators/mod_status.c
index 8707ebe58b..8e80202c44 100644
--- a/modules/generators/mod_status.c
+++ b/modules/generators/mod_status.c
@@ -557,7 +557,7 @@ static int status_handler(request_rec *r)
ap_rputs("</dl>", r);
if (is_async) {
- int read_line = 0, write_completion = 0, lingering_close = 0, keep_alive = 0,
+ int write_completion = 0, lingering_close = 0, keep_alive = 0,
connections = 0, stopping = 0, procs = 0;
/*
* These differ from 'busy' and 'ready' in how gracefully finishing
@@ -574,12 +574,11 @@ static int status_handler(request_rec *r)
"<th colspan=\"3\">Async connections</th></tr>\n"
"<tr><th>total</th><th>accepting</th>"
"<th>busy</th><th>idle</th>"
- "<th>reading</th><th>writing</th><th>keep-alive</th><th>closing</th></tr>\n", r);
+ "<th>writing</th><th>keep-alive</th><th>closing</th></tr>\n", r);
for (i = 0; i < server_limit; ++i) {
ps_record = ap_get_scoreboard_process(i);
if (ps_record->pid) {
connections += ps_record->connections;
- read_line += ps_record->read_line;
write_completion += ps_record->write_completion;
keep_alive += ps_record->keep_alive;
lingering_close += ps_record->lingering_close;
@@ -601,7 +600,7 @@ static int status_handler(request_rec *r)
"<td>%s%s</td>"
"<td>%u</td><td>%s</td>"
"<td>%u</td><td>%u</td>"
- "<td>%u</td><td>%u</td><td>%u</td><td>%u</td>"
+ "<td>%u</td><td>%u</td><td>%u</td>"
"</tr>\n",
i, ps_record->pid,
dying, old,
@@ -609,7 +608,6 @@ static int status_handler(request_rec *r)
ps_record->not_accepting ? "no" : "yes",
thread_busy_buffer[i],
thread_idle_buffer[i],
- ps_record->read_line,
ps_record->write_completion,
ps_record->keep_alive,
ps_record->lingering_close);
@@ -621,12 +619,12 @@ static int status_handler(request_rec *r)
"<td>%d</td><td>%d</td>"
"<td>%d</td><td>&nbsp;</td>"
"<td>%d</td><td>%d</td>"
- "<td>%d</td><td>%d</td><td>%d</td><td>%d</td>"
+ "<td>%d</td><td>%d</td><td>%d</td>"
"</tr>\n</table>\n",
procs, stopping,
connections,
busy_workers, idle_workers,
- read_line, write_completion, keep_alive, lingering_close);
+ write_completion, keep_alive, lingering_close);
}
else {
ap_rprintf(r, "Processes: %d\n"
@@ -634,14 +632,13 @@ static int status_handler(request_rec *r)
"BusyWorkers: %d\n"
"IdleWorkers: %d\n"
"ConnsTotal: %d\n"
- "ConnsAsyncReading: %d\n"
"ConnsAsyncWriting: %d\n"
"ConnsAsyncKeepAlive: %d\n"
"ConnsAsyncClosing: %d\n",
procs, stopping,
busy_workers, idle_workers,
connections,
- read_line, write_completion, keep_alive, lingering_close);
+ write_completion, keep_alive, lingering_close);
}
}
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
index b06c7beabe..d1f6fbbc1f 100644
--- a/modules/ssl/mod_ssl.c
+++ b/modules/ssl/mod_ssl.c
@@ -30,7 +30,6 @@
#include "util_md5.h"
#include "util_mutex.h"
#include "ap_provider.h"
-#include "ap_mpm.h"
#include "http_config.h"
#include "mod_proxy.h" /* for proxy_hook_section_post_config() */
@@ -690,80 +689,31 @@ static int ssl_hook_process_connection(conn_rec* c)
{
SSLConnRec *sslconn = myConnConfig(c);
- int status = DECLINED;
-
if (sslconn && !sslconn->disabled) {
/* On an active SSL connection, let the input filters initialize
* themselves which triggers the handshake, which again triggers
* all kinds of useful things such as SNI and ALPN.
*/
apr_bucket_brigade* temp;
-
- int again_mpm = 0;
+ apr_status_t rv;
temp = apr_brigade_create(c->pool, c->bucket_alloc);
+ rv = ap_get_brigade(c->input_filters, temp,
+ AP_MODE_INIT, APR_BLOCK_READ, 0);
+ apr_brigade_destroy(temp);
- if (ap_mpm_query(AP_MPMQ_CAN_AGAIN, &again_mpm) != APR_SUCCESS) {
- again_mpm = 0;
- }
-
- if (again_mpm) {
-
- /* Take advantage of an async MPM. If we see an EAGAIN,
- * loop round and don't block.
- */
- conn_state_t *cs = c->cs;
-
- apr_status_t rv;
-
- rv = ap_get_brigade(c->input_filters, temp,
- AP_MODE_INIT, APR_NONBLOCK_READ, 0);
-
- if (rv == APR_SUCCESS) {
- /* great news, lets continue */
-
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10370)
- "SSL handshake completed, continuing");
-
- status = DECLINED;
- }
- else if (rv == APR_EAGAIN) {
- /* we've been asked to come around again, don't block */
-
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10371)
- "SSL handshake in progress, continuing");
-
- status = AGAIN;
- }
- else if (rv == AP_FILTER_ERROR) {
- /* handshake error, but mod_ssl handled it */
-
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10372)
- "SSL handshake failed, returning error response");
-
- status = DECLINED;
- }
- else {
- /* we failed, give up */
-
- cs->state = CONN_STATE_LINGER;
-
- ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(10373)
- "SSL handshake was not completed, "
- "closing connection");
-
- status = OK;
+ if (APR_SUCCESS != APR_SUCCESS) {
+ if (c->cs) {
+ c->cs->state = CONN_STATE_LINGER;
}
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(10373)
+ "SSL handshake was not completed, "
+ "closing connection");
+ return OK;
}
- else {
- ap_get_brigade(c->input_filters, temp,
- AP_MODE_INIT, APR_BLOCK_READ, 0);
- }
-
- apr_brigade_destroy(temp);
}
-
- return status;
+
+ return DECLINED;
}
/*
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
index 4445b1f787..47e3f30cdc 100644
--- a/modules/ssl/ssl_engine_io.c
+++ b/modules/ssl/ssl_engine_io.c
@@ -323,7 +323,6 @@ typedef struct {
} char_buffer_t;
typedef struct {
- conn_rec *c;
SSL *ssl;
BIO *bio_out;
ap_filter_t *f;
@@ -796,32 +795,6 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx,
* (This is usually the case when the client forces an SSL
* renegotiation which is handled implicitly by OpenSSL.)
*/
- if (inctx->c->cs) {
- inctx->c->cs->sense = CONN_SENSE_WANT_READ;
- }
- inctx->rc = APR_EAGAIN;
-
- if (*len > 0) {
- inctx->rc = APR_SUCCESS;
- break;
- }
- if (inctx->block == APR_NONBLOCK_READ) {
- break;
- }
- continue; /* Blocking and nothing yet? Try again. */
- }
- if (ssl_err == SSL_ERROR_WANT_WRITE) {
- /*
- * If OpenSSL wants to write during read, and we were
- * nonblocking, report as an EAGAIN. Otherwise loop,
- * pulling more data from network filter.
- *
- * (This is usually the case when the client forces an SSL
- * renegotiation which is handled implicitly by OpenSSL.)
- */
- if (inctx->c->cs) {
- inctx->c->cs->sense = CONN_SENSE_WANT_WRITE;
- }
inctx->rc = APR_EAGAIN;
if (*len > 0) {
@@ -987,9 +960,7 @@ static apr_status_t ssl_filter_write(ap_filter_t *f,
* (This is usually the case when the client forces an SSL
* renegotiation which is handled implicitly by OpenSSL.)
*/
- if (outctx->c->cs) {
- outctx->c->cs->sense = CONN_SENSE_WANT_READ;
- }
+ outctx->c->cs->sense = CONN_SENSE_WANT_READ;
outctx->rc = APR_EAGAIN;
ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, outctx->c,
"Want read during nonblocking write");
@@ -1518,25 +1489,10 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx)
}
else if (ssl_err == SSL_ERROR_WANT_READ) {
/*
- * Call us back when ready to read *\/
+ * This is in addition to what was present earlier. It is
+ * borrowed from openssl_state_machine.c [mod_tls].
+ * TBD.
*/
- ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, outctx->c,
- "Want read during nonblocking accept");
- if (outctx->c->cs) {
- outctx->c->cs->sense = CONN_SENSE_WANT_READ;
- }
- outctx->rc = APR_EAGAIN;
- return APR_EAGAIN;
- }
- else if (ssl_err == SSL_ERROR_WANT_WRITE) {
- /*
- * Call us back when ready to write *\/
- */
- ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, outctx->c,
- "Want write during nonblocking accept");
- if (outctx->c->cs) {
- outctx->c->cs->sense = CONN_SENSE_WANT_WRITE;
- }
outctx->rc = APR_EAGAIN;
return APR_EAGAIN;
}
@@ -2339,7 +2295,6 @@ static apr_status_t ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_r
}
BIO_set_data(filter_ctx->pbioRead, (void *)inctx);
- inctx->c = c;
inctx->ssl = ssl;
inctx->bio_out = filter_ctx->pbioWrite;
inctx->f = filter_ctx->pInputFilter;
diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
index aab61ac11d..9e0eeca0fb 100644
--- a/server/mpm/event/event.c
+++ b/server/mpm/event/event.c
@@ -268,14 +268,12 @@ struct timeout_queue {
/*
* Several timeout queues that use different timeouts, so that we always can
* simply append to the end.
- * read_line_q uses vhost's TimeOut FIXME - we can use a short timeout here
* write_completion_q uses vhost's TimeOut
* keepalive_q uses vhost's KeepAliveTimeOut
* linger_q uses MAX_SECS_TO_LINGER
* short_linger_q uses SECONDS_TO_LINGER
*/
-static struct timeout_queue *read_line_q,
- *write_completion_q,
+static struct timeout_queue *write_completion_q,
*keepalive_q,
*linger_q,
*short_linger_q;
@@ -448,8 +446,7 @@ static event_retained_data *retained;
static int max_spawn_rate_per_bucket = MAX_SPAWN_RATE / 1;
struct event_srv_cfg_s {
- struct timeout_queue *rl_q,
- *wc_q,
+ struct timeout_queue *wc_q,
*ka_q;
};
@@ -734,9 +731,6 @@ static int event_query(int query_code, int *result, apr_status_t *rv)
case AP_MPMQ_CAN_POLL:
*result = 1;
break;
- case AP_MPMQ_CAN_AGAIN:
- *result = 1;
- break;
default:
*rv = APR_ENOTIMPL;
break;
@@ -985,19 +979,15 @@ static void process_lingering_close(event_conn_state_t *cs);
static void update_reqevents_from_sense(event_conn_state_t *cs, int sense)
{
- /* has the desired sense been overridden? */
- if (cs->pub.sense != CONN_SENSE_DEFAULT) {
+ if (sense < 0) {
sense = cs->pub.sense;
}
-
- /* read or write */
if (sense == CONN_SENSE_WANT_READ) {
cs->pfd.reqevents = APR_POLLIN | APR_POLLHUP;
}
- else if (sense == CONN_SENSE_WANT_WRITE) {
+ else {
cs->pfd.reqevents = APR_POLLOUT;
}
-
/* POLLERR is usually returned event only, but some pollset
* backends may require it in reqevents to do the right thing,
* so it shouldn't hurt (ignored otherwise).
@@ -1044,7 +1034,6 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
&mpm_event_module);
cs->pfd.desc_type = APR_POLL_SOCKET;
cs->pfd.desc.s = sock;
- cs->pub.sense = CONN_SENSE_DEFAULT;
update_reqevents_from_sense(cs, CONN_SENSE_WANT_READ);
pt->type = PT_CSD;
pt->baton = cs;
@@ -1075,6 +1064,7 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
*/
cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
+ cs->pub.sense = CONN_SENSE_DEFAULT;
rc = OK;
}
else {
@@ -1125,8 +1115,6 @@ read_request:
/*
* The process_connection hooks above should set the connection state
* appropriately upon return, for event MPM to either:
- * - call the hooks again after waiting for a read or write, or react to an
- * overridden CONN_SENSE_WANT_READ / CONN_SENSE_WANT_WRITE.
* - do lingering close (CONN_STATE_LINGER),
* - wait for readability of the next request with respect to the keepalive
* timeout (state CONN_STATE_CHECK_REQUEST_LINE_READABLE),
@@ -1152,12 +1140,11 @@ read_request:
* while this was expected to do lingering close unconditionally with
* worker or prefork MPMs for instance.
*/
- if (rc != AGAIN && (
- rc != OK || (cs->pub.state >= CONN_STATE_NUM)
+ if (rc != OK || (cs->pub.state >= CONN_STATE_NUM)
|| (cs->pub.state < CONN_STATE_LINGER
&& cs->pub.state != CONN_STATE_WRITE_COMPLETION
&& cs->pub.state != CONN_STATE_CHECK_REQUEST_LINE_READABLE
- && cs->pub.state != CONN_STATE_SUSPENDED))) {
+ && cs->pub.state != CONN_STATE_SUSPENDED)) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10111)
"process_socket: connection processing %s: closing",
rc ? apr_psprintf(c->pool, "returned error %i", rc)
@@ -1166,41 +1153,6 @@ read_request:
cs->pub.state = CONN_STATE_LINGER;
}
- if (cs->pub.state == CONN_STATE_READ_REQUEST_LINE) {
- ap_update_child_status(cs->sbh, SERVER_BUSY_READ, NULL);
-
- /* It greatly simplifies the logic to use a single timeout value per q
- * because the new element can just be added to the end of the list and
- * it will stay sorted in expiration time sequence. If brand new
- * sockets are sent to the event thread for a readability check, this
- * will be a slight behavior change - they use the non-keepalive
- * timeout today. With a normal client, the socket will be readable in
- * a few milliseconds anyway.
- */
- cs->queue_timestamp = apr_time_now();
- notify_suspend(cs);
-
- /* Add work to pollset. */
- update_reqevents_from_sense(cs, CONN_SENSE_WANT_READ);
- apr_thread_mutex_lock(timeout_mutex);
- TO_QUEUE_APPEND(cs->sc->rl_q, cs);
- rv = apr_pollset_add(event_pollset, &cs->pfd);
- if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
- AP_DEBUG_ASSERT(0);
- TO_QUEUE_REMOVE(cs->sc->rl_q, cs);
- apr_thread_mutex_unlock(timeout_mutex);
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(10374)
- "process_socket: apr_pollset_add failure for "
- "read request line");
- close_connection(cs);
- signal_threads(ST_GRACEFUL);
- }
- else {
- apr_thread_mutex_unlock(timeout_mutex);
- }
- return;
- }
-
if (cs->pub.state == CONN_STATE_WRITE_COMPLETION) {
int pending = DECLINED;
@@ -1222,7 +1174,7 @@ read_request:
cs->queue_timestamp = apr_time_now();
notify_suspend(cs);
- update_reqevents_from_sense(cs, CONN_SENSE_WANT_WRITE);
+ update_reqevents_from_sense(cs, -1);
apr_thread_mutex_lock(timeout_mutex);
TO_QUEUE_APPEND(cs->sc->wc_q, cs);
rv = apr_pollset_add(event_pollset, &cs->pfd);
@@ -1328,7 +1280,7 @@ static apr_status_t event_resume_suspended (conn_rec *c)
cs->pub.state = CONN_STATE_WRITE_COMPLETION;
notify_suspend(cs);
- update_reqevents_from_sense(cs, CONN_SENSE_WANT_WRITE);
+ update_reqevents_from_sense(cs, -1);
apr_thread_mutex_lock(timeout_mutex);
TO_QUEUE_APPEND(cs->sc->wc_q, cs);
apr_pollset_add(event_pollset, &cs->pfd);
@@ -1786,7 +1738,6 @@ static void process_lingering_close(event_conn_state_t *cs)
}
/* (Re)queue the connection to come back when readable */
- cs->pub.sense = CONN_SENSE_DEFAULT;
update_reqevents_from_sense(cs, CONN_SENSE_WANT_READ);
q = (cs->pub.state == CONN_STATE_LINGER_SHORT) ? short_linger_q : linger_q;
apr_thread_mutex_lock(timeout_mutex);
@@ -1960,11 +1911,10 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
last_log = now;
apr_thread_mutex_lock(timeout_mutex);
ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
- "connections: %u (clogged: %u read-line: %d write-completion: %d "
+ "connections: %u (clogged: %u write-completion: %d "
"keep-alive: %d lingering: %d suspended: %u)",
apr_atomic_read32(&connection_count),
apr_atomic_read32(&clogged_count),
- apr_atomic_read32(read_line_q->total),
apr_atomic_read32(write_completion_q->total),
apr_atomic_read32(keepalive_q->total),
apr_atomic_read32(&lingering_count),
@@ -2097,11 +2047,6 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
int blocking = 0;
switch (cs->pub.state) {
- case CONN_STATE_READ_REQUEST_LINE:
- remove_from_q = cs->sc->rl_q;
- blocking = 1;
- break;
-
case CONN_STATE_WRITE_COMPLETION:
remove_from_q = cs->sc->wc_q;
blocking = 1;
@@ -2318,19 +2263,16 @@ do_maintenance:
else {
process_keepalive_queue(now);
}
- /* Step 2: read line timeouts */
- process_timeout_queue(read_line_q, now,
- shutdown_connection);
- /* Step 3: write completion timeouts */
+ /* Step 2: write completion timeouts */
process_timeout_queue(write_completion_q, now,
defer_lingering_close);
- /* Step 4: (normal) lingering close completion timeouts */
+ /* Step 3: (normal) lingering close completion timeouts */
if (dying && linger_q->timeout > short_linger_q->timeout) {
/* Dying, force short timeout for normal lingering close */
linger_q->timeout = short_linger_q->timeout;
}
process_timeout_queue(linger_q, now, shutdown_connection);
- /* Step 5: (short) lingering close completion timeouts */
+ /* Step 4: (short) lingering close completion timeouts */
process_timeout_queue(short_linger_q, now, shutdown_connection);
apr_thread_mutex_unlock(timeout_mutex);
@@ -2340,7 +2282,6 @@ do_maintenance:
: -1);
ps->keep_alive = apr_atomic_read32(keepalive_q->total);
- ps->read_line = apr_atomic_read32(read_line_q->total);
ps->write_completion = apr_atomic_read32(write_completion_q->total);
ps->connections = apr_atomic_read32(&connection_count);
ps->suspended = apr_atomic_read32(&suspended_count);
@@ -3969,15 +3910,14 @@ static int event_post_config(apr_pool_t *pconf, apr_pool_t *plog,
struct {
struct timeout_queue *tail, *q;
apr_hash_t *hash;
- } rl, wc, ka;
+ } wc, ka;
/* Not needed in pre_config stage */
if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) {
return OK;
}
- rl.tail = wc.tail = ka.tail = NULL;
- rl.hash = apr_hash_make(ptemp);
+ wc.tail = ka.tail = NULL;
wc.hash = apr_hash_make(ptemp);
ka.hash = apr_hash_make(ptemp);
@@ -3991,13 +3931,7 @@ static int event_post_config(apr_pool_t *pconf, apr_pool_t *plog,
ap_set_module_config(s->module_config, &mpm_event_module, sc);
if (!wc.tail) {
-
/* The main server uses the global queues */
-
- rl.q = TO_QUEUE_MAKE(pconf, s->timeout, NULL);
- apr_hash_set(rl.hash, &s->timeout, sizeof s->timeout, rl.q);
- rl.tail = read_line_q = rl.q;
-
wc.q = TO_QUEUE_MAKE(pconf, s->timeout, NULL);
apr_hash_set(wc.hash, &s->timeout, sizeof s->timeout, wc.q);
wc.tail = write_completion_q = wc.q;
@@ -4008,17 +3942,8 @@ static int event_post_config(apr_pool_t *pconf, apr_pool_t *plog,
ka.tail = keepalive_q = ka.q;
}
else {
-
/* The vhosts use any existing queue with the same timeout,
* or their own queue(s) if there isn't */
-
- rl.q = apr_hash_get(rl.hash, &s->timeout, sizeof s->timeout);
- if (!rl.q) {
- rl.q = TO_QUEUE_MAKE(pconf, s->timeout, rl.tail);
- apr_hash_set(rl.hash, &s->timeout, sizeof s->timeout, rl.q);
- rl.tail = rl.tail->next = rl.q;
- }
-
wc.q = apr_hash_get(wc.hash, &s->timeout, sizeof s->timeout);
if (!wc.q) {
wc.q = TO_QUEUE_MAKE(pconf, s->timeout, wc.tail);
@@ -4035,7 +3960,6 @@ static int event_post_config(apr_pool_t *pconf, apr_pool_t *plog,
ka.tail = ka.tail->next = ka.q;
}
}
- sc->rl_q = rl.q;
sc->wc_q = wc.q;
sc->ka_q = ka.q;
}
diff --git a/support/ab.c b/support/ab.c
index 20de3a844c..38715ebd2d 100644
--- a/support/ab.c
+++ b/support/ab.c
@@ -237,11 +237,7 @@ typedef enum {
* know if it worked yet
*/
STATE_CONNECTED, /* we know TCP connect completed */
-#ifdef USE_SSL
- STATE_HANDSHAKE, /* in the handshake phase */
-#endif
- STATE_WRITE, /* in the write phase */
- STATE_READ /* in the read phase */
+ STATE_READ
} connect_state_e;
#define CBUFFSIZE (8192)
@@ -524,13 +520,21 @@ static void set_polled_events(struct connection *c, apr_int16_t new_reqevents)
}
}
-static void set_conn_state(struct connection *c, connect_state_e new_state,
- apr_int16_t events)
+static void set_conn_state(struct connection *c, connect_state_e new_state)
{
+ apr_int16_t events_by_state[] = {
+ 0, /* for STATE_UNCONNECTED */
+ APR_POLLOUT, /* for STATE_CONNECTING */
+ APR_POLLIN, /* for STATE_CONNECTED; we don't poll in this state,
+ * so prepare for polling in the following state --
+ * STATE_READ
+ */
+ APR_POLLIN /* for STATE_READ */
+ };
c->state = new_state;
- set_polled_events(c, events);
+ set_polled_events(c, events_by_state[new_state]);
}
/* --------------------------------------------------------- */
@@ -703,7 +707,7 @@ static void ssl_print_info(struct connection *c)
}
ssl_print_connection_info(bio_err,c->ssl);
SSL_SESSION_print(bio_err, SSL_get_session(c->ssl));
-}
+ }
static void ssl_proceed_handshake(struct connection *c)
{
@@ -779,19 +783,14 @@ static void ssl_proceed_handshake(struct connection *c)
}
#endif
write_request(c);
-
do_next = 0;
break;
case SSL_ERROR_WANT_READ:
-
- set_conn_state(c, STATE_HANDSHAKE, APR_POLLIN);
-
+ set_polled_events(c, APR_POLLIN);
do_next = 0;
break;
case SSL_ERROR_WANT_WRITE:
-
- set_conn_state(c, STATE_HANDSHAKE, APR_POLLOUT);
-
+ set_polled_events(c, APR_POLLOUT);
do_next = 0;
break;
case SSL_ERROR_WANT_CONNECT:
@@ -811,6 +810,9 @@ static void ssl_proceed_handshake(struct connection *c)
static void write_request(struct connection * c)
{
+ if (started >= requests) {
+ return;
+ }
do {
apr_time_t tnow;
@@ -843,14 +845,10 @@ static void write_request(struct connection * c)
if (e <= 0) {
switch (SSL_get_error(c->ssl, e)) {
case SSL_ERROR_WANT_READ:
-
- set_conn_state(c, STATE_WRITE, APR_POLLIN);
-
+ set_polled_events(c, APR_POLLIN);
break;
case SSL_ERROR_WANT_WRITE:
-
- set_conn_state(c, STATE_WRITE, APR_POLLOUT);
-
+ set_polled_events(c, APR_POLLOUT);
break;
default:
BIO_printf(bio_err, "SSL write failed - closing connection\n");
@@ -873,7 +871,7 @@ static void write_request(struct connection * c)
close_connection(c);
}
else {
- set_conn_state(c, STATE_WRITE, APR_POLLOUT);
+ set_polled_events(c, APR_POLLOUT);
}
return;
}
@@ -885,8 +883,7 @@ static void write_request(struct connection * c)
c->endwrite = lasttime = apr_time_now();
started++;
-
- set_conn_state(c, STATE_READ, APR_POLLIN);
+ set_conn_state(c, STATE_READ);
}
/* --------------------------------------------------------- */
@@ -1358,9 +1355,8 @@ static void start_connect(struct connection * c)
{
apr_status_t rv;
- if (!(started < requests)) {
+ if (!(started < requests))
return;
- }
c->read = 0;
c->bread = 0;
@@ -1443,12 +1439,12 @@ static void start_connect(struct connection * c)
#endif
if ((rv = apr_socket_connect(c->aprsock, destsa)) != APR_SUCCESS) {
if (APR_STATUS_IS_EINPROGRESS(rv)) {
- set_conn_state(c, STATE_CONNECTING, APR_POLLOUT);
+ set_conn_state(c, STATE_CONNECTING);
c->rwrite = 0;
return;
}
else {
- set_conn_state(c, STATE_UNCONNECTED, 0);
+ set_conn_state(c, STATE_UNCONNECTED);
apr_socket_close(c->aprsock);
if (good == 0 && destsa->next) {
destsa = destsa->next;
@@ -1469,6 +1465,7 @@ static void start_connect(struct connection * c)
}
/* connected first time */
+ set_conn_state(c, STATE_CONNECTED);
#ifdef USE_SSL
if (c->ssl) {
ssl_proceed_handshake(c);
@@ -1516,7 +1513,7 @@ static void close_connection(struct connection * c)
}
}
- set_conn_state(c, STATE_UNCONNECTED, 0);
+ set_conn_state(c, STATE_UNCONNECTED);
#ifdef USE_SSL
if (c->ssl) {
SSL_shutdown(c->ssl);
@@ -1574,14 +1571,10 @@ read_more:
return;
}
else if (scode == SSL_ERROR_WANT_READ) {
-
- set_conn_state(c, STATE_READ, APR_POLLIN);
-
+ set_polled_events(c, APR_POLLIN);
}
else if (scode == SSL_ERROR_WANT_WRITE) {
-
- set_conn_state(c, STATE_READ, APR_POLLOUT);
-
+ set_polled_events(c, APR_POLLOUT);
}
else {
/* some fatal error: */
@@ -1675,7 +1668,7 @@ read_more:
}
else {
/* header is in invalid or too big - close connection */
- set_conn_state(c, STATE_UNCONNECTED, 0);
+ set_conn_state(c, STATE_UNCONNECTED);
apr_socket_close(c->aprsock);
err_response++;
if (bad++ > 10) {
@@ -1765,13 +1758,7 @@ read_more:
goto read_more;
}
- /* are we done? */
- if (started >= requests && (c->bread >= c->length)) {
- close_connection(c);
- }
-
- /* are we keepalive? if so, reuse existing connection */
- else if (c->keepalive && (c->bread >= c->length)) {
+ if (c->keepalive && (c->bread >= c->length)) {
/* finished a keep-alive connection */
good++;
/* save out time */
@@ -1803,7 +1790,7 @@ read_more:
c->read = c->bread = 0;
/* zero connect time with keep-alive */
c->start = c->connect = lasttime = apr_time_now();
-
+ set_conn_state(c, STATE_CONNECTED);
write_request(c);
}
}
@@ -1993,7 +1980,6 @@ static void test(void)
do {
status = apr_pollset_poll(readbits, aprtimeout, &n, &pollresults);
} while (APR_STATUS_IS_EINTR(status));
-
if (status != APR_SUCCESS)
apr_err("apr_pollset_poll", status);
@@ -2029,23 +2015,8 @@ static void test(void)
* connection is done and we loop here endlessly calling
* apr_poll().
*/
- if ((rtnev & APR_POLLIN) || (rtnev & APR_POLLPRI) || (rtnev & APR_POLLHUP)) {
-
- switch (c->state) {
-#ifdef USE_SSL
- case STATE_HANDSHAKE:
- ssl_proceed_handshake(c);
- break;
-#endif
- case STATE_WRITE:
- write_request(c);
- break;
- case STATE_READ:
- read_connection(c);
- break;
- }
-
- }
+ if ((rtnev & APR_POLLIN) || (rtnev & APR_POLLPRI) || (rtnev & APR_POLLHUP))
+ read_connection(c);
if ((rtnev & APR_POLLERR) || (rtnev & APR_POLLNVAL)) {
if (destsa->next && c->state == STATE_CONNECTING && good == 0) {
destsa = destsa->next;
@@ -2069,7 +2040,7 @@ static void test(void)
/* call connect() again to detect errors */
rv = apr_socket_connect(c->aprsock, destsa);
if (rv != APR_SUCCESS) {
- set_conn_state(c, STATE_UNCONNECTED, 0);
+ set_conn_state(c, STATE_UNCONNECTED);
apr_socket_close(c->aprsock);
err_conn++;
if (bad++ > 10) {
@@ -2081,7 +2052,7 @@ static void test(void)
continue;
}
else {
-
+ set_conn_state(c, STATE_CONNECTED);
#ifdef USE_SSL
if (c->ssl)
ssl_proceed_handshake(c);
@@ -2089,24 +2060,16 @@ static void test(void)
#endif
write_request(c);
}
-
}
else {
-
- switch (c->state) {
-#ifdef USE_SSL
- case STATE_HANDSHAKE:
- ssl_proceed_handshake(c);
- break;
-#endif
- case STATE_WRITE:
- write_request(c);
- break;
- case STATE_READ:
+ /* POLLOUT is one shot */
+ set_polled_events(c, APR_POLLIN);
+ if (c->state == STATE_READ) {
read_connection(c);
- break;
}
-
+ else {
+ write_request(c);
+ }
}
}
}
@@ -2729,7 +2692,7 @@ int main(int argc, const char * const argv[])
if (ssl_cert != NULL) {
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, ssl_cert) <= 0) {
BIO_printf(bio_err, "unable to get certificate from '%s'\n",
- ssl_cert);
+ ssl_cert);
ERR_print_errors(bio_err);
exit(1);
}
diff --git a/test/modules/http2/test_105_timeout.py b/test/modules/http2/test_105_timeout.py
index 3b030cdd0d..24133ae52c 100644
--- a/test/modules/http2/test_105_timeout.py
+++ b/test/modules/http2/test_105_timeout.py
@@ -44,7 +44,6 @@ class TestTimeout:
sock.close()
# Check that mod_reqtimeout handshake setting takes effect
- @pytest.mark.skip(reason="SSL handshake timeout currently broken")
def test_h2_105_02(self, env):
conf = H2Conf(env)
conf.add("""