Skip to content
Snippets Groups Projects
Commit 09dd8310 authored by Martin Stjernholm's avatar Martin Stjernholm
Browse files

Improved dmalloc mode by not freeing meta-blocks that contains unfreed

blocks. That way we can avoid fatals or segfaults before the leak
detection completes. Also improved some rtldebug checks.

Rev: src/block_alloc.h:1.79
parent 19f2dc0e
No related branches found
No related tags found
No related merge requests found
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
|| This file is part of Pike. For copyright information see COPYRIGHT. || This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information. || for more information.
|| $Id: block_alloc.h,v 1.78 2006/01/24 07:32:22 mast Exp $ || $Id: block_alloc.h,v 1.79 2006/01/24 12:00:49 mast Exp $
*/ */
#undef PRE_INIT_BLOCK #undef PRE_INIT_BLOCK
...@@ -110,6 +110,7 @@ static struct PIKE_CONCAT(DATA,_context) *PIKE_CONCAT(DATA,_ctxs)=0; \ ...@@ -110,6 +110,7 @@ static struct PIKE_CONCAT(DATA,_context) *PIKE_CONCAT(DATA,_ctxs)=0; \
static struct PIKE_CONCAT(DATA,_block) *PIKE_CONCAT(DATA,_blocks)=0; \ static struct PIKE_CONCAT(DATA,_block) *PIKE_CONCAT(DATA,_blocks)=0; \
\ \
/* Points to the last meta-block in the DATA,_block list that isn't full. */ \ /* Points to the last meta-block in the DATA,_block list that isn't full. */ \
/* -1 when the block alloc isn't initialized. */ \
static struct PIKE_CONCAT(DATA,_block) *PIKE_CONCAT(DATA,_free_blocks)= \ static struct PIKE_CONCAT(DATA,_block) *PIKE_CONCAT(DATA,_free_blocks)= \
(void*)-1; \ (void*)-1; \
\ \
...@@ -214,36 +215,49 @@ struct DATA *PIKE_CONCAT(alloc_,DATA)(void) \ ...@@ -214,36 +215,49 @@ struct DATA *PIKE_CONCAT(alloc_,DATA)(void) \
}) \ }) \
\ \
DO_IF_DMALLOC( \ DO_IF_DMALLOC( \
static void PIKE_CONCAT(check_free_,DATA)(struct DATA *d) \ static void PIKE_CONCAT3(dmalloc_,DATA,_not_freed) (struct DATA *d, \
const char *msg) \
{ \ { \
struct PIKE_CONCAT(DATA,_block) *tmp; \ /* Separate function to allow gdb breakpoints. */ \
struct PIKE_CONCAT(DATA,_context) *ctx = PIKE_CONCAT(DATA,_ctxs); \ fprintf (stderr, "struct " TOSTR(DATA) \
for(tmp=PIKE_CONCAT(DATA,_blocks);tmp;tmp=tmp->next) \ " at %p is still in use %s\n", d, msg); \
} \
\
static void PIKE_CONCAT(dmalloc_late_free_,DATA) (struct DATA *d) \
{ \ { \
if( (char *)d < (char *)tmp) continue; \ /* Separate function to allow gdb breakpoints. */ \
if( (char *)d >= (char *)(tmp->x+(BSIZE))) continue; \ fprintf (stderr, "struct " TOSTR(DATA) " at %p freed now (too late)\n", d); \
if ((char *) d - (char *) tmp->x != \ dmalloc_mark_as_free (d, 1); \
(d - tmp->x) * (ptrdiff_t) sizeof (struct DATA)) break; \ dmalloc_unregister (d, 1); \
return; \ PIKE_MEM_NA (*d); \
} \ } \
while (ctx) { \ \
for(tmp=ctx->blocks; tmp; tmp=tmp->next) \ static void PIKE_CONCAT3(dmalloc_free_,DATA,_block) ( \
struct PIKE_CONCAT(DATA,_block) *blk, const char *msg) \
{ \ { \
if( (char *)d < (char *)tmp) continue; \ int dont_free = 0; \
if( (char *)d >= (char *)(tmp->x+(BSIZE))) continue; \ size_t i; \
if ((char *) d - (char *) tmp->x != \ for (i = 0; i < (BSIZE); i++) { \
(d - tmp->x) * (ptrdiff_t) sizeof (struct DATA)) break; \ if (dmalloc_check_allocated (blk->x + i, 1)) { \
return; \ PIKE_CONCAT3(dmalloc_,DATA,_not_freed) (blk->x + i, msg); \
dont_free = 1; \
DMALLOC_DESCRIBE_BLOCK ((blk->x + i)); \
debug_malloc_dump_references (blk->x + i, 0, 2, 0); \
} \ } \
ctx = ctx->next; \ else \
dmalloc_unregister(blk->x + i, 1); \
} \ } \
Pike_fatal("really_free_%s called on non-block_alloc region (%p).\n", \ if (dont_free) { \
#DATA, d); \ /* If a block still is in use we conciously leak this */ \
/* meta-block to allow access to it later. That way we can */ \
/* avoid fatals before the leak report. */ \
dmalloc_accept_leak (blk); \
} \
else { \
/* Mark meta-block as available, since libc will mess with it. */ \
PIKE_MEM_RW (blk->x); \
free ((char *) blk); \
} \ } \
\
static void PIKE_CONCAT (dmalloc_describe_, DATA) (struct DATA *d) \
{ \
DMALLOC_DESCRIBE_BLOCK (d); \
} \ } \
) \ ) \
\ \
...@@ -257,17 +271,20 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \ ...@@ -257,17 +271,20 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \
\ \
DO_IF_DMALLOC({ \ DO_IF_DMALLOC({ \
struct DATA *d2; \ struct DATA *d2; \
PIKE_CONCAT(check_free_,DATA)(d); \
dmalloc_mark_as_free(d, 1); \
blk = PIKE_CONCAT(DATA,_free_blocks); \ blk = PIKE_CONCAT(DATA,_free_blocks); \
if(blk == NULL || (char *)d < (char *)blk || \ if(blk == NULL || (char *)d < (char *)blk || \
(char *)d >= (char *)(blk->x+(BSIZE))) { \ (char *)d >= (char *)(blk->x+(BSIZE))) { \
blk = PIKE_CONCAT(DATA,_blocks); \ blk = PIKE_CONCAT(DATA,_blocks); \
while((char *)d < (char *)blk || \ while (blk && ((char *)d < (char *)blk || \
(char *)d >= (char *)(blk->x+(BSIZE))) \ (char *)d >= (char *)(blk->x+(BSIZE)))) \
blk = blk->next; \ blk = blk->next; \
} \ } \
if (blk) { \
if (!dmalloc_check_allocated (d, 0)) \
Pike_fatal ("really_free_" TOSTR(DATA) " called with " \
"unknown pointer %p (probably already freed)\n", d); \
blk->used--; \ blk->used--; \
dmalloc_mark_as_free(d, 1); \
PIKE_MEM_NA(*d); \ PIKE_MEM_NA(*d); \
d2 = PIKE_CONCAT(DATA,s_to_free)[PIKE_CONCAT(DATA,s_to_free_ptr)]; \ d2 = PIKE_CONCAT(DATA,s_to_free)[PIKE_CONCAT(DATA,s_to_free_ptr)]; \
PIKE_CONCAT(DATA,s_to_free)[PIKE_CONCAT(DATA,s_to_free_ptr)] = d; \ PIKE_CONCAT(DATA,s_to_free)[PIKE_CONCAT(DATA,s_to_free_ptr)] = d; \
...@@ -278,16 +295,29 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \ ...@@ -278,16 +295,29 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \
PIKE_MEM_WO(*d); \ PIKE_MEM_WO(*d); \
else \ else \
return; \ return; \
} \
else if (dmalloc_check_allocated (d, 0)) { \
PIKE_CONCAT(dmalloc_late_free_,DATA) (d); \
return; \
} \
}); \ }); \
\ \
blk = PIKE_CONCAT(DATA,_free_blocks); \ blk = PIKE_CONCAT(DATA,_free_blocks); \
if(blk == NULL || (char *)d < (char *)blk || \ if(blk == NULL || (char *)d < (char *)blk || \
(char *)d >= (char *)(blk->x+(BSIZE))) { \ (char *)d >= (char *)(blk->x+(BSIZE))) { \
blk = PIKE_CONCAT(DATA,_blocks); \ blk = PIKE_CONCAT(DATA,_blocks); \
DO_IF_DEBUG ( \
if (!blk) Pike_fatal ("really_free_" TOSTR(DATA) \
" got invalid pointer %p\n", d) \
); \
if((char *)d < (char *)blk || \ if((char *)d < (char *)blk || \
(char *)d >= (char *)(blk->x+(BSIZE))) { \ (char *)d >= (char *)(blk->x+(BSIZE))) { \
do { \ do { \
blk = blk->next; \ blk = blk->next; \
DO_IF_DEBUG ( \
if (!blk) Pike_fatal ("really_free_" TOSTR(DATA) \
" got invalid pointer %p\n", d) \
); \
} while((char *)d < (char *)blk || \ } while((char *)d < (char *)blk || \
(char *)d >= (char *)(blk->x+(BSIZE))); \ (char *)d >= (char *)(blk->x+(BSIZE))); \
if(blk == PIKE_CONCAT(DATA,_free_blocks)) \ if(blk == PIKE_CONCAT(DATA,_free_blocks)) \
...@@ -304,6 +334,13 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \ ...@@ -304,6 +334,13 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \
PIKE_CONCAT(DATA,_free_blocks) = blk; \ PIKE_CONCAT(DATA,_free_blocks) = blk; \
} \ } \
\ \
DO_IF_DEBUG ( \
if ((char *) d < (char *) &blk->x || \
((char *) d - (char *) &blk->x) % sizeof (struct DATA)) \
Pike_fatal ("really_free_" TOSTR(DATA) \
" got misaligned pointer %p\n", d); \
); \
\
DO_PRE_INIT_BLOCK(d); \ DO_PRE_INIT_BLOCK(d); \
d->BLOCK_ALLOC_NEXT = (void *)blk->PIKE_CONCAT3(free_,DATA,s); \ d->BLOCK_ALLOC_NEXT = (void *)blk->PIKE_CONCAT3(free_,DATA,s); \
blk->PIKE_CONCAT3(free_,DATA,s)=d; \ blk->PIKE_CONCAT3(free_,DATA,s)=d; \
...@@ -323,19 +360,16 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \ ...@@ -323,19 +360,16 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \
blk->next->prev = NULL; \ blk->next->prev = NULL; \
} \ } \
\ \
DO_IF_DMALLOC({ \ DO_IF_DMALLOC ( \
size_t i; \ PIKE_CONCAT3(dmalloc_free_,DATA,_block) ( \
for (i = 0; i < (BSIZE); i++) { \ blk, "in block expected to be empty") \
dmalloc_check_block_free( \ ); \
blk->x + i, DMALLOC_LOCATION(), #DATA, \ DO_IF_NOT_DMALLOC( \
(describe_block_fn *) PIKE_CONCAT (dmalloc_describe_, DATA)); \
dmalloc_unregister(blk->x + i, 1); \
} \
}); \
\
/* Mark meta-block as available, since libc will mess with it. */ \ /* Mark meta-block as available, since libc will mess with it. */ \
PIKE_MEM_RW(*blk); \ PIKE_MEM_RW(*blk); \
free(blk); \ free(blk); \
); \
\
--PIKE_CONCAT3(num_empty_,DATA,_blocks); \ --PIKE_CONCAT3(num_empty_,DATA,_blocks); \
} \ } \
\ \
...@@ -345,20 +379,17 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \ ...@@ -345,20 +379,17 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \
static void PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(void) \ static void PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(void) \
{ \ { \
struct PIKE_CONCAT(DATA,_block) *tmp; \ struct PIKE_CONCAT(DATA,_block) *tmp; \
\
DO_IF_DMALLOC( \ DO_IF_DMALLOC( \
MEMSET(PIKE_CONCAT(DATA,s_to_free), 0, sizeof(PIKE_CONCAT(DATA,s_to_free))); \ MEMSET(PIKE_CONCAT(DATA,s_to_free), 0, sizeof(PIKE_CONCAT(DATA,s_to_free))); \
for(tmp=PIKE_CONCAT(DATA,_blocks);tmp;tmp=tmp->next) \ while ((tmp = PIKE_CONCAT(DATA,_blocks))) { \
{ \ PIKE_CONCAT(DATA,_blocks) = tmp->next; \
size_t tmp2; \ PIKE_CONCAT3(dmalloc_free_,DATA,_block) ( \
for(tmp2=0;tmp2<(BSIZE);tmp2++) \ tmp, "in free_all_" TOSTR(DATA) "_blocks"); \
{ \
dmalloc_check_block_free( \
tmp->x+tmp2, DMALLOC_LOCATION(), #DATA, \
(describe_block_fn *) PIKE_CONCAT (dmalloc_describe_, DATA)); \
dmalloc_unregister(tmp->x+tmp2, 1); \
} \
} \ } \
) \ ); \
\
DO_IF_NOT_DMALLOC( \
while((tmp=PIKE_CONCAT(DATA,_blocks))) \ while((tmp=PIKE_CONCAT(DATA,_blocks))) \
{ \ { \
PIKE_CONCAT(DATA,_blocks)=tmp->next; \ PIKE_CONCAT(DATA,_blocks)=tmp->next; \
...@@ -366,6 +397,8 @@ static void PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(void) \ ...@@ -366,6 +397,8 @@ static void PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(void) \
PIKE_MEM_RW(tmp->x); \ PIKE_MEM_RW(tmp->x); \
free((char *)tmp); \ free((char *)tmp); \
} \ } \
); \
\
if (PIKE_CONCAT(DATA,_ctxs)) { \ if (PIKE_CONCAT(DATA,_ctxs)) { \
struct PIKE_CONCAT(DATA, _context) *ctx = PIKE_CONCAT(DATA,_ctxs); \ struct PIKE_CONCAT(DATA, _context) *ctx = PIKE_CONCAT(DATA,_ctxs); \
PIKE_CONCAT(DATA,_blocks)=ctx->blocks; \ PIKE_CONCAT(DATA,_blocks)=ctx->blocks; \
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment