httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ruediger Pluem <rpl...@apache.org>
Subject Re: svn commit: r741947 - in /httpd/httpd/trunk/modules/mappers: config9.m4 mod_watchdog.c mod_watchdog.h
Date Sun, 08 Feb 2009 11:14:51 GMT


On 02/07/2009 08:51 PM, mturk@apache.org wrote:
> Author: mturk
> Date: Sat Feb  7 19:51:52 2009
> New Revision: 741947
> 
> URL: http://svn.apache.org/viewvc?rev=741947&view=rev
> Log:
> Add watchdog module
> 
> Added:
>     httpd/httpd/trunk/modules/mappers/mod_watchdog.c   (with props)
>     httpd/httpd/trunk/modules/mappers/mod_watchdog.h   (with props)
> Modified:
>     httpd/httpd/trunk/modules/mappers/config9.m4
> 

> Added: httpd/httpd/trunk/modules/mappers/mod_watchdog.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mappers/mod_watchdog.c?rev=741947&view=auto
> ==============================================================================

> +/*--------------------------------------------------------------------------*/
> +/*                                                                          */
> +/* Main watchdog worker thread.                                             */
> +/* For singleton workers child thread theat first obtains the process       */
> +/* mutex is running. Threads in other child's are locked on mutex.          */
> +/*                                                                          */
> +/*--------------------------------------------------------------------------*/
> +static void* 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;
> +
> +    w->pool = apr_thread_pool_get(thread);
> +    w->is_running = 1;
> +
> +    apr_thread_mutex_unlock(w->startup);
> +    if (w->mutex) {
> +        while (w->is_running) {
> +            rv = apr_proc_mutex_trylock(w->mutex);
> +            if (rv == APR_SUCCESS) {
> +                if (probed) {
> +                    /* Sleep after we were locked
> +                     * up to 1 second. Httpd can be
> +                     * in the middle of shutdown, and
> +                     * our child didn't yet received
> +                     * the shutdown signal.
> +                     */
> +                    probed = 10;
> +                    while (w->is_running && probed > 0) {
> +                        apr_sleep(AP_WD_TM_INTERVAL);
> +                        probed--;
> +                    }
> +                }
> +                locked = 1;
> +                break;
> +            }
> +            probed = 1;
> +            apr_sleep(AP_WD_TM_SLICE);
> +        }
> +    }
> +    if (w->is_running) {
> +        watchdog_list_t *wl = w->callbacks;
> +        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd_server_conf->s,
> +                     "%sWatchdog (%s) running (%d)",
> +                     w->singleton ? "Singleton" : "",
> +                     w->name, getpid());
> +        apr_time_clock_hires(w->pool);
> +        if (wl) {
> +            apr_pool_t *ctx = NULL;
> +            apr_pool_create(&ctx, w->pool);
> +            while (wl && w->is_running) {
> +                /* Execute watchdog callback */
> +                wl->status = (*wl->callback_fn)(AP_WATCHDOG_STATE_STARTING,
> +                                                (void *)wl->data, ctx);
> +                wl = wl->next;
> +            }
> +            apr_pool_destroy(ctx);
> +        }
> +        else {
> +            ap_run_watchdog_init(wd_server_conf->s, w->name, w->pool);
> +            inited = 1;
> +        }
> +    }
> +
> +    /* Main execution loop */
> +    while (w->is_running) {
> +        apr_pool_t *ctx = NULL;
> +        apr_time_t curr;
> +        watchdog_list_t *wl = w->callbacks;
> +
> +        apr_sleep(AP_WD_TM_SLICE);
> +        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) {
> +                    if (!ctx)

Is this check really needed? ctx should be always NULL here.

> +                        apr_pool_create(&ctx, w->pool);
> +                    wl->step = 0;
> +                    /* Execute watchdog callback */
> +                    wl->status = (*wl->callback_fn)(AP_WATCHDOG_STATE_RUNNING,
> +                                                    (void *)wl->data, ctx);
> +                }
> +            }
> +            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) {
> +                if (!ctx)
> +                    apr_pool_create(&ctx, w->pool);

Is this check really needed? ctx should be always NULL here.

> +                w->step = 0;
> +                /* Run watchdog step hook */
> +                ap_run_watchdog_step(wd_server_conf->s, w->name, ctx);
> +            }
> +        }
> +        if (ctx)
> +            apr_pool_destroy(ctx);
> +        if (!w->is_running) {
> +            break;
> +        }
> +    }
> +    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,
> +                     "%sWatchdog (%s) stopping (%d)",
> +                     w->singleton ? "Singleton" : "",
> +                     w->name, getpid());
> +
> +    if (locked)
> +        apr_proc_mutex_unlock(w->mutex);
> +    apr_thread_exit(w->thread, APR_SUCCESS);
> +
> +    return NULL;
> +}
> +
> +static apr_status_t wd_startup(ap_watchdog_t *w, apr_pool_t *p)
> +{
> +    apr_status_t rc;
> +
> +    /* Create thread startup mutex */
> +    rc = apr_thread_mutex_create(&w->startup, APR_THREAD_MUTEX_UNNESTED, p);
> +    if (rc != APR_SUCCESS)
> +        return rc;
> +
> +    if (w->singleton) {
> +        /* Initialize singleton mutex in child */
> +        rc = apr_proc_mutex_child_init(&w->mutex, w->mutex_path, p);
> +        if (rc != APR_SUCCESS)
> +            return rc;
> +    }
> +
> +    /* This mutex fixes problems with a fast start/fast end, where the pool
> +     * cleanup was being invoked before the thread completely spawned.
> +     */

Can you elaborate this a bit more (maybe with an example)?
I currently do not understand which problem is solved here.

> +    apr_thread_mutex_lock(w->startup);
> +
> +    /* Start the newly created watchdog */
> +    rc = apr_thread_create(&w->thread, NULL, wd_worker, w, p);
> +    if (rc) {
> +        apr_pool_cleanup_kill(p, w, wd_worker_cleanup);

I don't see that this cleanup gets registered anywhere.

> +    }
> +
> +    apr_thread_mutex_lock(w->startup);
> +    apr_thread_mutex_unlock(w->startup);
> +    apr_thread_mutex_destroy(w->startup);
> +
> +    return rc;
> +}
> +

Regards

RĂ¼diger

Mime
View raw message