On Wed, Sep 19, 2001 at 12:27:35PM -0700, Jon Travis wrote: > BZzzzt. The attached code registers a cleanup from within a cleanup, and > does so 'correctly'. See the program attached at the bottom, which behaves > incorrectly. It is simple code, but not knowing that a given > function registers a cleanup can cause major problems (leaking > file descriptors, etc. eventually). The file should contain 'Cleanup', > because the cleanup of the file should flush the buffer -- that > cleanup is never run, though. > > > when the cleanup is registered, it is gauranteed to be there when the > > cleanup > > is run. > > > > Anything else is completely broken. > > > #include "apr.h" > #include "apr_file_io.h" > > static apr_status_t my_cleanup(void *cbdata){ > apr_pool_t *p = cbdata; > apr_file_t *file; > > apr_file_open(&file, "/tmp/bonk", > APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED, > APR_OS_DEFAULT, p); > apr_file_printf(file, "Cleanup"); > return APR_SUCCESS; > } > > int main(int argc, char *argv[]){ > apr_pool_t *pool; > > apr_initialize(); > apr_pool_create(&pool, NULL); > apr_pool_cleanup_register(pool, pool, my_cleanup, NULL); > apr_pool_destroy(pool); > apr_terminate(); > return 0; > }
Does this fix it for you? All testmem tests passed for me and your code above properly flushes "Cleanup" to the file. (Someone needs to check my work on run_child_cleanups() and make sure that the popping is necessary. It looked to be in the same situation.) -aaron Index: memory/unix/apr_pools.c =================================================================== RCS file: /home/cvspublic/apr/memory/unix/apr_pools.c,v retrieving revision 1.111 diff -u -r1.111 apr_pools.c --- memory/unix/apr_pools.c 2001/09/17 20:12:23 1.111 +++ memory/unix/apr_pools.c 2001/09/20 18:06:46 @@ -564,7 +564,8 @@ struct process_chain; struct cleanup; -static void run_cleanups(struct cleanup *c); +static struct cleanup *pop_cleanup(apr_pool_t *p); +static void run_cleanups(apr_pool_t *p); static void free_proc_chain(struct process_chain *p); static apr_pool_t *permanent_pool; @@ -764,26 +765,35 @@ return (*cleanup) (data); } -static void run_cleanups(struct cleanup *c) +static struct cleanup *pop_cleanup(apr_pool_t *p) { - while (c) { - (*c->plain_cleanup) ((void *)c->data); - c = c->next; + struct cleanup *c; + if ((c = p->cleanups)) { + p->cleanups = c->next; + c->next = NULL; } + return c; } -static void run_child_cleanups(struct cleanup *c) +static void run_cleanups(apr_pool_t *p) { - while (c) { + struct cleanup *c; + while ((c = pop_cleanup(p))) { + (*c->plain_cleanup) ((void *)c->data); + } +} + +static void run_child_cleanups(apr_pool_t *p) +{ + struct cleanup *c; + while ((c = pop_cleanup(p))) { (*c->child_cleanup) ((void *)c->data); - c = c->next; } } static void cleanup_pool_for_exec(apr_pool_t *p) { - run_child_cleanups(p->cleanups); - p->cleanups = NULL; + run_child_cleanups(p); for (p = p->sub_pools; p; p = p->sub_next) { cleanup_pool_for_exec(p); @@ -863,8 +873,7 @@ } /* run cleanups and free any subprocesses. */ - run_cleanups(a->cleanups); - a->cleanups = NULL; + run_cleanups(a); free_proc_chain(a->subprocesses); a->subprocesses = NULL;