|
Packit |
90a5c9 |
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
Packit |
90a5c9 |
* contributor license agreements. See the NOTICE file distributed with
|
|
Packit |
90a5c9 |
* this work for additional information regarding copyright ownership.
|
|
Packit |
90a5c9 |
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
Packit |
90a5c9 |
* (the "License"); you may not use this file except in compliance with
|
|
Packit |
90a5c9 |
* the License. You may obtain a copy of the License at
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
90a5c9 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
90a5c9 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
90a5c9 |
* See the License for the specific language governing permissions and
|
|
Packit |
90a5c9 |
* limitations under the License.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Watchdog module.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "apr.h"
|
|
Packit |
90a5c9 |
#include "mod_watchdog.h"
|
|
Packit |
90a5c9 |
#include "ap_provider.h"
|
|
Packit |
90a5c9 |
#include "ap_mpm.h"
|
|
Packit |
90a5c9 |
#include "http_core.h"
|
|
Packit |
90a5c9 |
#include "util_mutex.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define AP_WATCHDOG_PGROUP "watchdog"
|
|
Packit |
90a5c9 |
#define AP_WATCHDOG_PVERSION "parent"
|
|
Packit |
90a5c9 |
#define AP_WATCHDOG_CVERSION "child"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct watchdog_list_t watchdog_list_t;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct watchdog_list_t
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
struct watchdog_list_t *next;
|
|
Packit |
90a5c9 |
ap_watchdog_t *wd;
|
|
Packit |
90a5c9 |
apr_status_t status;
|
|
Packit |
90a5c9 |
apr_interval_time_t interval;
|
|
Packit |
90a5c9 |
apr_interval_time_t step;
|
|
Packit |
90a5c9 |
const void *data;
|
|
Packit |
90a5c9 |
ap_watchdog_callback_fn_t *callback_fn;
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct ap_watchdog_t
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_thread_mutex_t *startup;
|
|
Packit |
90a5c9 |
apr_proc_mutex_t *mutex;
|
|
Packit |
90a5c9 |
const char *name;
|
|
Packit |
90a5c9 |
watchdog_list_t *callbacks;
|
|
Packit |
90a5c9 |
int is_running;
|
|
Packit |
90a5c9 |
int singleton;
|
|
Packit |
90a5c9 |
int active;
|
|
Packit |
90a5c9 |
apr_interval_time_t step;
|
|
Packit |
90a5c9 |
apr_thread_t *thread;
|
|
Packit |
90a5c9 |
apr_pool_t *pool;
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct wd_server_conf_t wd_server_conf_t;
|
|
Packit |
90a5c9 |
struct wd_server_conf_t
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int child_workers;
|
|
Packit |
90a5c9 |
int parent_workers;
|
|
Packit |
90a5c9 |
apr_pool_t *pool;
|
|
Packit |
90a5c9 |
server_rec *s;
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static wd_server_conf_t *wd_server_conf = NULL;
|
|
Packit |
90a5c9 |
static apr_interval_time_t wd_interval = AP_WD_TM_INTERVAL;
|
|
Packit |
90a5c9 |
static int mpm_is_forked = AP_MPMQ_NOT_SUPPORTED;
|
|
Packit |
90a5c9 |
static const char *wd_proc_mutex_type = "watchdog-callback";
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t wd_worker_cleanup(void *data)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
ap_watchdog_t *w = (ap_watchdog_t *)data;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (w->is_running) {
|
|
Packit |
90a5c9 |
watchdog_list_t *wl = w->callbacks;
|
|
Packit |
90a5c9 |
while (wl) {
|
|
Packit |
90a5c9 |
if (wl->status == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
/* Execute watchdog callback with STOPPING state */
|
|
Packit |
90a5c9 |
(*wl->callback_fn)(AP_WATCHDOG_STATE_STOPPING,
|
|
Packit |
90a5c9 |
(void *)wl->data, w->pool);
|
|
Packit |
90a5c9 |
wl->status = APR_EOF;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
wl = wl->next;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
w->is_running = 0;
|
|
Packit |
90a5c9 |
apr_thread_join(&rv, w->thread);
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/* Main watchdog worker thread. */
|
|
Packit |
90a5c9 |
/* For singleton workers child thread that first obtains the process */
|
|
Packit |
90a5c9 |
/* mutex is running. Threads in other child's are locked on mutex. */
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
static void* APR_THREAD_FUNC wd_worker(apr_thread_t *thread, void *data)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
ap_watchdog_t *w = (ap_watchdog_t *)data;
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
int locked = 0;
|
|
Packit |
90a5c9 |
int probed = 0;
|
|
Packit |
90a5c9 |
int inited = 0;
|
|
Packit |
90a5c9 |
int mpmq_s = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
w->pool = apr_thread_pool_get(thread);
|
|
Packit |
90a5c9 |
w->is_running = 1;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_thread_mutex_unlock(w->startup);
|
|
Packit |
90a5c9 |
if (w->mutex) {
|
|
Packit |
90a5c9 |
while (w->is_running) {
|
|
Packit |
90a5c9 |
if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
w->is_running = 0;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (mpmq_s == AP_MPMQ_STOPPING) {
|
|
Packit |
90a5c9 |
w->is_running = 0;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
rv = apr_proc_mutex_trylock(w->mutex);
|
|
Packit |
90a5c9 |
if (rv == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
if (probed) {
|
|
Packit |
90a5c9 |
/* Sleep after we were locked
|
|
Packit |
90a5c9 |
* up to 1 second. Httpd can be
|
|
Packit |
90a5c9 |
* in the middle of shutdown, and
|
|
Packit |
90a5c9 |
* our child didn't yet received
|
|
Packit |
90a5c9 |
* the shutdown signal.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
probed = 10;
|
|
Packit |
90a5c9 |
while (w->is_running && probed > 0) {
|
|
Packit |
90a5c9 |
apr_sleep(AP_WD_TM_INTERVAL);
|
|
Packit |
90a5c9 |
probed--;
|
|
Packit |
90a5c9 |
if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
w->is_running = 0;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (mpmq_s == AP_MPMQ_STOPPING) {
|
|
Packit |
90a5c9 |
w->is_running = 0;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
locked = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
probed = 1;
|
|
Packit |
90a5c9 |
apr_sleep(AP_WD_TM_SLICE);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (w->is_running) {
|
|
Packit |
90a5c9 |
watchdog_list_t *wl = w->callbacks;
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd_server_conf->s,
|
|
Packit |
90a5c9 |
APLOGNO(02972) "%sWatchdog (%s) running",
|
|
Packit |
90a5c9 |
w->singleton ? "Singleton " : "", w->name);
|
|
Packit |
90a5c9 |
apr_time_clock_hires(w->pool);
|
|
Packit |
90a5c9 |
if (wl) {
|
|
Packit |
90a5c9 |
apr_pool_t *ctx = NULL;
|
|
Packit |
90a5c9 |
apr_pool_create(&ctx, w->pool);
|
|
Packit |
90a5c9 |
while (wl && w->is_running) {
|
|
Packit |
90a5c9 |
/* Execute watchdog callback */
|
|
Packit |
90a5c9 |
wl->status = (*wl->callback_fn)(AP_WATCHDOG_STATE_STARTING,
|
|
Packit |
90a5c9 |
(void *)wl->data, ctx);
|
|
Packit |
90a5c9 |
wl = wl->next;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
apr_pool_destroy(ctx);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
ap_run_watchdog_init(wd_server_conf->s, w->name, w->pool);
|
|
Packit |
90a5c9 |
inited = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Main execution loop */
|
|
Packit |
90a5c9 |
while (w->is_running) {
|
|
Packit |
90a5c9 |
apr_pool_t *ctx = NULL;
|
|
Packit |
90a5c9 |
apr_time_t curr;
|
|
Packit |
90a5c9 |
watchdog_list_t *wl = w->callbacks;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_sleep(AP_WD_TM_SLICE);
|
|
Packit |
90a5c9 |
if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
w->is_running = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (mpmq_s == AP_MPMQ_STOPPING) {
|
|
Packit |
90a5c9 |
w->is_running = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!w->is_running) {
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
curr = apr_time_now() - AP_WD_TM_SLICE;
|
|
Packit |
90a5c9 |
while (wl && w->is_running) {
|
|
Packit |
90a5c9 |
if (wl->status == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
wl->step += (apr_time_now() - curr);
|
|
Packit |
90a5c9 |
if (wl->step >= wl->interval) {
|
|
Packit |
90a5c9 |
if (!ctx)
|
|
Packit |
90a5c9 |
apr_pool_create(&ctx, w->pool);
|
|
Packit |
90a5c9 |
wl->step = 0;
|
|
Packit |
90a5c9 |
/* Execute watchdog callback */
|
|
Packit |
90a5c9 |
wl->status = (*wl->callback_fn)(AP_WATCHDOG_STATE_RUNNING,
|
|
Packit |
90a5c9 |
(void *)wl->data, ctx);
|
|
Packit |
90a5c9 |
if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
w->is_running = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (mpmq_s == AP_MPMQ_STOPPING) {
|
|
Packit |
90a5c9 |
w->is_running = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
wl = wl->next;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (w->is_running && w->callbacks == NULL) {
|
|
Packit |
90a5c9 |
/* This is hook mode watchdog
|
|
Packit |
90a5c9 |
* running on WatchogInterval
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
w->step += (apr_time_now() - curr);
|
|
Packit |
90a5c9 |
if (w->step >= wd_interval) {
|
|
Packit |
90a5c9 |
if (!ctx)
|
|
Packit |
90a5c9 |
apr_pool_create(&ctx, w->pool);
|
|
Packit |
90a5c9 |
w->step = 0;
|
|
Packit |
90a5c9 |
/* Run watchdog step hook */
|
|
Packit |
90a5c9 |
ap_run_watchdog_step(wd_server_conf->s, w->name, ctx);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (ctx)
|
|
Packit |
90a5c9 |
apr_pool_destroy(ctx);
|
|
Packit |
90a5c9 |
if (!w->is_running) {
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (inited) {
|
|
Packit |
90a5c9 |
/* Run the watchdog exit hooks.
|
|
Packit |
90a5c9 |
* If this was singleton watchdog the init hook
|
|
Packit |
90a5c9 |
* might never been called, so skip the exit hook
|
|
Packit |
90a5c9 |
* in that case as well.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
ap_run_watchdog_exit(wd_server_conf->s, w->name, w->pool);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
watchdog_list_t *wl = w->callbacks;
|
|
Packit |
90a5c9 |
while (wl) {
|
|
Packit |
90a5c9 |
if (wl->status == APR_SUCCESS) {
|
|
Packit |
90a5c9 |
/* Execute watchdog callback with STOPPING state */
|
|
Packit |
90a5c9 |
(*wl->callback_fn)(AP_WATCHDOG_STATE_STOPPING,
|
|
Packit |
90a5c9 |
(void *)wl->data, w->pool);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
wl = wl->next;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd_server_conf->s,
|
|
Packit |
90a5c9 |
APLOGNO(02973) "%sWatchdog (%s) stopping",
|
|
Packit |
90a5c9 |
w->singleton ? "Singleton " : "", w->name);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (locked)
|
|
Packit |
90a5c9 |
apr_proc_mutex_unlock(w->mutex);
|
|
Packit |
90a5c9 |
apr_thread_exit(w->thread, APR_SUCCESS);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t wd_startup(ap_watchdog_t *w, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rc;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Create thread startup mutex */
|
|
Packit |
90a5c9 |
rc = apr_thread_mutex_create(&w->startup, APR_THREAD_MUTEX_UNNESTED, p);
|
|
Packit |
90a5c9 |
if (rc != APR_SUCCESS)
|
|
Packit |
90a5c9 |
return rc;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (w->singleton) {
|
|
Packit |
90a5c9 |
/* Initialize singleton mutex in child */
|
|
Packit |
90a5c9 |
rc = apr_proc_mutex_child_init(&w->mutex,
|
|
Packit |
90a5c9 |
apr_proc_mutex_lockfile(w->mutex), p);
|
|
Packit |
90a5c9 |
if (rc != APR_SUCCESS)
|
|
Packit |
90a5c9 |
return rc;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* This mutex fixes problems with a fast start/fast end, where the pool
|
|
Packit |
90a5c9 |
* cleanup was being invoked before the thread completely spawned.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
apr_thread_mutex_lock(w->startup);
|
|
Packit |
90a5c9 |
apr_pool_pre_cleanup_register(p, w, wd_worker_cleanup);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Start the newly created watchdog */
|
|
Packit |
90a5c9 |
rc = apr_thread_create(&w->thread, NULL, wd_worker, w, p);
|
|
Packit |
90a5c9 |
if (rc) {
|
|
Packit |
90a5c9 |
apr_pool_cleanup_kill(p, w, wd_worker_cleanup);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_thread_mutex_lock(w->startup);
|
|
Packit |
90a5c9 |
apr_thread_mutex_unlock(w->startup);
|
|
Packit |
90a5c9 |
apr_thread_mutex_destroy(w->startup);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return rc;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t ap_watchdog_get_instance(ap_watchdog_t **watchdog,
|
|
Packit |
90a5c9 |
const char *name,
|
|
Packit |
90a5c9 |
int parent,
|
|
Packit |
90a5c9 |
int singleton,
|
|
Packit |
90a5c9 |
apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
ap_watchdog_t *w;
|
|
Packit |
90a5c9 |
const char *pver = parent ? AP_WATCHDOG_PVERSION : AP_WATCHDOG_CVERSION;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (parent && mpm_is_forked != AP_MPMQ_NOT_SUPPORTED) {
|
|
Packit |
90a5c9 |
/* Parent threads are not supported for
|
|
Packit |
90a5c9 |
* forked mpm's
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
*watchdog = NULL;
|
|
Packit |
90a5c9 |
return APR_ENOTIMPL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
w = ap_lookup_provider(AP_WATCHDOG_PGROUP, name, pver);
|
|
Packit |
90a5c9 |
if (w) {
|
|
Packit |
90a5c9 |
*watchdog = w;
|
|
Packit |
90a5c9 |
return APR_SUCCESS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
w = apr_pcalloc(p, sizeof(ap_watchdog_t));
|
|
Packit |
90a5c9 |
w->name = name;
|
|
Packit |
90a5c9 |
w->pool = p;
|
|
Packit |
90a5c9 |
w->singleton = parent ? 0 : singleton;
|
|
Packit |
90a5c9 |
*watchdog = w;
|
|
Packit |
90a5c9 |
return ap_register_provider(p, AP_WATCHDOG_PGROUP, name,
|
|
Packit |
90a5c9 |
pver, *watchdog);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t ap_watchdog_set_callback_interval(ap_watchdog_t *w,
|
|
Packit |
90a5c9 |
apr_interval_time_t interval,
|
|
Packit |
90a5c9 |
const void *data,
|
|
Packit |
90a5c9 |
ap_watchdog_callback_fn_t *callback)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
watchdog_list_t *c = w->callbacks;
|
|
Packit |
90a5c9 |
apr_status_t rv = APR_EOF;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (c) {
|
|
Packit |
90a5c9 |
if (c->data == data && c->callback_fn == callback) {
|
|
Packit |
90a5c9 |
/* We have existing callback.
|
|
Packit |
90a5c9 |
* Update the interval and reset status, so the
|
|
Packit |
90a5c9 |
* callback and continue execution if stopped earlier.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
c->interval = interval;
|
|
Packit |
90a5c9 |
c->step = 0;
|
|
Packit |
90a5c9 |
c->status = APR_SUCCESS;
|
|
Packit |
90a5c9 |
rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
c = c->next;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t ap_watchdog_register_callback(ap_watchdog_t *w,
|
|
Packit |
90a5c9 |
apr_interval_time_t interval,
|
|
Packit |
90a5c9 |
const void *data,
|
|
Packit |
90a5c9 |
ap_watchdog_callback_fn_t *callback)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
watchdog_list_t *c = w->callbacks;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
while (c) {
|
|
Packit |
90a5c9 |
if (c->data == data && c->callback_fn == callback) {
|
|
Packit |
90a5c9 |
/* We have already registered callback.
|
|
Packit |
90a5c9 |
* Do not allow callbacks that have the same
|
|
Packit |
90a5c9 |
* function and data pointers.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
return APR_EEXIST;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
c = c->next;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
c = apr_palloc(w->pool, sizeof(watchdog_list_t));
|
|
Packit |
90a5c9 |
c->data = data;
|
|
Packit |
90a5c9 |
c->callback_fn = callback;
|
|
Packit |
90a5c9 |
c->interval = interval;
|
|
Packit |
90a5c9 |
c->step = 0;
|
|
Packit |
90a5c9 |
c->status = APR_EINIT;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
c->wd = w;
|
|
Packit |
90a5c9 |
c->next = w->callbacks;
|
|
Packit |
90a5c9 |
w->callbacks = c;
|
|
Packit |
90a5c9 |
w->active++;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return APR_SUCCESS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/* Pre config hook. */
|
|
Packit |
90a5c9 |
/* Create default watchdogs for parent and child */
|
|
Packit |
90a5c9 |
/* Parent watchdog executes inside parent process so it doesn't need the */
|
|
Packit |
90a5c9 |
/* singleton mutex */
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
static int wd_pre_config_hook(apr_pool_t *pconf, apr_pool_t *plog,
|
|
Packit |
90a5c9 |
apr_pool_t *ptemp)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
ap_watchdog_t *w;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_mpm_query(AP_MPMQ_IS_FORKED, &mpm_is_forked);
|
|
Packit |
90a5c9 |
if ((rv = ap_watchdog_get_instance(&w,
|
|
Packit |
90a5c9 |
AP_WATCHDOG_SINGLETON, 0, 1, pconf)) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if ((rv = ap_watchdog_get_instance(&w,
|
|
Packit |
90a5c9 |
AP_WATCHDOG_DEFAULT, 0, 0, pconf)) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (mpm_is_forked == AP_MPMQ_NOT_SUPPORTED) {
|
|
Packit |
90a5c9 |
/* Create parent process watchdog for
|
|
Packit |
90a5c9 |
* non forked mpm's only.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if ((rv = ap_watchdog_get_instance(&w,
|
|
Packit |
90a5c9 |
AP_WATCHDOG_DEFAULT, 1, 0, pconf)) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((rv = ap_mutex_register(pconf, wd_proc_mutex_type, NULL,
|
|
Packit |
90a5c9 |
APR_LOCK_DEFAULT, 0)) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/* Post config hook. */
|
|
Packit |
90a5c9 |
/* Create watchdog thread in parent and initializes Watchdog module */
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
static int wd_post_config_hook(apr_pool_t *pconf, apr_pool_t *plog,
|
|
Packit |
90a5c9 |
apr_pool_t *ptemp, server_rec *s)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
const char *pk = "watchdog_init_module_tag";
|
|
Packit |
90a5c9 |
apr_pool_t *ppconf = pconf;
|
|
Packit |
90a5c9 |
const apr_array_header_t *wl;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
|
|
Packit |
90a5c9 |
/* First time config phase -- skip. */
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_pool_userdata_get((void *)&wd_server_conf, pk, ppconf);
|
|
Packit |
90a5c9 |
if (!wd_server_conf) {
|
|
Packit |
90a5c9 |
if (!(wd_server_conf = apr_pcalloc(ppconf, sizeof(wd_server_conf_t))))
|
|
Packit |
90a5c9 |
return APR_ENOMEM;
|
|
Packit |
90a5c9 |
apr_pool_create(&wd_server_conf->pool, ppconf);
|
|
Packit |
90a5c9 |
apr_pool_userdata_set(wd_server_conf, pk, apr_pool_cleanup_null, ppconf);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(010033)
|
|
Packit |
90a5c9 |
"Watchdog: Running with WatchdogInterval %"
|
|
Packit |
90a5c9 |
APR_TIME_T_FMT "ms", apr_time_as_msec(wd_interval));
|
|
Packit |
90a5c9 |
wd_server_conf->s = s;
|
|
Packit |
90a5c9 |
if ((wl = ap_list_provider_names(pconf, AP_WATCHDOG_PGROUP,
|
|
Packit |
90a5c9 |
AP_WATCHDOG_PVERSION))) {
|
|
Packit |
90a5c9 |
const ap_list_provider_names_t *wn;
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02974)
|
|
Packit |
90a5c9 |
"Watchdog: found parent providers.");
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
wn = (ap_list_provider_names_t *)wl->elts;
|
|
Packit |
90a5c9 |
for (i = 0; i < wl->nelts; i++) {
|
|
Packit |
90a5c9 |
ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP,
|
|
Packit |
90a5c9 |
wn[i].provider_name,
|
|
Packit |
90a5c9 |
AP_WATCHDOG_PVERSION);
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02975)
|
|
Packit |
90a5c9 |
"Watchdog: Looking for parent (%s).", wn[i].provider_name);
|
|
Packit |
90a5c9 |
if (w) {
|
|
Packit |
90a5c9 |
if (!w->active) {
|
|
Packit |
90a5c9 |
int status = ap_run_watchdog_need(s, w->name, 1,
|
|
Packit |
90a5c9 |
w->singleton);
|
|
Packit |
90a5c9 |
if (status == OK) {
|
|
Packit |
90a5c9 |
/* One of the modules returned OK to this watchog.
|
|
Packit |
90a5c9 |
* Mark it as active
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
w->active = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (w->active) {
|
|
Packit |
90a5c9 |
/* We have active watchdog.
|
|
Packit |
90a5c9 |
* Create the watchdog thread
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01571)
|
|
Packit |
90a5c9 |
"Watchdog: Failed to create parent worker thread.");
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02976)
|
|
Packit |
90a5c9 |
"Watchdog: Created parent worker thread (%s).", w->name);
|
|
Packit |
90a5c9 |
wd_server_conf->parent_workers++;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (wd_server_conf->parent_workers) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01572)
|
|
Packit |
90a5c9 |
"Spawned %d parent worker threads.",
|
|
Packit |
90a5c9 |
wd_server_conf->parent_workers);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if ((wl = ap_list_provider_names(pconf, AP_WATCHDOG_PGROUP,
|
|
Packit |
90a5c9 |
AP_WATCHDOG_CVERSION))) {
|
|
Packit |
90a5c9 |
const ap_list_provider_names_t *wn;
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02977)
|
|
Packit |
90a5c9 |
"Watchdog: found child providers.");
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
wn = (ap_list_provider_names_t *)wl->elts;
|
|
Packit |
90a5c9 |
for (i = 0; i < wl->nelts; i++) {
|
|
Packit |
90a5c9 |
ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP,
|
|
Packit |
90a5c9 |
wn[i].provider_name,
|
|
Packit |
90a5c9 |
AP_WATCHDOG_CVERSION);
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02978)
|
|
Packit |
90a5c9 |
"Watchdog: Looking for child (%s).", wn[i].provider_name);
|
|
Packit |
90a5c9 |
if (w) {
|
|
Packit |
90a5c9 |
if (!w->active) {
|
|
Packit |
90a5c9 |
int status = ap_run_watchdog_need(s, w->name, 0,
|
|
Packit |
90a5c9 |
w->singleton);
|
|
Packit |
90a5c9 |
if (status == OK) {
|
|
Packit |
90a5c9 |
/* One of the modules returned OK to this watchog.
|
|
Packit |
90a5c9 |
* Mark it as active
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
w->active = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (w->active) {
|
|
Packit |
90a5c9 |
/* We have some callbacks registered.
|
|
Packit |
90a5c9 |
* Create mutexes for singleton watchdogs
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if (w->singleton) {
|
|
Packit |
90a5c9 |
rv = ap_proc_mutex_create(&w->mutex, NULL, wd_proc_mutex_type,
|
|
Packit |
90a5c9 |
w->name, s,
|
|
Packit |
90a5c9 |
wd_server_conf->pool, 0);
|
|
Packit |
90a5c9 |
if (rv != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(10095)
|
|
Packit |
90a5c9 |
"Watchdog: Failed to create singleton mutex.");
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02979)
|
|
Packit |
90a5c9 |
"Watchdog: Created singleton mutex (%s).", w->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
wd_server_conf->child_workers++;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/* Child init hook. */
|
|
Packit |
90a5c9 |
/* Create watchdog threads and initializes Mutexes in child */
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
static void wd_child_init_hook(apr_pool_t *p, server_rec *s)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv = OK;
|
|
Packit |
90a5c9 |
const apr_array_header_t *wl;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!wd_server_conf->child_workers) {
|
|
Packit |
90a5c9 |
/* We don't have anything configured, bail out.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02980)
|
|
Packit |
90a5c9 |
"Watchdog: nothing configured?");
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if ((wl = ap_list_provider_names(p, AP_WATCHDOG_PGROUP,
|
|
Packit |
90a5c9 |
AP_WATCHDOG_CVERSION))) {
|
|
Packit |
90a5c9 |
const ap_list_provider_names_t *wn;
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
wn = (ap_list_provider_names_t *)wl->elts;
|
|
Packit |
90a5c9 |
for (i = 0; i < wl->nelts; i++) {
|
|
Packit |
90a5c9 |
ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP,
|
|
Packit |
90a5c9 |
wn[i].provider_name,
|
|
Packit |
90a5c9 |
AP_WATCHDOG_CVERSION);
|
|
Packit |
90a5c9 |
if (w && w->active) {
|
|
Packit |
90a5c9 |
/* We have some callbacks registered.
|
|
Packit |
90a5c9 |
* Kick of the watchdog
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) {
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01573)
|
|
Packit |
90a5c9 |
"Watchdog: Failed to create child worker thread.");
|
|
Packit |
90a5c9 |
/* No point to continue */
|
|
Packit |
90a5c9 |
return;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02981)
|
|
Packit |
90a5c9 |
"Watchdog: Created child worker thread (%s).", wn[i].provider_name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/* WatchdogInterval directive */
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
static const char *wd_cmd_watchdog_int(cmd_parms *cmd, void *dummy,
|
|
Packit |
90a5c9 |
const char *arg)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
const char *errs = ap_check_cmd_context(cmd, GLOBAL_ONLY);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (errs != NULL)
|
|
Packit |
90a5c9 |
return errs;
|
|
Packit |
90a5c9 |
rv = ap_timeout_parameter_parse(arg, &wd_interval, "s");
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (rv != APR_SUCCESS)
|
|
Packit |
90a5c9 |
return "Unparse-able WatchdogInterval setting";
|
|
Packit |
90a5c9 |
if (wd_interval < AP_WD_TM_SLICE) {
|
|
Packit |
90a5c9 |
return apr_psprintf(cmd->pool, "Invalid WatchdogInterval: minimal value %"
|
|
Packit |
90a5c9 |
APR_TIME_T_FMT "ms", apr_time_as_msec(AP_WD_TM_SLICE));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/* List of directives specific to our module. */
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
static const command_rec wd_directives[] =
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
AP_INIT_TAKE1(
|
|
Packit |
90a5c9 |
"WatchdogInterval", /* directive name */
|
|
Packit |
90a5c9 |
wd_cmd_watchdog_int, /* config action routine */
|
|
Packit |
90a5c9 |
NULL, /* argument to include in call */
|
|
Packit |
90a5c9 |
RSRC_CONF, /* where available */
|
|
Packit |
90a5c9 |
"Watchdog interval in seconds"
|
|
Packit |
90a5c9 |
),
|
|
Packit |
90a5c9 |
{NULL}
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/* Which functions are responsible for which hooks in the server. */
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
static void wd_register_hooks(apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Only the mpm_winnt has child init hook handler.
|
|
Packit |
90a5c9 |
* Make sure that we are called after the mpm child init handler
|
|
Packit |
90a5c9 |
* initializes.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
static const char *const after_mpm[] = { "mpm_winnt.c", NULL};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Pre config handling
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
ap_hook_pre_config(wd_pre_config_hook,
|
|
Packit |
90a5c9 |
NULL,
|
|
Packit |
90a5c9 |
NULL,
|
|
Packit |
90a5c9 |
APR_HOOK_FIRST);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Post config handling
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
ap_hook_post_config(wd_post_config_hook,
|
|
Packit |
90a5c9 |
NULL,
|
|
Packit |
90a5c9 |
NULL,
|
|
Packit |
90a5c9 |
APR_HOOK_LAST);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Child init hook
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
ap_hook_child_init(wd_child_init_hook,
|
|
Packit |
90a5c9 |
after_mpm,
|
|
Packit |
90a5c9 |
NULL,
|
|
Packit |
90a5c9 |
APR_HOOK_MIDDLE);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
APR_REGISTER_OPTIONAL_FN(ap_watchdog_get_instance);
|
|
Packit |
90a5c9 |
APR_REGISTER_OPTIONAL_FN(ap_watchdog_register_callback);
|
|
Packit |
90a5c9 |
APR_REGISTER_OPTIONAL_FN(ap_watchdog_set_callback_interval);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/* The list of callback routines and data structures that provide */
|
|
Packit |
90a5c9 |
/* the static hooks into our module from the other parts of the server. */
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
AP_DECLARE_MODULE(watchdog) = {
|
|
Packit |
90a5c9 |
STANDARD20_MODULE_STUFF,
|
|
Packit |
90a5c9 |
NULL, /* create per-directory config structure */
|
|
Packit |
90a5c9 |
NULL, /* merge per-directory config structures */
|
|
Packit |
90a5c9 |
NULL, /* create per-server config structure */
|
|
Packit |
90a5c9 |
NULL, /* merge per-server config structures */
|
|
Packit |
90a5c9 |
wd_directives, /* command apr_table_t */
|
|
Packit |
90a5c9 |
wd_register_hooks /* register hooks */
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/* The list of optional hooks that we provide */
|
|
Packit |
90a5c9 |
/* */
|
|
Packit |
90a5c9 |
/*--------------------------------------------------------------------------*/
|
|
Packit |
90a5c9 |
APR_HOOK_STRUCT(
|
|
Packit |
90a5c9 |
APR_HOOK_LINK(watchdog_need)
|
|
Packit |
90a5c9 |
APR_HOOK_LINK(watchdog_init)
|
|
Packit |
90a5c9 |
APR_HOOK_LINK(watchdog_exit)
|
|
Packit |
90a5c9 |
APR_HOOK_LINK(watchdog_step)
|
|
Packit |
90a5c9 |
)
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ap, AP_WD, int, watchdog_need,
|
|
Packit |
90a5c9 |
(server_rec *s, const char *name,
|
|
Packit |
90a5c9 |
int parent, int singleton),
|
|
Packit |
90a5c9 |
(s, name, parent, singleton),
|
|
Packit |
90a5c9 |
DECLINED)
|
|
Packit |
90a5c9 |
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap, AP_WD, int, watchdog_init,
|
|
Packit |
90a5c9 |
(server_rec *s, const char *name,
|
|
Packit |
90a5c9 |
apr_pool_t *pool),
|
|
Packit |
90a5c9 |
(s, name, pool),
|
|
Packit |
90a5c9 |
OK, DECLINED)
|
|
Packit |
90a5c9 |
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap, AP_WD, int, watchdog_exit,
|
|
Packit |
90a5c9 |
(server_rec *s, const char *name,
|
|
Packit |
90a5c9 |
apr_pool_t *pool),
|
|
Packit |
90a5c9 |
(s, name, pool),
|
|
Packit |
90a5c9 |
OK, DECLINED)
|
|
Packit |
90a5c9 |
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ap, AP_WD, int, watchdog_step,
|
|
Packit |
90a5c9 |
(server_rec *s, const char *name,
|
|
Packit |
90a5c9 |
apr_pool_t *pool),
|
|
Packit |
90a5c9 |
(s, name, pool),
|
|
Packit |
90a5c9 |
OK, DECLINED)
|