]> granicus.if.org Git - apache/commitdiff
Add suspend_connection and resume_connection hooks to notify modules
authorJeff Trawick <trawick@apache.org>
Sat, 30 Nov 2013 17:56:25 +0000 (17:56 +0000)
committerJeff Trawick <trawick@apache.org>
Sat, 30 Nov 2013 17:56:25 +0000 (17:56 +0000)
when the thread/connection relationship changes.  (Currently implemented
only for the Event MPM; should be implemented for all async MPMs.)

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

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

diff --git a/CHANGES b/CHANGES
index 3fbc5aa7655d99ac5c013a190ad7284129f2f1b5..f41f6c43b92ad3af965c8dd99d35b81f65853944 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) 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.)
+     [Jeff Trawick]
+
   *) mod_ssl: Don't flush when an EOS is received. Prepares mod_ssl
      to support write completion. [Graham Leggett]
 
index b0ef6bf3615eb428d355769c462d6445b6e7bdfd..f52604b694980cb52e9dbd7060b3dd40f0e9ab45 100644 (file)
  * 20130924.0 (2.5.0-dev)  Add ap_errorlog_provider
  * 20130924.1 (2.5.0-dev)  Add ap_proxy_connection_reusable()
  * 20131112.0 (2.5.0-dev)  Add parse_errorlog_arg to ap_errorlog_provider
+ * 20131112.1 (2.5.0-dev)  Add suspend_connection and resume_connection hooks
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20131112
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 0                  /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 1                  /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 76bb59488d21e98ba069a546da4c6ef890125b5f..15dfc4602d2570ede66725da4095a8d1ac7d9d9c 100644 (file)
@@ -419,6 +419,47 @@ AP_DECLARE_HOOK(apr_status_t, mpm_unregister_socket_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 c1d78b469847b51c5cd2e6160dee48dff8846150..4fbbc429493ec1008949ee648f2e318c704d7fb4 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"
@@ -190,6 +191,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;
@@ -197,6 +200,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 */
@@ -905,6 +915,62 @@ static int stop_lingering_close(event_conn_state_t *cs)
     return 0;
 }
 
+static void notify_suspend(event_conn_state_t *cs)
+{
+    static int how_many = 0;
+
+    if (++how_many == 7) {
+        *(int *)0xcafebabe = 0;
+    }
+    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
  */
@@ -935,6 +1001,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);
@@ -945,6 +1012,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);
@@ -976,6 +1044,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;
     }
 
@@ -1029,6 +1098,7 @@ read_request:
              */
             cs->expiration_time = ap_server_conf->timeout + apr_time_now();
             c->sbh = NULL;
+            notify_suspend(cs);
             apr_thread_mutex_lock(timeout_mutex);
             TO_QUEUE_APPEND(write_completion_q, cs);
             cs->pfd.reqevents = (
@@ -1055,6 +1125,7 @@ read_request:
     if (cs->pub.state == CONN_STATE_LINGER) {
         if (!start_lingering_close_blocking(cs)) {
             c->sbh = NULL;
+            notify_suspend(cs);
             return;
         }
     }
@@ -1070,6 +1141,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);
 
@@ -1095,6 +1167,7 @@ read_request:
      * or timeout.
      */
     c->sbh = NULL;
+    notify_suspend(cs);
     return;
 }
 
@@ -3360,7 +3433,7 @@ static void event_hooks(apr_pool_t * p)
                                         APR_HOOK_MIDDLE);
     ap_hook_mpm_unregister_socket_callback(event_unregister_socket_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 e1f05324474e0661290e4da9b8f05be5dcdef70e..b5b142aac367caeb6deb23ee7b5ce61d28c95807 100644 (file)
@@ -75,6 +75,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)
@@ -119,6 +121,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)