]> granicus.if.org Git - apache/commitdiff
PR56333: Add an API to resume a connection that a handler has previously suspended.
authorEric Covener <covener@apache.org>
Sun, 11 May 2014 20:52:32 +0000 (20:52 +0000)
committerEric Covener <covener@apache.org>
Sun, 11 May 2014 20:52:32 +0000 (20:52 +0000)
Submitted by: Artem <artemciy gmail.com>, Edward Lu <Chaosed0 gmail.com>
Committed by: covener

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

CHANGES
include/ap_mmn.h
include/ap_mpm.h
include/httpd.h
include/mpm_common.h
modules/test/mod_dialup.c
server/mpm/event/event.c
server/mpm_common.c

diff --git a/CHANGES b/CHANGES
index 824eedbc60d4d1784c235cd57dee19992425c061..ab0ce9a8a4848265f35ba39a96bfab308622644d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
-
+  
+  *) core: Add ap_mpm_resume_suspended() API to allow a suspended connection
+     to resume. PR56333 
+     [Artem <artemciy gmail.com>, Edward Lu <Chaosed0 gmail.com>]
   *) core: Add ap_mpm_register_socket_callback_timeout() API. [Eric Covener]
 
   *) mod_proxy_wstunnel: Honor ProxyWebsocketIdleTimeout in asynchronous
index a3acb2505d738a0a522cd33e10b0d8ab0b970d1a..cbb31afc3890850959a05b080adda884b423bb5f 100644 (file)
  * 20140207.2 (2.5.0-dev)  Add proxy detach_backend hook
  * 20140207.3 (2.5.0-dev)  Add mod_ssl_openssl.h and OpenSSL-specific hooks
  * 20140207.4 (2.5.0-dev)  add ap_mpm_register_socket_callback_timeout
