]> granicus.if.org Git - apache/commitdiff
Merge r1470679, r1477094 from trunk:
authorJim Jagielski <jim@apache.org>
Mon, 19 Aug 2013 15:42:12 +0000 (15:42 +0000)
committerJim Jagielski <jim@apache.org>
Mon, 19 Aug 2013 15:42:12 +0000 (15:42 +0000)
core, mod_ssl: Lift the restriction that prevents mod_ssl taking
full advantage of the event MPM. Enable the ability for a module
to reverse the sense of a poll event from a read to a write or vice
versa.

Update the docs to note that SSL now works with the event MPM as per r1470679.

Submitted by: minfrin
Reviewed/backported by: jim

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1515476 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
docs/manual/mod/event.xml
include/ap_mmn.h
include/httpd.h
modules/ssl/ssl_engine_io.c
server/mpm/event/event.c

diff --git a/CHANGES b/CHANGES
index 9dea413a3554cb1adb7d03d88f693980121baba1..de5aa4bfb3b6771f75fed8720b77bba65cba1bfd 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,11 @@
 
 Changes with Apache 2.4.7
 
+  *) core, mod_ssl: Enable the ability for a module to reverse the sense of
+     a poll event from a read to a write or vice versa. This is a step on
+     the way to allow mod_ssl taking full advantage of the event MPM.
+     [Graham Leggett]
+
   *) Makefile.win: Install proper pcre DLL file during debug build install.
      PR 55235.  [Ben Reser <ben reser org>]
 
diff --git a/STATUS b/STATUS
index 0bb4e1a83ee1e7f86131d13cf1478940fff4a0af..a68f6344f50ec888d604fc44f017f494ce19521a 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -92,18 +92,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  * core, mod_ssl: Lift the restriction that prevents mod_ssl taking
-    full advantage of the event MPM. Enable the ability for a module
-    to reverse the sense of a poll event from a read to a write or vice
-    versa.
-    trunk patches: http://svn.apache.org/r1470679
-                   http://svn.apache.org/r1477094
-    2.4.x patch: http://people.apache.org/~minfrin/httpd-event-ssl.patch
-    +1: minfrin, jim, sf
-    sf: These docs/CHANGES commits should be included, too:
-        http://svn.apache.org/r1514214
-        http://svn.apache.org/r1514617
-
   * configure: '--enable-maintainer-mode' should also auto-enable mod_bucketeer
     trunk: http://svn.apache.org/viewvc?view=revision&revision=1503680
     2.4.x patch: trunk patch works
index c27136058d4d425068dc8dc815e9b7f62bd7fb25..764608c164a3918d3914e3c24e5507b08932c7b7 100644 (file)
@@ -60,10 +60,19 @@ of consuming threads only for connections with active processing</description>
     status page of <module>mod_status</module> shows how many connections are
     in the mentioned states.</p>
 
-    <p>The improved connection handling does not yet work for certain
-    connection filters, in particular SSL. For SSL connections, this MPM will
-    fall back to the behaviour of the <module>worker</module> MPM and
-    reserve one worker thread per connection.</p>
+    <p>The improved connection handling may not work for certain connection
+    filters that have declared themselves as incompatible with event. In these
+    cases, this MPM will fall back to the behaviour of the
+    <module>worker</module> MPM and reserve one worker thread per connection.
+    All modules shipped with the server are compatible with the event MPM.</p>
+
+    <p>A similar restriction is currently present for requests involving an
+    output filter that needs to read and/or modify the whole response body,
+    like for example mod_ssl, mod_deflate, or mod_include. If the
+    connection to the client blocks while the filter is processing the
+    data, and the amount of data produced by the filter is too big to be
+    buffered in memory, the thread used for the request is not freed while
+    httpd waits until the pending data is sent to the client.</p>
 
     <p>The MPM assumes that the underlying <code>apr_pollset</code>
     implementation is reasonably threadsafe. This enables the MPM to
@@ -152,10 +161,10 @@ of consuming threads only for connections with active processing</description>
 <usage>
     <p>The event MPM handles some connections in an asynchronous way, where
     request worker threads are only allocated for short periods of time as
-    needed, and other (mostly SSL) connections with one request worker thread
-    reserved per connection. This can lead to situations where all workers are
-    tied up and no worker thread is available to handle new work on established
-    async connections.</p>
+    needed, and other connections with one request worker thread reserved per
+    connection. This can lead to situations where all workers are tied up and
+    no worker thread is available to handle new work on established async
+    connections.</p>
 
     <p>To mitigate this problem, the event MPM does two things: Firstly, it
     limits the number of connections accepted per process, depending on the
index 82a0acb00d9356303603b6a51b9b09266ccfacac..4f5ed0677e199b0091403105ba2bbf09de04d20c 100644 (file)
  * 20120211.22 (2.4.5-dev) No longer prevent usage of strtoul()
  * 20120211.23 (2.4.5-dev) Add ap_proxy_clear_connection()
  * 20120211.24 (2.4.7-dev) add open_htaccess hook.
