]> granicus.if.org Git - apache/commitdiff
Merge r1546759, r1546760 from trunk:
authorJim Jagielski <jim@apache.org>
Tue, 15 Apr 2014 19:15:02 +0000 (19:15 +0000)
committerJim Jagielski <jim@apache.org>
Tue, 15 Apr 2014 19:15:02 +0000 (19:15 +0000)
Add suspend_connection and resume_connection hooks to notify modules
when the thread/connection relationship changes.  (Currently implemented
only for the Event MPM; should be implemented for all async MPMs.)

follow-up to r1546759: remove an inadvertently committed testcase
Submitted by: trawick
Reviewed/backported by: jim

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

CHANGES
STATUS
include/ap_mmn.h
include/mpm_common.h
server/mpm/event/event.c
server/mpm_common.c

diff --git a/CHANGES b/CHANGES
index 04f18665011b44321f622545039989eda36f9765..ad0180d764822b000cb24c1bddc2c69810bc6fbd 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,10 @@ Changes with Apache 2.4.10
      "http-equiv" meta tag specifies a Content-Type behind any other
      "http-equiv" meta tag. PR 56287 [Micha Lenk <micha lenk info>]
 
+  *) Add suspend_connection and resume_connection hooks to notify modules
+     when the thread/connection relationship changes.  (Should be implemented
+     for any third-party async MPMs.)  [Jeff Trawick]
+
   *) mod_lua: Redesign how request record table access behaves,
      in order to utilize the request record from within these tables
      [Daniel Gruno]
diff --git a/STATUS b/STATUS
index 1b240eabb3651dc32f33a9a1fb611dd15df8f263..fd442fce030ba76f78d5570cb60624f82c9199a3 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -114,13 +114,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
      2.4.x patch: trunk works
      +1 covener, jim, ylavic
 
-   * event: Add suspend/resume hooks to event MPM to inform modules when
-     connections/requests change thread affinity.
-     trunk: http://svn.apache.org/viewvc?view=revision&revision=1546759
-            http://svn.apache.org/viewvc?view=revision&revision=1546760
-     2.4.x patch: http://people.apache.org/~trawick/suspend_resume_24.txt
-     +1: trawick, jim, ylavic
-
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]
index 8918e1a5f32c38a5962f376ce9140869d9faa385..32e05d55b4de93c9e082fca10eeac057a196ff7e 100644 (file)
  * 20120211.30 (2.4.7-dev) REWRITE_REDIRECT_HANDLER_NAME in mod_rewrite.h
  * 20120211.31 (2.4.7-dev) Add ap_proxy_port_of_scheme()
  * 20120211.32 (2.4.10-dev) Add SSL reusable SNI to mod_proxy.h's proxy_conn_rec
