-*- 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
* 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
#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
/** @} */
/**
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,
/** context of this connection */
void *ctx;
+
+ /** Context under which this connection was suspended */
+ void *suspended_baton;
};
struct conn_slave_rec {
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
{
int status;
dialup_baton_t *db = (dialup_baton_t *)baton;
+ conn_rec *c = db->r->connection;
apr_thread_mutex_lock(db->r->invoke_mtx);
}
apr_thread_mutex_unlock(db->r->invoke_mtx);
+
+ ap_mpm_resume_suspended(c);
}
static int
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 ||
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);
case AP_MPMQ_GENERATION:
*result = retained->my_generation;
break;
+ case AP_MPMQ_CAN_SUSPEND:
+ *result = 1;
+ break;
default:
*rv = APR_ENOTIMPL;
break;
return;
}
else if (cs->pub.state == CONN_STATE_SUSPENDED) {
+ cs->c->suspended_baton = cs;
apr_atomic_inc32(&suspended_count);
}
/*
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 */
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,
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) \
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)
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);