Alexis Marrero wrote: > Jim, > > This are my results for the memory leak search in apache.table(). > > The table object creates a memory pool by using apr_pool_create_ex() and > destroys the pool using apr_pool_destroy(). I added a line in > MpTable_New() before "return (PyObject*)t" to destroy the pool and ran > 1M iterations and I notice that there was no memory leak. Therefore the > apache functions seems to be working fine.
Actually I don't think apr_pool_destroy() in table_dealloc is actually destroying the pool. I've been poking around in the code and there is something odd going on here. I tried registering a cleanup in MpTable_New() using: apr_pool_cleanup_register(t->pool, "pool cleanup called", cleanup_test, apr_pool_cleaunp_null); The cleanup_test callback just logs the "pool cleanup called" message to a file. apr_pool_destroy() is getting called in table_dealloc, but cleanup_test never gets called which indicates that the pool is *not* being destroyed, and hence our memory leak. I tried your trick of immediately calling apr_pool_destroy in MpTable_New(), and cleanup_test does get called there. So, the big question is... why is the pool not being destroyed? Can anyone offer some insight here? The attached diff is for trunk if anyone wants to play around with it. Jim
Index: tableobject.c =================================================================== --- tableobject.c (revision 431994) +++ tableobject.c (working copy) @@ -59,6 +59,19 @@ return (PyObject *)result; } + + +apr_status_t cleanup_test(void *msg) +{ + FILE *f; + f = fopen("/tmp/debug_table.log", "a+"); + fprintf(f, "%s\n", (char *)msg); + fclose(f); + + return 0; +} + + /** ** MpTable_New ** @@ -78,6 +91,8 @@ tableobject *t; apr_pool_t *p; + cleanup_test("MpTable_New() called"); + /* XXX need second arg abort function to report mem error */ apr_pool_create_ex(&p, NULL, NULL, NULL); @@ -86,7 +101,12 @@ /* remember the pointer to our own pool */ t->pool = p; + apr_pool_cleanup_register(p, " pool cleanup called", cleanup_test, apr_pool_cleanup_null); + /* Uncomment this to test that cleanup_test is getting called correctly. + apr_pool_destroy(t->pool); + */ + return (PyObject *)t; } @@ -99,10 +119,13 @@ static void table_dealloc(register tableobject *self) { + cleanup_test("table_dealloc:"); if (MpTable_Check(self)) { - if (self->pool) + if (self->pool) { + cleanup_test(" preparing to destroy the pool"); apr_pool_destroy(self->pool); + } PyObject_Del(self); } else