+ * 20120211.33 (2.4.10-dev) Add suspend_connection and resume_connection hooks
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20120211
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 32                   /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 33                   /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 59684313c6a8587a481ec6db6db6379834a6a633..69afef8c944b8854787cfdb66ef89738ec249a5d 100644 (file)
@@ -411,6 +411,47 @@ AP_DECLARE_HOOK(apr_status_t, mpm_register_timed_callback,
 /* get MPM name (e.g., "prefork" or "event") */
 AP_DECLARE_HOOK(const char *,mpm_get_name,(void))
 
+/**
+ * Notification that connection handling is suspending (disassociating from the
+ * current thread)
+ * @param c The current connection
+ * @param r The current request, or NULL if there is no active request
+ * @ingroup hooks
+ * @see ap_hook_resume_connection
+ * @note This hook is not implemented by MPMs like Prefork and Worker which 
+ * handle all processing of a particular connection on the same thread.
+ * @note This hook will be called on the thread that was previously
+ * processing the connection.
+ * @note This hook is not called at the end of connection processing.  This
+ * hook only notifies a module when processing of an active connection is
+ * suspended.
+ * @note Resumption and subsequent suspension of a connection solely to perform
+ * I/O by the MPM, with no execution of non-MPM code, may not necessarily result
+ * in a call to this hook.
+ */
+AP_DECLARE_HOOK(void, suspend_connection,
+                (conn_rec *c, request_rec *r))
+
+/**
+ * Notification that connection handling is resuming (associating with a thread)
+ * @param c The current connection
+ * @param r The current request, or NULL if there is no active request
+ * @ingroup hooks
+ * @see ap_hook_suspend_connection
+ * @note This hook is not implemented by MPMs like Prefork and Worker which 
+ * handle all processing of a particular connection on the same thread.
+ * @note This hook will be called on the thread that will resume processing
+ * the connection.
+ * @note This hook is not called at the beginning of connection processing.
+ * This hook only notifies a module when processing resumes for a
+ * previously-suspended connection.
+ * @note Resumption and subsequent suspension of a connection solely to perform
+ * I/O by the MPM, with no execution of non-MPM code, may not necessarily result
+ * in a call to this hook.
+ */
+AP_DECLARE_HOOK(void, resume_connection,
+                (conn_rec *c, request_rec *r))
+
 /* mutex type string for accept mutex, if any; MPMs should use the
  * same mutex type for ease of configuration
  */
index 7a95498ea356122d03984b231399ce783a8400f2..9bcad5c38ebf8b023310162808ba9964dcf9562e 100644 (file)
@@ -83,6 +83,7 @@
 #include "http_config.h"        /* for read_config */
 #include "http_core.h"          /* for get_remote_host */
 #include "http_connection.h"
+#include "http_protocol.h"
 #include "ap_mpm.h"
 #include "mpm_common.h"
 #include "ap_listen.h"
@@ -185,6 +186,8 @@ static int mpm_state = AP_MPMQ_STARTING;
 
 static apr_thread_mutex_t *timeout_mutex;
 
+module AP_MODULE_DECLARE_DATA mpm_event_module;
+
 struct event_conn_state_t {
     /** APR_RING of expiration timeouts */
     APR_RING_ENTRY(event_conn_state_t) timeout_list;
@@ -192,6 +195,13 @@ struct event_conn_state_t {
     apr_time_t expiration_time;
     /** connection record this struct refers to */
     conn_rec *c;
+    /** request record (if any) this struct refers to */
+    request_rec *r;
+    /** is the current conn_rec suspended?  (disassociated with
+     * a particular MPM thread; for suspend_/resume_connection
+     * hooks)
+     */
+    int suspended;
     /** memory pool to allocate from */
     apr_pool_t *p;
     /** bucket allocator */
@@ -875,6 +885,57 @@ static int stop_lingering_close(event_conn_state_t *cs)
     return 0;
 }
 
+static void notify_suspend(event_conn_state_t *cs)
+{
+    ap_run_suspend_connection(cs->c, cs->r);
+    cs->suspended = 1;
+}
+
+static void notify_resume(event_conn_state_t *cs)
+{
+    cs->suspended = 0;
+    ap_run_resume_connection(cs->c, cs->r);
+}
+
+/*
+ * This runs before any non-MPM cleanup code on the connection;
+ * if the connection is currently suspended as far as modules
+ * know, provide notification of resumption.
+ */
+static apr_status_t ptrans_pre_cleanup(void *dummy)
+{
+    event_conn_state_t *cs = dummy;
+
+    if (cs->suspended) {
+        notify_resume(cs);
+    }
+    return APR_SUCCESS;
+}
+
+/*
+ * event_pre_read_request() and event_request_cleanup() track the
+ * current r for a given connection.
+ */
+static apr_status_t event_request_cleanup(void *dummy)
+{
+    conn_rec *c = dummy;
+    event_conn_state_t *cs = ap_get_module_config(c->conn_config,
+                                                  &mpm_event_module);
+
+    cs->r = NULL;
+    return APR_SUCCESS;
+}
+
+static void event_pre_read_request(request_rec *r, conn_rec *c)
+{
+    event_conn_state_t *cs = ap_get_module_config(c->conn_config,
+                                                  &mpm_event_module);
+
+    cs->r = r;
+    apr_pool_cleanup_register(r->pool, c, event_request_cleanup,
+                              apr_pool_cleanup_null);
+}
+
 /*
  * process one connection in the worker
  */
@@ -905,6 +966,7 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
         apr_atomic_inc32(&connection_count);
         apr_pool_cleanup_register(c->pool, cs, decrement_connection_count,
                                   apr_pool_cleanup_null);
+        ap_set_module_config(c->conn_config, &mpm_event_module, cs);
         c->current_thread = thd;
         cs->c = c;
         c->cs = &(cs->pub);
@@ -915,6 +977,7 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
         pt->type = PT_CSD;
         pt->baton = cs;
         cs->pfd.client_data = pt;
+        apr_pool_pre_cleanup_register(p, cs, ptrans_pre_cleanup);
         TO_QUEUE_ELEM_INIT(cs);
 
         ap_update_vhost_given_ip(c);
@@ -946,6 +1009,7 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
     else {
         c = cs->c;
         c->sbh = sbh;
+        notify_resume(cs);
         c->current_thread = thd;
     }
 
@@ -998,6 +1062,7 @@ read_request:
              * event thread poll for writeability.
              */
             cs->expiration_time = ap_server_conf->timeout + apr_time_now();
+            notify_suspend(cs);
             apr_thread_mutex_lock(timeout_mutex);
             TO_QUEUE_APPEND(write_completion_q, cs);
             cs->pfd.reqevents = (
@@ -1023,6 +1088,7 @@ read_request:
 
     if (cs->pub.state == CONN_STATE_LINGER) {
         if (!start_lingering_close_blocking(cs))
+            notify_suspend(cs);
             return;
     }
     else if (cs->pub.state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
@@ -1037,6 +1103,7 @@ read_request:
         cs->expiration_time = ap_server_conf->keep_alive_timeout +
                               apr_time_now();
         c->sbh = NULL;
+        notify_suspend(cs);
         apr_thread_mutex_lock(timeout_mutex);
         TO_QUEUE_APPEND(keepalive_q, cs);
 
@@ -1062,6 +1129,7 @@ read_request:
      * or timeout.
      */
     c->sbh = NULL;
+    notify_suspend(cs);
     return;
 }
 
@@ -3171,6 +3239,7 @@ static void event_hooks(apr_pool_t * p)
     ap_hook_mpm_query(event_query, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL,
                                         APR_HOOK_MIDDLE);
+    ap_hook_pre_read_request(event_pre_read_request, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_mpm_get_name(event_get_name, NULL, NULL, APR_HOOK_MIDDLE);
 }
 
index 348e66760662ca139e6ae85e5514eacb1fb10cf0..3b8e4ebccfcce933efaaf1a19c3597f36342a29e 100644 (file)
@@ -73,6 +73,8 @@ APR_HOOK_STRUCT(
     APR_HOOK_LINK(mpm_get_name)
     APR_HOOK_LINK(end_generation)
     APR_HOOK_LINK(child_status)
+    APR_HOOK_LINK(suspend_connection)
+    APR_HOOK_LINK(resume_connection)
 )
 AP_IMPLEMENT_HOOK_RUN_ALL(int, fatal_exception,
                           (ap_exception_info_t *ei), (ei), OK, DECLINED)
@@ -108,6 +110,12 @@ AP_IMPLEMENT_HOOK_VOID(end_generation,
 AP_IMPLEMENT_HOOK_VOID(child_status,
                        (server_rec *s, pid_t pid, ap_generation_t gen, int slot, mpm_child_status status),
                        (s,pid,gen,slot,status))
+AP_IMPLEMENT_HOOK_VOID(suspend_connection,
+                       (conn_rec *c, request_rec *r),
+                       (c, r))
+AP_IMPLEMENT_HOOK_VOID(resume_connection,
+                       (conn_rec *c, request_rec *r),
+                       (c, r))
 
 /* hooks with no args are implemented last, after disabling APR hook probes */
 #if defined(APR_HOOK_PROBES_ENABLED)