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;
}