+ * 20140207.5 (2.5.0-dev)  Add ap_mpm_resume_suspended(), AP_MPMQ_CAN_SUSPEND to
+ *                         ap_mpm_query(), and suspended_baton to conn_rec
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20140207
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 4                  /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 5                  /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index d851f35582ac0446c800fb405cc5734c557ab10f..d50acd95e3af312aaaad4fc69472dc73affb59f4 100644 (file)
@@ -178,6 +178,8 @@ AP_DECLARE(apr_status_t) ap_os_create_privileged_process(
 #define AP_MPMQ_GENERATION           15
 /** MPM can drive serf internally  */
 #define AP_MPMQ_HAS_SERF             16
+/** MPM supports suspending/resuming connections */
+#define AP_MPMQ_CAN_SUSPEND          17
 /** @} */
 
 /**
@@ -197,6 +199,8 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result);
 
 typedef void (ap_mpm_callback_fn_t)(void *baton);
 
+/* only added support in the Event MPM....  check for APR_ENOTIMPL */
+AP_DECLARE(apr_status_t) ap_mpm_resume_suspended(conn_rec *c);
 /* only added support in the Event MPM....  check for APR_ENOTIMPL */
 AP_DECLARE(apr_status_t) ap_mpm_register_timed_callback(apr_time_t t,
                                                        ap_mpm_callback_fn_t *cbfn,
index 29985d2594629530d82ddc77faf73c579b97b609..d458ad70ad253ffef8f4a05a0670d3e4710b22d7 100644 (file)
@@ -1173,6 +1173,9 @@ struct conn_rec {
 
     /** context of this connection */
     void *ctx;
+
+    /** Context under which this connection was suspended */
+    void *suspended_baton;
 };
 
 struct conn_slave_rec {
index 44a693fbb357e79fc1249a3816e4b21383e07f17..4031b51ddf1f96175f044f74cdac07d77387d13e 100644 (file)
@@ -446,6 +446,11 @@ AP_DECLARE_HOOK(apr_status_t, mpm_register_socket_callback_timeout,
 AP_DECLARE_HOOK(apr_status_t, mpm_unregister_socket_callback,
                 (apr_socket_t **s, apr_pool_t *p))
 
+/** Resume the suspended connection 
+ * @ingroup hooks
+ */
+AP_DECLARE_HOOK(apr_status_t, mpm_resume_suspended, (conn_rec*))
+
 /**
  * Get MPM name (e.g., "prefork" or "event")
  * @ingroup hooks
index 93e9743080271f10f62344588c6b0cb69b16d0db..b46097a825f6d0bb89cb4e68b16c7ffc66ff763c 100644 (file)
@@ -105,6 +105,7 @@ dialup_callback(void *baton)
 {
     int status;
     dialup_baton_t *db = (dialup_baton_t *)baton;
+    conn_rec *c = db->r->connection;
 
     apr_thread_mutex_lock(db->r->invoke_mtx);
 
@@ -127,6 +128,8 @@ dialup_callback(void *baton)
     }
 
     apr_thread_mutex_unlock(db->r->invoke_mtx);
+
+    ap_mpm_resume_suspended(c);
 }
 
 static int
@@ -139,7 +142,7 @@ dialup_handler(request_rec *r)
     apr_file_t *fd;
     dialup_baton_t *db;
     apr_bucket *e;
-
+    int mpm_can_suspend = 0;
 
     /* See core.c, default handler for all of the cases we just decline. */
     if (r->method_number != M_GET ||
@@ -148,6 +151,13 @@ dialup_handler(request_rec *r)
         return DECLINED;
     }
 
+    rv = ap_mpm_query(AP_MPMQ_CAN_SUSPEND, &mpm_can_suspend);
+    if (!mpm_can_suspend) {
+        ap_log_rerror (APLOG_MARK, LOG_NOTICE, rv, r, APLOGNO(02617)
+                "dialup: MPM doesn't support suspending");
+        return DECLINED;
+    }
+
     dcfg = ap_get_module_config(r->per_dir_config,
                                 &dialup_module);
 
index 58042f9170b2868acf58ea9311da573868bc9d0a..7eb83cb032034a83d37d655fe476af5510bf6650 100644 (file)
@@ -551,6 +551,9 @@ static int event_query(int query_code, int *result, apr_status_t *rv)
     case AP_MPMQ_GENERATION:
         *result = retained->my_generation;
         break;
+    case AP_MPMQ_CAN_SUSPEND:
+        *result = 1;
+        break;
     default:
         *rv = APR_ENOTIMPL;
         break;
@@ -1154,6 +1157,7 @@ read_request:
         return;
     }
     else if (cs->pub.state == CONN_STATE_SUSPENDED) {
+        cs->c->suspended_baton = cs;
         apr_atomic_inc32(&suspended_count);
     }
     /*
@@ -1167,6 +1171,33 @@ read_request:
     return;
 }
 
+/* Put a SUSPENDED connection back into a queue. */
+static apr_status_t event_resume_suspended (conn_rec *c) {
+    event_conn_state_t* cs = (event_conn_state_t*) c->suspended_baton;
+    if (cs == NULL) {
+        ap_log_cerror (APLOG_MARK, LOG_WARNING, 0, c, APLOGNO(02615)
+                "event_resume_suspended: suspended_baton is NULL");
+        return APR_EGENERAL;
+    } else if (!cs->suspended) {
+        ap_log_cerror (APLOG_MARK, LOG_WARNING, 0, c, APLOGNO(02616)
+                "event_resume_suspended: Thread isn't suspended");
+        return APR_EGENERAL;
+    }
+    apr_atomic_dec32(&suspended_count);
+    c->suspended_baton = NULL;
+
+    apr_thread_mutex_lock(timeout_mutex);
+    TO_QUEUE_APPEND(write_completion_q, cs);
+    cs->pfd.reqevents = (
+            cs->pub.sense == CONN_SENSE_WANT_READ ? APR_POLLIN :
+                    APR_POLLOUT) | APR_POLLHUP | APR_POLLERR;
+    cs->pub.sense = CONN_SENSE_DEFAULT;
+    apr_pollset_add(event_pollset, &cs->pfd);
+    apr_thread_mutex_unlock(timeout_mutex);
+
+    return OK;
+}
+
 /* conns_this_child has gone to zero or below.  See if the admin coded
    "MaxConnectionsPerChild 0", and keep going in that case.  Doing it this way
    simplifies the hot path in worker_thread */
@@ -3478,6 +3509,7 @@ static void event_hooks(apr_pool_t * p)
                                         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);
+    ap_hook_mpm_resume_suspended(event_resume_suspended, NULL, NULL, APR_HOOK_MIDDLE);
 }
 
 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
index f459a1b1337ea47c40f66333429b9ff264576fa4..387c5cd06b0fc63aa0dcf56c1772d82e08b5b9e0 100644 (file)
@@ -72,6 +72,7 @@
     APR_HOOK_LINK(mpm_register_socket_callback_timeout) \
     APR_HOOK_LINK(mpm_unregister_socket_callback) \
     APR_HOOK_LINK(mpm_get_name) \
+    APR_HOOK_LINK(mpm_resume_suspended) \
     APR_HOOK_LINK(end_generation) \
     APR_HOOK_LINK(child_status) \
     APR_HOOK_LINK(suspend_connection) \
@@ -103,6 +104,9 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int, mpm_query,
 AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, mpm_register_timed_callback,
                             (apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton),
                             (t, cbfn, baton), APR_ENOTIMPL)
+AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, mpm_resume_suspended,
+                            (conn_rec *c),
+                            (c), APR_ENOTIMPL)
 AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, mpm_register_socket_callback,
                             (apr_socket_t **s, apr_pool_t *p, int for_read, ap_mpm_callback_fn_t *cbfn, void *baton),
                             (s, p, for_read, cbfn, baton), APR_ENOTIMPL)
@@ -547,6 +551,10 @@ void ap_core_child_status(server_rec *s, pid_t pid,
                  pid, gen, slot, status_msg);
 }
 
+AP_DECLARE(apr_status_t) ap_mpm_resume_suspended(conn_rec *c) {
+    return ap_run_mpm_resume_suspended(c);
+}
+
 AP_DECLARE(apr_status_t) ap_mpm_register_timed_callback(apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton)
 {
     return ap_run_mpm_register_timed_callback(t, cbfn, baton);