+ * 20120211.25 (2.4.7-dev) Add conn_sense_e
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20120211
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 24                   /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 25                   /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 36cd58d542e181d3dc5e0bc044bba00599b24f7d..c84e24468a1361667753758d8099c3ee95b60bf3 100644 (file)
@@ -1175,12 +1175,20 @@ typedef enum  {
     CONN_STATE_LINGER_SHORT     /* MPM has started lingering close with short timeout */
 } conn_state_e;
 
+typedef enum  {
+    CONN_SENSE_DEFAULT,
+    CONN_SENSE_WANT_READ,       /* next event must be read */
+    CONN_SENSE_WANT_WRITE       /* next event must be write */
+} conn_sense_e;
+
 /**
  * @brief A structure to contain connection state information
  */
 struct conn_state_t {
     /** Current state of the connection */
     conn_state_e state;
+    /** Whether to read instead of write, or write instead of read */
+    conn_sense_e sense;
 };
 
 /* Per-vhost config... */
index d135bd38152fec2796014b9842d75e36a2e8f99b..cca15b4c7cc3f4da2c6b486460aba99c98d2bfbb 100644 (file)
@@ -775,6 +775,18 @@ static apr_status_t ssl_filter_write(ap_filter_t *f,
              */
             outctx->rc = APR_EAGAIN;
         }
+        else if (ssl_err == SSL_ERROR_WANT_READ) {
+            /*
+             * If OpenSSL wants to read during write, and we were
+             * nonblocking, set the sense explicitly to read and
+             * report as an EAGAIN.
+             *
+             * (This is usually the case when the client forces an SSL
+             * renegotiation which is handled implicitly by OpenSSL.)
+             */
+            outctx->c->cs->sense = CONN_SENSE_WANT_READ;
+            outctx->rc = APR_EAGAIN;
+        }
         else if (ssl_err == SSL_ERROR_SYSCALL) {
             ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, APLOGNO(01993)
                           "SSL output filter write failed.");
@@ -1902,8 +1914,10 @@ void ssl_io_filter_init(conn_rec *c, request_rec *r, SSL *ssl)
     filter_ctx->pbioWrite       = BIO_new(&bio_filter_out_method);
     filter_ctx->pbioWrite->ptr  = (void *)bio_filter_out_ctx_new(filter_ctx, c);
 
-    /* We insert a clogging input filter. Let the core know. */
-    c->clogging_input_filters = 1;
+    /* write is non blocking for the benefit of async mpm */
+    if (c->cs) {
+        BIO_set_nbio(filter_ctx->pbioWrite, 1);
+    }
 
     ssl_io_input_add_filter(filter_ctx, c, r, ssl);
 
index c64b08f5f4ca8e3416e9d6a34e2e6a7d41c2a5a6..f12468f51ac821328c5bd5446777ca01171d4634 100644 (file)
@@ -790,7 +790,10 @@ static int start_lingering_close_common(event_conn_state_t *cs)
     apr_atomic_inc32(&lingering_count);
     apr_thread_mutex_lock(timeout_mutex);
     TO_QUEUE_APPEND(*q, cs);
-    cs->pfd.reqevents = APR_POLLIN | APR_POLLHUP | APR_POLLERR;
+    cs->pfd.reqevents = (
+            cs->pub.sense == CONN_SENSE_WANT_WRITE ? APR_POLLOUT :
+                    APR_POLLIN) | APR_POLLHUP | APR_POLLERR;
+    cs->pub.sense = CONN_SENSE_DEFAULT;
     rv = apr_pollset_add(event_pollset, &cs->pfd);
     apr_thread_mutex_unlock(timeout_mutex);
     if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
@@ -938,6 +941,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;
     }
     else {
         c = cs->c;
@@ -946,9 +950,11 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
     }
 
     if (c->clogging_input_filters && !c->aborted) {
-        /* Since we have an input filter which 'cloggs' the input stream,
-         * like mod_ssl, lets just do the normal read from input filters,
-         * like the Worker MPM does.
+        /* Since we have an input filter which 'clogs' the input stream,
+         * like mod_ssl used to, lets just do the normal read from input
+         * filters, like the Worker MPM does. Filters that need to write
+         * where they would otherwise read, or read where they would
+         * otherwise write, should set the sense appropriately.
          */
         apr_atomic_inc32(&clogged_count);
         ap_run_process_connection(c);
@@ -994,7 +1000,10 @@ read_request:
             cs->expiration_time = ap_server_conf->timeout + apr_time_now();
             apr_thread_mutex_lock(timeout_mutex);
             TO_QUEUE_APPEND(write_completion_q, cs);
-            cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
+            cs->pfd.reqevents = (
+                    cs->pub.sense == CONN_SENSE_WANT_READ ? APR_POLLIN :
+                            APR_POLLOUT) | APR_POLLHUP | APR_POLLERR;
+            cs->pub.sense = CONN_SENSE_DEFAULT;
             rc = apr_pollset_add(event_pollset, &cs->pfd);
             apr_thread_mutex_unlock(timeout_mutex);
             return;