summaryrefslogtreecommitdiffstats
path: root/modules/proxy/mod_proxy_hcheck.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-25 04:41:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-25 04:41:27 +0000
commitc54018b07a9085c0a3aedbc2bd01a85a3b3e20cf (patch)
treef6e1d6fcf9f6db3794c418b2f89ecf9e08ff41c8 /modules/proxy/mod_proxy_hcheck.c
parentAdding debian version 2.4.38-3+deb10u10. (diff)
downloadapache2-c54018b07a9085c0a3aedbc2bd01a85a3b3e20cf.tar.xz
apache2-c54018b07a9085c0a3aedbc2bd01a85a3b3e20cf.zip
Merging upstream version 2.4.59.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules/proxy/mod_proxy_hcheck.c')
-rw-r--r--modules/proxy/mod_proxy_hcheck.c348
1 files changed, 240 insertions, 108 deletions
diff --git a/modules/proxy/mod_proxy_hcheck.c b/modules/proxy/mod_proxy_hcheck.c
index 2783a58..70f1de8 100644
--- a/modules/proxy/mod_proxy_hcheck.c
+++ b/modules/proxy/mod_proxy_hcheck.c
@@ -20,6 +20,7 @@
#if APR_HAS_THREADS
#include "apr_thread_pool.h"
#endif
+#include "http_ssl.h"
module AP_MODULE_DECLARE_DATA proxy_hcheck_module;
@@ -33,7 +34,6 @@ module AP_MODULE_DECLARE_DATA proxy_hcheck_module;
#endif
#else
#define HC_USE_THREADS 0
-typedef void apr_thread_pool_t;
#endif
typedef struct {
@@ -65,6 +65,7 @@ typedef struct {
const char *method; /* Method string for the HTTP/AJP request */
const char *req; /* pre-formatted HTTP/AJP request */
proxy_worker *w; /* Pointer to the actual worker */
+ const char *protocol; /* HTTP 1.0 or 1.1? */
} wctx_t;
typedef struct {
@@ -73,9 +74,11 @@ typedef struct {
proxy_balancer *balancer;
proxy_worker *worker;
proxy_worker *hc;
- apr_time_t now;
+ apr_time_t *now;
} baton_t;
+static APR_OPTIONAL_FN_TYPE(ajp_handle_cping_cpong) *ajp_handle_cping_cpong = NULL;
+
static void *hc_create_config(apr_pool_t *p, server_rec *s)
{
sctx_t *ctx = apr_pcalloc(p, sizeof(sctx_t));
@@ -89,7 +92,10 @@ static void *hc_create_config(apr_pool_t *p, server_rec *s)
}
static ap_watchdog_t *watchdog;
-static int tpsize = HC_THREADPOOL_SIZE;
+#if HC_USE_THREADS
+static apr_thread_pool_t *hctp;
+static int tpsize;
+#endif
/*
* This serves double duty by not only validating (and creating)
@@ -110,6 +116,10 @@ static const char *set_worker_hc_param(apr_pool_t *p,
if (!worker && !v) {
return "Bad call to set_worker_hc_param()";
}
+ if (!ctx) {
+ ctx = hc_create_config(p, s);
+ ap_set_module_config(s->module_config, &proxy_hcheck_module, ctx);
+ }
temp = (hc_template_t *)v;
if (!strcasecmp(key, "hctemplate")) {
hc_template_t *template;
@@ -333,7 +343,8 @@ static const char *set_hc_tpsize (cmd_parms *cmd, void *dummy, const char *arg)
*/
static request_rec *create_request_rec(apr_pool_t *p, server_rec *s,
proxy_balancer *balancer,
- const char *method)
+ const char *method,
+ const char *protocol)
{
request_rec *r;
@@ -391,10 +402,12 @@ static request_rec *create_request_rec(apr_pool_t *p, server_rec *s,
else {
r->header_only = 0;
}
-
r->protocol = "HTTP/1.0";
r->proto_num = HTTP_VERSION(1, 0);
-
+ if ( protocol && (protocol[7] == '1') ) {
+ r->protocol = "HTTP/1.1";
+ r->proto_num = HTTP_VERSION(1, 1);
+ }
r->hostname = NULL;
return r;
@@ -418,31 +431,43 @@ static void create_hcheck_req(wctx_t *wctx, proxy_worker *hc,
{
char *req = NULL;
const char *method = NULL;
+ const char *protocol = NULL;
+
+ /* TODO: Fold into switch/case below? This seems more obvious */
+ if ( (hc->s->method == OPTIONS11) || (hc->s->method == HEAD11) || (hc->s->method == GET11) ) {
+ protocol = "HTTP/1.1";
+ } else {
+ protocol = "HTTP/1.0";
+ }
switch (hc->s->method) {
case OPTIONS:
+ case OPTIONS11:
method = "OPTIONS";
req = apr_psprintf(p,
- "OPTIONS * HTTP/1.0\r\n"
+ "OPTIONS * %s\r\n"
"Host: %s:%d\r\n"
- "\r\n",
+ "\r\n", protocol,
hc->s->hostname_ex, (int)hc->s->port);
break;
case HEAD:
+ case HEAD11:
method = "HEAD";
/* fallthru */
case GET:
+ case GET11:
if (!method) { /* did we fall thru? If not, we are GET */
method = "GET";
}
req = apr_psprintf(p,
- "%s %s%s%s HTTP/1.0\r\n"
+ "%s %s%s%s %s\r\n"
"Host: %s:%d\r\n"
"\r\n",
method,
(wctx->path ? wctx->path : ""),
(wctx->path && *hc->s->hcuri ? "/" : "" ),
(*hc->s->hcuri ? hc->s->hcuri : ""),
+ protocol,
hc->s->hostname_ex, (int)hc->s->port);
break;
@@ -451,6 +476,7 @@ static void create_hcheck_req(wctx_t *wctx, proxy_worker *hc,
}
wctx->req = req;
wctx->method = method;
+ wctx->protocol = protocol;
}
static proxy_worker *hc_get_hcworker(sctx_t *ctx, proxy_worker *worker,
@@ -463,7 +489,7 @@ static proxy_worker *hc_get_hcworker(sctx_t *ctx, proxy_worker *worker,
if (!hc) {
apr_uri_t uri;
apr_status_t rv;
- const char *url = worker->s->name;
+ const char *url = worker->s->name_ex;
wctx_t *wctx = apr_pcalloc(ctx->p, sizeof(wctx_t));
port = (worker->s->port ? worker->s->port
@@ -473,16 +499,25 @@ static proxy_worker *hc_get_hcworker(sctx_t *ctx, proxy_worker *worker,
worker, worker->s->scheme, worker->s->hostname_ex,
(int)port);
- ap_proxy_define_worker(ctx->p, &hc, NULL, NULL, worker->s->name, 0);
+ ap_proxy_define_worker(ctx->p, &hc, NULL, NULL, worker->s->name_ex, 0);
apr_snprintf(hc->s->name, sizeof hc->s->name, "%pp", worker);
+ apr_snprintf(hc->s->name_ex, sizeof hc->s->name_ex, "%pp", worker);
PROXY_STRNCPY(hc->s->hostname, worker->s->hostname); /* for compatibility */
PROXY_STRNCPY(hc->s->hostname_ex, worker->s->hostname_ex);
PROXY_STRNCPY(hc->s->scheme, worker->s->scheme);
PROXY_STRNCPY(hc->s->hcuri, worker->s->hcuri);
PROXY_STRNCPY(hc->s->hcexpr, worker->s->hcexpr);
- hc->hash.def = hc->s->hash.def = ap_proxy_hashfunc(hc->s->name, PROXY_HASHFUNC_DEFAULT);
- hc->hash.fnv = hc->s->hash.fnv = ap_proxy_hashfunc(hc->s->name, PROXY_HASHFUNC_FNV);
+ hc->hash.def = hc->s->hash.def = ap_proxy_hashfunc(hc->s->name_ex,
+ PROXY_HASHFUNC_DEFAULT);
+ hc->hash.fnv = hc->s->hash.fnv = ap_proxy_hashfunc(hc->s->name_ex,
+ PROXY_HASHFUNC_FNV);
hc->s->port = port;
+ hc->s->conn_timeout_set = worker->s->conn_timeout_set;
+ hc->s->conn_timeout = worker->s->conn_timeout;
+ hc->s->ping_timeout_set = worker->s->ping_timeout_set;
+ hc->s->ping_timeout = worker->s->ping_timeout;
+ hc->s->timeout_set = worker->s->timeout_set;
+ hc->s->timeout = worker->s->timeout;
/* Do not disable worker in case of errors */
hc->s->status |= PROXY_WORKER_IGNORE_ERRORS;
/* Mark as the "generic" worker */
@@ -516,33 +551,78 @@ static proxy_worker *hc_get_hcworker(sctx_t *ctx, proxy_worker *worker,
return hc;
}
-static int hc_determine_connection(sctx_t *ctx, proxy_worker *worker,
- apr_sockaddr_t **addr, apr_pool_t *p)
+static int hc_determine_connection(const char *proxy_function,
+ proxy_conn_rec *backend,
+ server_rec *s)
{
- apr_status_t rv = APR_SUCCESS;
+ proxy_worker *worker = backend->worker;
+ apr_status_t rv;
+
/*
* normally, this is done in ap_proxy_determine_connection().
* TODO: Look at using ap_proxy_determine_connection() with a
* fake request_rec
*/
- if (worker->cp->addr) {
- *addr = worker->cp->addr;
+ rv = ap_proxy_determine_address(proxy_function, backend,
+ worker->s->hostname_ex, worker->s->port,
+ 0, NULL, s);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(03249)
+ "DNS lookup failure for: %s:%hu",
+ worker->s->hostname_ex, worker->s->port);
+ return !OK;
}
- else {
- rv = apr_sockaddr_info_get(addr, worker->s->hostname_ex,
- APR_UNSPEC, worker->s->port, 0, p);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ctx->s, APLOGNO(03249)
- "DNS lookup failure for: %s:%d",
- worker->s->hostname_ex, (int)worker->s->port);
+
+ return OK;
+}
+
+static apr_status_t backend_cleanup(const char *proxy_function, proxy_conn_rec *backend,
+ server_rec *s, int status)
+{
+ if (backend) {
+ backend->close = 1;
+ ap_proxy_release_connection(proxy_function, backend, s);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(03251)
+ "Health check %s Status (%d) for %s.",
+ ap_proxy_show_hcmethod(backend->worker->s->method),
+ status,
+ backend->worker->s->name_ex);
+ }
+ if (status != OK) {
+ return APR_EGENERAL;
+ }
+ return APR_SUCCESS;
+}
+
+static int hc_get_backend(const char *proxy_function, proxy_conn_rec **backend,
+ proxy_worker *hc, sctx_t *ctx)
+{
+ int status;
+
+ status = ap_proxy_acquire_connection(proxy_function, backend, hc, ctx->s);
+ if (status != OK) {
+ return status;
+ }
+
+ if (strcmp(hc->s->scheme, "https") == 0 || strcmp(hc->s->scheme, "wss") == 0 ) {
+ if (!ap_ssl_has_outgoing_handlers()) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ctx->s, APLOGNO(03252)
+ "mod_ssl not configured?");
+ return !OK;
}
+ (*backend)->is_ssl = 1;
}
- return (rv == APR_SUCCESS ? OK : !OK);
+
+ return hc_determine_connection(proxy_function, *backend, ctx->s);
}
-static apr_status_t hc_init_worker(sctx_t *ctx, proxy_worker *worker)
+static apr_status_t hc_init_baton(baton_t *baton)
{
+ sctx_t *ctx = baton->ctx;
+ proxy_worker *worker = baton->worker, *hc;
apr_status_t rv = APR_SUCCESS;
+ int once = 0;
+
/*
* Since this is the watchdog, workers never actually handle a
* request here, and so the local data isn't initialized (of
@@ -555,52 +635,67 @@ static apr_status_t hc_init_worker(sctx_t *ctx, proxy_worker *worker)
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ctx->s, APLOGNO(03250) "Cannot init worker");
return rv;
}
- if (worker->s->is_address_reusable && !worker->s->disablereuse &&
- hc_determine_connection(ctx, worker, &worker->cp->addr,
- worker->cp->pool) != OK) {
+ once = 1;
+ }
+
+ baton->hc = hc = hc_get_hcworker(ctx, worker, baton->ptemp);
+
+ /* Try to resolve the worker address once if it's reusable */
+ if (once && worker->s->is_address_reusable) {
+ proxy_conn_rec *backend = NULL;
+ if (hc_get_backend("HCHECK", &backend, hc, ctx)) {
rv = APR_EGENERAL;
}
+ if (backend) {
+ backend->close = 1;
+ ap_proxy_release_connection("HCHECK", backend, ctx->s);
+ }
}
- return rv;
-}
-static apr_status_t backend_cleanup(const char *proxy_function, proxy_conn_rec *backend,
- server_rec *s, int status)
-{
- if (backend) {
- backend->close = 1;
- ap_proxy_release_connection(proxy_function, backend, s);
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(03251)
- "Health check %s Status (%d) for %s.",
- ap_proxy_show_hcmethod(backend->worker->s->method),
- status,
- backend->worker->s->name);
- }
- if (status != OK) {
- return APR_EGENERAL;
- }
- return APR_SUCCESS;
+ return rv;
}
-static int hc_get_backend(const char *proxy_function, proxy_conn_rec **backend,
- proxy_worker *hc, sctx_t *ctx, apr_pool_t *ptemp)
+static apr_status_t hc_check_cping(baton_t *baton, apr_thread_t *thread)
{
int status;
- status = ap_proxy_acquire_connection(proxy_function, backend, hc, ctx->s);
- if (status == OK) {
- (*backend)->addr = hc->cp->addr;
- (*backend)->hostname = hc->s->hostname_ex;
- if (strcmp(hc->s->scheme, "https") == 0) {
- if (!ap_proxy_ssl_enable(NULL)) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ctx->s, APLOGNO(03252)
- "mod_ssl not configured?");
- return !OK;
- }
- (*backend)->is_ssl = 1;
- }
+ sctx_t *ctx = baton->ctx;
+ proxy_worker *hc = baton->hc;
+ proxy_conn_rec *backend = NULL;
+ apr_pool_t *ptemp = baton->ptemp;
+ request_rec *r;
+ apr_interval_time_t timeout;
+ if (!ajp_handle_cping_cpong) {
+ return APR_ENOTIMPL;
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, baton->ctx->s, "HCCPING starting");
+ if ((status = hc_get_backend("HCCPING", &backend, hc, ctx)) != OK) {
+ return backend_cleanup("HCCPING", backend, ctx->s, status);
+ }
+ if ((status = ap_proxy_connect_backend("HCCPING", backend, hc, ctx->s)) != OK) {
+ return backend_cleanup("HCCPING", backend, ctx->s, status);
}
- return hc_determine_connection(ctx, hc, &(*backend)->addr, ptemp);
+ r = create_request_rec(ptemp, ctx->s, baton->balancer, "CPING", NULL);
+ if ((status = ap_proxy_connection_create_ex("HCCPING", backend, r)) != OK) {
+ return backend_cleanup("HCCPING", backend, ctx->s, status);
+ }
+ set_request_connection(r, backend->connection);
+ backend->connection->current_thread = thread;
+
+ if (hc->s->ping_timeout_set) {
+ timeout = hc->s->ping_timeout;
+ } else if ( hc->s->conn_timeout_set) {
+ timeout = hc->s->conn_timeout;
+ } else if ( hc->s->timeout_set) {
+ timeout = hc->s->timeout;
+ } else {
+ /* default to socket timeout */
+ apr_socket_timeout_get(backend->sock, &timeout);
+ }
+ status = ajp_handle_cping_cpong(backend->sock, r, timeout);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, baton->ctx->s, "HCCPING done %d", status);
+ return backend_cleanup("HCCPING", backend, ctx->s, status);
}
static apr_status_t hc_check_tcp(baton_t *baton)
@@ -610,7 +705,7 @@ static apr_status_t hc_check_tcp(baton_t *baton)
proxy_worker *hc = baton->hc;
proxy_conn_rec *backend = NULL;
- status = hc_get_backend("HCTCP", &backend, hc, ctx, baton->ptemp);
+ status = hc_get_backend("HCTCP", &backend, hc, ctx);
if (status == OK) {
status = ap_proxy_connect_backend("HCTCP", backend, hc, ctx->s);
/* does an unconditional ap_proxy_is_socket_connected() */
@@ -636,6 +731,7 @@ static int hc_read_headers(request_rec *r)
{
char buffer[HUGE_STRING_LEN];
int len;
+ const char *ct;
len = ap_getline(buffer, sizeof(buffer), r, 1);
if (len <= 0) {
@@ -670,6 +766,7 @@ static int hc_read_headers(request_rec *r)
} else {
return !OK;
}
+
/* OK, 1st line is OK... scarf in the headers */
while ((len = ap_getline(buffer, sizeof(buffer), r, 1)) > 0) {
char *value, *end;
@@ -686,6 +783,11 @@ static int hc_read_headers(request_rec *r)
*end = '\0';
apr_table_add(r->headers_out, buffer, value);
}
+
+ /* Set the Content-Type for the request if set */
+ if ((ct = apr_table_get(r->headers_out, "Content-Type")) != NULL)
+ ap_set_content_type(r, ct);
+
return OK;
}
@@ -736,7 +838,7 @@ static int hc_read_body(request_rec *r, apr_bucket_brigade *bb)
* then apply those to the resulting response, otherwise
* any status code 2xx or 3xx is considered "passing"
*/
-static apr_status_t hc_check_http(baton_t *baton)
+static apr_status_t hc_check_http(baton_t *baton, apr_thread_t *thread)
{
int status;
proxy_conn_rec *backend = NULL;
@@ -754,20 +856,19 @@ static apr_status_t hc_check_http(baton_t *baton)
return APR_ENOTIMPL;
}
- if ((status = hc_get_backend("HCOH", &backend, hc, ctx, ptemp)) != OK) {
+ if ((status = hc_get_backend("HCOH", &backend, hc, ctx)) != OK) {
return backend_cleanup("HCOH", backend, ctx->s, status);
}
if ((status = ap_proxy_connect_backend("HCOH", backend, hc, ctx->s)) != OK) {
return backend_cleanup("HCOH", backend, ctx->s, status);
}
- r = create_request_rec(ptemp, ctx->s, baton->balancer, wctx->method);
- if (!backend->connection) {
- if ((status = ap_proxy_connection_create_ex("HCOH", backend, r)) != OK) {
- return backend_cleanup("HCOH", backend, ctx->s, status);
- }
+ r = create_request_rec(ptemp, ctx->s, baton->balancer, wctx->method, wctx->protocol);
+ if ((status = ap_proxy_connection_create_ex("HCOH", backend, r)) != OK) {
+ return backend_cleanup("HCOH", backend, ctx->s, status);
}
set_request_connection(r, backend->connection);
+ backend->connection->current_thread = thread;
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
@@ -796,22 +897,22 @@ static apr_status_t hc_check_http(baton_t *baton)
if (ok > 0) {
ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, ctx->s,
"Condition %s for %s (%s): passed", worker->s->hcexpr,
- hc->s->name, worker->s->name);
+ hc->s->name_ex, worker->s->name_ex);
} else if (ok < 0 || err) {
ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctx->s, APLOGNO(03301)
"Error on checking condition %s for %s (%s): %s", worker->s->hcexpr,
- hc->s->name, worker->s->name, err);
+ hc->s->name_ex, worker->s->name_ex, err);
status = !OK;
} else {
ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, ctx->s,
"Condition %s for %s (%s) : failed", worker->s->hcexpr,
- hc->s->name, worker->s->name);
+ hc->s->name_ex, worker->s->name_ex);
status = !OK;
}
} else if (r->status < 200 || r->status > 399) {
ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, ctx->s,
"Response status %i for %s (%s): failed", r->status,
- hc->s->name, worker->s->name);
+ hc->s->name_ex, worker->s->name_ex);
status = !OK;
}
return backend_cleanup("HCOH", backend, ctx->s, status);
@@ -823,29 +924,31 @@ static void * APR_THREAD_FUNC hc_check(apr_thread_t *thread, void *b)
server_rec *s = baton->ctx->s;
proxy_worker *worker = baton->worker;
proxy_worker *hc = baton->hc;
- apr_time_t now = baton->now;
+ apr_time_t now;
apr_status_t rv;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(03256)
"%sHealth checking %s", (thread ? "Threaded " : ""),
- worker->s->name);
+ worker->s->name_ex);
- worker->s->updated = now;
if (hc->s->method == TCP) {
rv = hc_check_tcp(baton);
}
+ else if (hc->s->method == CPING) {
+ rv = hc_check_cping(baton, thread);
+ }
else {
- rv = hc_check_http(baton);
+ rv = hc_check_http(baton, thread);
}
+
+ now = apr_time_now();
if (rv == APR_ENOTIMPL) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(03257)
"Somehow tried to use unimplemented hcheck method: %d",
(int)hc->s->method);
- apr_pool_destroy(baton->ptemp);
- return NULL;
}
/* what state are we in ? */
- if (PROXY_WORKER_IS_HCFAILED(worker)) {
+ else if (PROXY_WORKER_IS_HCFAILED(worker) || PROXY_WORKER_IS_ERROR(worker)) {
if (rv == APR_SUCCESS) {
worker->s->pcount += 1;
if (worker->s->pcount >= worker->s->passes) {
@@ -854,11 +957,12 @@ static void * APR_THREAD_FUNC hc_check(apr_thread_t *thread, void *b)
worker->s->pcount = 0;
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(03302)
"%sHealth check ENABLING %s", (thread ? "Threaded " : ""),
- worker->s->name);
+ worker->s->name_ex);
}
}
- } else {
+ }
+ else {
if (rv != APR_SUCCESS) {
worker->s->error_time = now;
worker->s->fcount += 1;
@@ -867,11 +971,16 @@ static void * APR_THREAD_FUNC hc_check(apr_thread_t *thread, void *b)
worker->s->fcount = 0;
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(03303)
"%sHealth check DISABLING %s", (thread ? "Threaded " : ""),
- worker->s->name);
+ worker->s->name_ex);
}
}
}
+ if (baton->now) {
+ *baton->now = now;
+ }
apr_pool_destroy(baton->ptemp);
+ worker->s->updated = now;
+
return NULL;
}
@@ -879,12 +988,10 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
apr_pool_t *pool)
{
apr_status_t rv = APR_SUCCESS;
- apr_time_t now = apr_time_now();
proxy_balancer *balancer;
sctx_t *ctx = (sctx_t *)data;
server_rec *s = ctx->s;
proxy_server_conf *conf;
- static apr_thread_pool_t *hctp = NULL;
switch (state) {
case AP_WATCHDOG_STATE_STARTING:
@@ -911,15 +1018,11 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
"Skipping apr_thread_pool_create()");
hctp = NULL;
}
-
#endif
break;
case AP_WATCHDOG_STATE_RUNNING:
/* loop thru all workers */
- ap_log_error(APLOG_MARK, APLOG_TRACE5, 0, s,
- "Run of %s watchdog.",
- HCHECK_WATHCHDOG_NAME);
if (s) {
int i;
conf = (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
@@ -927,45 +1030,52 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
ctx->s = s;
for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
int n;
+ apr_time_t now;
proxy_worker **workers;
proxy_worker *worker;
/* Have any new balancers or workers been added dynamically? */
ap_proxy_sync_balancer(balancer, s, conf);
workers = (proxy_worker **)balancer->workers->elts;
+ now = apr_time_now();
for (n = 0; n < balancer->workers->nelts; n++) {
worker = *workers;
if (!PROXY_WORKER_IS(worker, PROXY_WORKER_STOPPED) &&
- (worker->s->method != NONE) &&
- (now > worker->s->updated + worker->s->interval)) {
+ (worker->s->method != NONE) &&
+ (worker->s->updated != 0) &&
+ (now > worker->s->updated + worker->s->interval)) {
baton_t *baton;
apr_pool_t *ptemp;
+
ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s,
"Checking %s worker: %s [%d] (%pp)", balancer->s->name,
- worker->s->name, worker->s->method, worker);
+ worker->s->name_ex, worker->s->method, worker);
- if ((rv = hc_init_worker(ctx, worker)) != APR_SUCCESS) {
- return rv;
- }
- /* This pool must last the lifetime of the (possible) thread */
+ /* This pool has the lifetime of the check */
apr_pool_create(&ptemp, ctx->p);
apr_pool_tag(ptemp, "hc_request");
- baton = apr_palloc(ptemp, sizeof(baton_t));
+ baton = apr_pcalloc(ptemp, sizeof(baton_t));
baton->ctx = ctx;
- baton->now = now;
baton->balancer = balancer;
baton->worker = worker;
baton->ptemp = ptemp;
- baton->hc = hc_get_hcworker(ctx, worker, ptemp);
-
- if (!hctp) {
- hc_check(NULL, baton);
+ if ((rv = hc_init_baton(baton))) {
+ worker->s->updated = now;
+ apr_pool_destroy(ptemp);
+ return rv;
}
+ worker->s->updated = 0;
#if HC_USE_THREADS
- else {
- rv = apr_thread_pool_push(hctp, hc_check, (void *)baton,
- APR_THREAD_TASK_PRIORITY_NORMAL, NULL);
+ if (hctp) {
+ apr_thread_pool_push(hctp, hc_check, (void *)baton,
+ APR_THREAD_TASK_PRIORITY_NORMAL,
+ NULL);
}
+ else
#endif
+ {
+ baton->now = &now;
+ hc_check(NULL, baton);
+ }
}
workers++;
}
@@ -984,9 +1094,9 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
ap_log_error(APLOG_MARK, APLOG_INFO, rv, s, APLOGNO(03315)
"apr_thread_pool_destroy() failed");
}
+ hctp = NULL;
}
#endif
- hctp = NULL;
break;
}
return rv;
@@ -994,7 +1104,22 @@ static apr_status_t hc_watchdog_callback(int state, void *data,
static int hc_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptemp)
{
+#if HC_USE_THREADS
+ hctp = NULL;
tpsize = HC_THREADPOOL_SIZE;
+#endif
+
+ ajp_handle_cping_cpong = APR_RETRIEVE_OPTIONAL_FN(ajp_handle_cping_cpong);
+ if (ajp_handle_cping_cpong) {
+ proxy_hcmethods_t *method = proxy_hcmethods;
+ for (; method->name; method++) {
+ if (method->method == CPING) {
+ method->implemented = 1;
+ break;
+ }
+ }
+ }
+
return OK;
}
static int hc_post_config(apr_pool_t *p, apr_pool_t *plog,
@@ -1050,6 +1175,7 @@ static int hc_post_config(apr_pool_t *p, apr_pool_t *plog,
"watchdog callback registered (%s for %s)", HCHECK_WATHCHDOG_NAME, s->server_hostname);
s = s->next;
}
+
return OK;
}
@@ -1060,6 +1186,8 @@ static void hc_show_exprs(request_rec *r)
int i;
sctx_t *ctx = (sctx_t *) ap_get_module_config(r->server->module_config,
&proxy_hcheck_module);
+ if (!ctx)
+ return;
if (apr_is_empty_table(ctx->conditions))
return;
@@ -1089,6 +1217,8 @@ static void hc_select_exprs(request_rec *r, const char *expr)
int i;
sctx_t *ctx = (sctx_t *) ap_get_module_config(r->server->module_config,
&proxy_hcheck_module);
+ if (!ctx)
+ return;
if (apr_is_empty_table(ctx->conditions))
return;
@@ -1112,6 +1242,8 @@ static int hc_valid_expr(request_rec *r, const char *expr)
int i;
sctx_t *ctx = (sctx_t *) ap_get_module_config(r->server->module_config,
&proxy_hcheck_module);
+ if (!ctx)
+ return 0;
if (apr_is_empty_table(ctx->conditions))
return 0;