httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Glenn <gs-apache-...@gluelogic.com>
Subject Re: ap_process_config_tree called twice -- causes command_rec entries to be called twice -- httpd-2.0.47
Date Mon, 13 Oct 2003 04:41:02 GMT
On Sun, Oct 12, 2003 at 10:46:44PM +0200, Erik Abele wrote:
> Yes, this is the intended behaviour, there's even a comment at 
> main.c:564
> 
>     /* Note that we preflight the config file once
>      * before reading it _again_ in the main loop.
>      * This allows things, log files configuration
>      * for example, to settle down.
>      */
> 
> So, post_config hooks are always called twice.  You can see
> a working example in modules/mappers/mod_rewrite.c or in
> modules/generators/mod_cgid.c: there you'll find a flag
> called "first_time" in the post_config/cgid_init handler
> which takes care of the number of passes.

This response is slightly OT from the original question, but here's
what I have used in modules I've written.  Would there be any interest
in making these macros available to all modules?

Cheers,
Glenn


/* Apache runs init routines twice.  Set token to ensure things run only once.
 * (modified from Apache2 modules/generators/mod_cgid.c)
 * (The pool must have the same lifetime as the server (i.e. s->process->pool)
 *  so that when server is restarted, the userdata set below will be cleaned up
 *  and the module will be reinitialized properly.  A file-scoped global flag
 *  is not suitable for this purpose, unless it acts as a toggle and makes the
 *  assumption that init routines are always run twice, and exactly twice,
 *  (which is currently true AFAIK).
 *  The method below is safer.)
 */
#define RUN_INIT_ONCE(pool, tag)                                        \
    do {                                                                \
        void *userdata_data;                                            \
        apr_pool_userdata_get(&userdata_data, tag "_init_once", (pool));\
        if (userdata_data != NULL) {                                    \
            return OK;                                                  \
        }                                                               \
        apr_pool_userdata_set((const void *)1, tag "_init_once",        \
                              apr_pool_cleanup_null, (pool));           \
    } while (0)


static int
example_init(apr_pool_t *p, apr_pool_t *l, apr_pool_t *t, server_rec *s)
{
    /* ... code that can or should be run twice ... */

    /* Check that code in the rest of this routine has not already been run. */
    RUN_INIT_ONCE(s->process->pool, "mod_example"); /*(use unique module tag)*/

    /* ... code that must only be run the _first_ time init is called ... */

    return OK;
}


/* Or the inversion of the the macro behavior above */
#define RETURN_IF_PREFLIGHT(pool, tag)                                  \
    do {                                                                \
        void *userdata_data;                                            \
        apr_pool_userdata_get(&userdata_data, tag "_preflight", (pool));\
        if (userdata_data == NULL) {                                    \
            apr_pool_userdata_set((const void *)1, tag "_preflight",    \
                                  apr_pool_cleanup_null, (pool));       \
            return OK;                                                  \
        }                                                               \
    } while (0)


static int
example_init(apr_pool_t *p, apr_pool_t *l, apr_pool_t *t, server_rec *s)
{
    /* ... code that can or should be run twice ... */

    /* Do not run code in rest of this routine if preflight read of config */
    RETURN_IF_PREFLIGHT(s->process->pool, "mod_example");/*(unique module tag)*/

    /* ... code that must only be run the _second_ time init is called ... */

    return OK;
}

Mime
View raw message