/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
/* Do nothing if the thread wasn't started. */ if (apr_atomic_read32(&w->thread_started) != 1) return APR_SUCCESS;
if (w->is_running) {
watchdog_list_t *wl = w->callbacks; while (wl) { if (wl->status == APR_SUCCESS) { /* Execute watchdog callback with STOPPING state */
(*wl->callback_fn)(AP_WATCHDOG_STATE_STOPPING,
(void *)wl->data, w->pool);
wl->status = APR_EOF;
}
wl = wl->next;
}
}
w->is_running = 0;
apr_thread_join(&rv, w->thread); return rv;
}
/*--------------------------------------------------------------------------*/ /* */ /* Main watchdog worker thread. */ /* For singleton workers child thread that first obtains the process */ /* mutex is running. Threads in other child's are locked on mutex. */ /* */ /*--------------------------------------------------------------------------*/ staticvoid* APR_THREAD_FUNC wd_worker(apr_thread_t *thread, void *data)
{
ap_watchdog_t *w = (ap_watchdog_t *)data;
apr_status_t rv; int locked = 0; int probed = 0; int inited = 0; int mpmq_s = 0;
apr_pool_t *temp_pool = NULL;
/* Main execution loop */ while (w->is_running) {
apr_time_t curr;
watchdog_list_t *wl = w->callbacks;
apr_sleep(AP_WD_TM_SLICE); if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
w->is_running = 0;
} if (mpmq_s == AP_MPMQ_STOPPING) {
w->is_running = 0;
} if (!w->is_running) { break;
}
curr = apr_time_now() - AP_WD_TM_SLICE; while (wl && w->is_running) { if (wl->status == APR_SUCCESS) {
wl->step += (apr_time_now() - curr); if (wl->step >= wl->interval) {
wl->step = 0; /* Execute watchdog callback */
wl->status = (*wl->callback_fn)(AP_WATCHDOG_STATE_RUNNING,
(void *)wl->data, temp_pool); if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpmq_s) != APR_SUCCESS) {
w->is_running = 0;
} if (mpmq_s == AP_MPMQ_STOPPING) {
w->is_running = 0;
}
}
}
wl = wl->next;
} if (w->is_running && w->callbacks == NULL) { /* This is hook mode watchdog * running on WatchogInterval
*/
w->step += (apr_time_now() - curr); if (w->step >= wd_interval) {
w->step = 0; /* Run watchdog step hook */
ap_run_watchdog_step(wd_server_conf->s, w->name, temp_pool);
}
}
apr_pool_clear(temp_pool);
}
apr_pool_destroy(temp_pool);
if (inited) { /* Run the watchdog exit hooks. * If this was singleton watchdog the init hook * might never been called, so skip the exit hook * in that case as well.
*/
ap_run_watchdog_exit(wd_server_conf->s, w->name, w->pool);
} else {
watchdog_list_t *wl = w->callbacks; while (wl) { if (wl->status == APR_SUCCESS) { /* Execute watchdog callback with STOPPING state */
(*wl->callback_fn)(AP_WATCHDOG_STATE_STOPPING,
(void *)wl->data, w->pool);
}
wl = wl->next;
}
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd_server_conf->s,
APLOGNO(02973) "%sWatchdog (%s) stopping",
w->singleton ? "Singleton " : "", w->name);
if (locked)
apr_proc_mutex_unlock(w->mutex);
apr_thread_exit(w->thread, APR_SUCCESS);
while (c) { if (c->data == data && c->callback_fn == callback) { /* We have existing callback. * Update the interval and reset status, so the * callback and continue execution if stopped earlier.
*/
c->interval = interval;
c->step = 0;
c->status = APR_SUCCESS;
rv = APR_SUCCESS; break;
}
c = c->next;
} return rv;
}
while (c) { if (c->data == data && c->callback_fn == callback) { /* We have already registered callback. * Do not allow callbacks that have the same * function and data pointers.
*/ return APR_EEXIST;
}
c = c->next;
}
c = apr_palloc(w->pool, sizeof(watchdog_list_t));
c->data = data;
c->callback_fn = callback;
c->interval = interval;
c->step = 0;
c->status = APR_EINIT;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02974) "Watchdog: found parent providers.");
wn = (ap_list_provider_names_t *)wl->elts; for (i = 0; i < wl->nelts; i++) {
ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP,
wn[i].provider_name,
AP_WATCHDOG_PVERSION);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02975) "Watchdog: Looking for parent (%s).", wn[i].provider_name); if (w) { if (!w->active) { int status = ap_run_watchdog_need(s, w->name, 1,
w->singleton); if (status == OK) { /* One of the modules returned OK to this watchdog. * Mark it as active
*/
w->active = 1;
}
} if (w->active) { /* We have active watchdog. * Create the watchdog thread
*/ if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01571) "Watchdog: Failed to create parent worker thread."); return rv;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02976) "Watchdog: Created parent worker thread (%s).", w->name);
wd_server_conf->parent_workers++;
}
}
}
} if (wd_server_conf->parent_workers) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01572) "Spawned %d parent worker threads.",
wd_server_conf->parent_workers);
} if ((wl = ap_list_provider_names(pconf, AP_WATCHDOG_PGROUP,
AP_WATCHDOG_CVERSION))) { const ap_list_provider_names_t *wn; int i;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02977) "Watchdog: found child providers.");
wn = (ap_list_provider_names_t *)wl->elts; for (i = 0; i < wl->nelts; i++) {
ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP,
wn[i].provider_name,
AP_WATCHDOG_CVERSION);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02978) "Watchdog: Looking for child (%s).", wn[i].provider_name); if (w) { if (!w->active) { int status = ap_run_watchdog_need(s, w->name, 0,
w->singleton); if (status == OK) { /* One of the modules returned OK to this watchdog. * Mark it as active
*/
w->active = 1;
}
} if (w->active) { /* We have some callbacks registered. * Create mutexes for singleton watchdogs
*/ if (w->singleton) {
rv = ap_proc_mutex_create(&w->mutex, NULL, wd_proc_mutex_type,
w->name, s,
wd_server_conf->pool, 0); if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(10095) "Watchdog: Failed to create singleton mutex."); return rv;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02979) "Watchdog: Created singleton mutex (%s).", w->name);
}
wd_server_conf->child_workers++;
}
}
}
} return OK;
}
if (rv != APR_SUCCESS) return"Unparse-able WatchdogInterval setting"; if (wd_interval < AP_WD_TM_SLICE) { return apr_psprintf(cmd->pool, "Invalid WatchdogInterval: minimal value %"
APR_TIME_T_FMT "ms", apr_time_as_msec(AP_WD_TM_SLICE));
}
return NULL;
}
/*--------------------------------------------------------------------------*/ /* */ /* List of directives specific to our module. */ /* */ /*--------------------------------------------------------------------------*/ staticconst command_rec wd_directives[] =
{
AP_INIT_TAKE1( "WatchdogInterval", /* directive name */
wd_cmd_watchdog_int, /* config action routine */
NULL, /* argument to include in call */
RSRC_CONF, /* where available */ "Watchdog interval in seconds"
),
{NULL}
};
/*--------------------------------------------------------------------------*/ /* */ /* Which functions are responsible for which hooks in the server. */ /* */ /*--------------------------------------------------------------------------*/ staticvoid wd_register_hooks(apr_pool_t *p)
{
/* Only the mpm_winnt has child init hook handler. * Make sure that we are called after the mpm child init handler * initializes.
*/ staticconstchar *const after_mpm[] = { "mpm_winnt.c", NULL};
/* Pre config handling
*/
ap_hook_pre_config(wd_pre_config_hook,
NULL,
NULL,
APR_HOOK_FIRST);
/* Post config handling
*/
ap_hook_post_config(wd_post_config_hook,
NULL,
NULL,
APR_HOOK_LAST);
/*--------------------------------------------------------------------------*/ /* */ /* The list of callback routines and data structures that provide */ /* the static hooks into our module from the other parts of the server. */ /* */ /*--------------------------------------------------------------------------*/
AP_DECLARE_MODULE(watchdog) = {
STANDARD20_MODULE_STUFF,
NULL, /* create per-directory config structure */
NULL, /* merge per-directory config structures */
NULL, /* create per-server config structure */
NULL, /* merge per-server config structures */
wd_directives, /* command apr_table_t */
wd_register_hooks /* register hooks */
};
/*--------------------------------------------------------------------------*/ /* */ /* The list of optional hooks that we provide */ /* */ /*--------------------------------------------------------------------------*/
APR_HOOK_STRUCT(
APR_HOOK_LINK(watchdog_need)
APR_HOOK_LINK(watchdog_init)
APR_HOOK_LINK(watchdog_exit)
APR_HOOK_LINK(watchdog_step)
)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.