]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
*) core/mod_ssl/mpm_event: reverting changes to nonblocing SSL handshakes
authorStefan Eissing <icing@apache.org>
Fri, 4 Feb 2022 12:22:26 +0000 (12:22 +0000)
committerStefan Eissing <icing@apache.org>
Fri, 4 Feb 2022 12:22:26 +0000 (12:22 +0000)
     to stabilize CI tests again. Previous revision of trunk has been copied
     to branches/trunk-ssl-handshake-unblocking to make those into a PR where
     changes can be discussed and tested separately.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1897760 13f79535-47bb-0310-9956-ffa450edef68

12 files changed:
CHANGES
changes-entries/ab-ssl-sense-fix.txt [deleted file]
include/ap_mmn.h
include/ap_mpm.h
include/httpd.h
include/scoreboard.h
modules/generators/mod_status.c
modules/ssl/mod_ssl.c
modules/ssl/ssl_engine_io.c
server/mpm/event/event.c
support/ab.c
test/modules/http2/test_105_timeout.py

diff --git a/CHANGES b/CHANGES
index 044de2ae07d3d85217046381ef605472bc0bd046..de3bbe22d627de0a0845fbb9fba6a568a456b8f3 100644 (file)
--- 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 (file)
index 289498c..0000000
+++ /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]
-
index 6060c766d790c6363e528134a19880248a890376..4fda68b1b32faf44641a1e71e438c4f59e432dab 100644 (file)
  * 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()
  *
index 82075a4488b31916ca754c3b7ee804af38cab834..6698d0e7c6069ecef0c7c55a14472ac2efa4a01f 100644 (file)
@@ -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
 /** @} */
 
 /**
index 906bed6927cf23278c53f58a466d510bcad7e3ef..dfd03040933dfc5056ada2d4a8ef8e531ea60a5b 100644 (file)
@@ -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(). */
index b0bdc6f13b076c15ed9df628b06179464af16767..321b32778a0b4cc437f2208336a211d518a75528 100644 (file)
@@ -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,
index 8707ebe58b38d91138ccc72975c99a3b6654e5b4..8e80202c446e25a0adc6788a66a03a774fd19c77 100644 (file)
@@ -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);
         }
     }
 
index b06c7beabef075130c85b868ab41e285d82990f2..d1f6fbbc1f116b1f0b84abe43d0e463f1dc5b8c5 100644 (file)
@@ -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;
 }
 
 /*
index 4445b1f78787722d925aadf7798ac5d53f9966b8..47e3f30cdc35f16cae1a24210c00bc6db4dd538c 100644 (file)
@@ -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;
index aab61ac11db0ba3c51a7cb3c1bfc0e7277c075bd..9e0eeca0fbbd3657fc32a11033b7540a5ffe21a3 100644 (file)
@@ -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;
     }
index 20de3a844ce4f0addfb490803e7e18a3e85d3ab5..38715ebd2db64ab3aebfe2eea14992eb4827a190 100644 (file)
@@ -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);
         }
index 3b030cdd0d10a362c6b677815656efcf5d403110..24133ae52cfdeef3196649e98b6338ff47df8fbd 100644 (file)
@@ -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("""