From fba67798ed9de00e5a33c18ba9cfe66caec06aa3 Mon Sep 17 00:00:00 2001 From: Eric Covener Date: Sun, 11 May 2014 20:52:32 +0000 Subject: [PATCH] PR56333: Add an API to resume a connection that a handler has previously suspended. Submitted by: Artem , Edward Lu Committed by: covener git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1593860 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 6 +++++- include/ap_mmn.h | 4 +++- include/ap_mpm.h | 4 ++++ include/httpd.h | 3 +++ include/mpm_common.h | 5 +++++ modules/test/mod_dialup.c | 12 +++++++++++- server/mpm/event/event.c | 32 ++++++++++++++++++++++++++++++++ server/mpm_common.c | 8 ++++++++ 8 files changed, 71 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 824eedbc60..ab0ce9a8a4 100644 --- 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 , Edward Lu ] + *) core: Add ap_mpm_register_socket_callback_timeout() API. [Eric Covener] *) mod_proxy_wstunnel: Honor ProxyWebsocketIdleTimeout in asynchronous diff --git a/include/ap_mmn.h b/include/ap_mmn.h index a3acb2505d..cbb31afc38 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -452,6 +452,8 @@ * 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" */ @@ -459,7 +461,7 @@ #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 diff --git a/include/ap_mpm.h b/include/ap_mpm.h index d851f35582..d50acd95e3 100644 --- a/include/ap_mpm.h +++ b/include/ap_mpm.h @@ -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, diff --git a/include/httpd.h b/include/httpd.h index 29985d2594..d458ad70ad 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -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 { diff --git a/include/mpm_common.h b/include/mpm_common.h index 44a693fbb3..4031b51ddf 100644 --- a/include/mpm_common.h +++ b/include/mpm_common.h @@ -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 diff --git a/modules/test/mod_dialup.c b/modules/test/mod_dialup.c index 93e9743080..b46097a825 100644 --- a/modules/test/mod_dialup.c +++ b/modules/test/mod_dialup.c @@ -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); diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index 58042f9170..7eb83cb032 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -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, diff --git a/server/mpm_common.c b/server/mpm_common.c index f459a1b133..387c5cd06b 100644 --- a/server/mpm_common.c +++ b/server/mpm_common.c @@ -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); -- 2.40.0