diff options
author | Ian Lynagh <igloo@earth.li> | 2006-12-13 13:35:18 +0000 |
---|---|---|
committer | Ian Lynagh <igloo@earth.li> | 2006-12-13 13:35:18 +0000 |
commit | 4307b489da14ddd13c85fe837c5f27bf991c312e (patch) | |
tree | e9298ee73e8cd900c2e919569b872a75ebb39133 /rts/RtsUtils.c | |
parent | 6ffb1cec5bc6fcc834547fc456322d2eb2418ff6 (diff) | |
download | haskell-4307b489da14ddd13c85fe837c5f27bf991c312e.tar.gz |
Fix allocation debugger to handle allocations in con/destructors
conc021 is an example of a program that broke.
It doesn't handle them particularly well still, but it doesn't crash at
least.
Diffstat (limited to 'rts/RtsUtils.c')
-rw-r--r-- | rts/RtsUtils.c | 93 |
1 files changed, 64 insertions, 29 deletions
diff --git a/rts/RtsUtils.c b/rts/RtsUtils.c index 518d464040..a2a2919702 100644 --- a/rts/RtsUtils.c +++ b/rts/RtsUtils.c @@ -86,57 +86,92 @@ initAllocator(void) void shutdownAllocator(void) { + Allocated *prev, *a; + + if (allocs == NULL) { + barf("Allocator shutdown requested, but not initialised!"); + } + #ifdef THREADED_RTS closeMutex(&allocator_mutex); #endif + + prev = allocs; + while (1) { + a = prev->next; + free(prev); + if (a == NULL) return; + IF_DEBUG(sanity, + debugBelch("Warning: %p still allocated at shutdown\n", + a->addr);) + prev = a; + } } static void addAllocation(void *addr, size_t len) { Allocated *a; size_t alloc_size; - if (allocs == NULL) { - barf("addAllocation: allocator debugger not initialised"); + if (allocs != NULL) { + alloc_size = sizeof(Allocated); + if ((a = (Allocated *) malloc(alloc_size)) == NULL) { + /* don't fflush(stdout); WORKAROUND bug in Linux glibc */ + MallocFailHook((W_) alloc_size, + "creating info for debugging allocator"); + stg_exit(EXIT_INTERNAL_ERROR); + } + a->addr = addr; + a->len = len; + ACQUIRE_LOCK(&allocator_mutex); + a->next = allocs->next; + allocs->next = a; + RELEASE_LOCK(&allocator_mutex); } - alloc_size = sizeof(Allocated); - if ((a = (Allocated *) malloc(alloc_size)) == NULL) { - /* don't fflush(stdout); WORKAROUND bug in Linux glibc */ - MallocFailHook((W_) alloc_size, "creating info for debugging allocator"); - stg_exit(EXIT_INTERNAL_ERROR); + else { + /* This doesn't actually help as we haven't looked at the flags + * at the time that it matters (while running constructors) */ + IF_DEBUG(sanity, + debugBelch("Ignoring allocation %p %zd as allocs is NULL\n", + addr, len);) } - a->addr = addr; - a->len = len; - ACQUIRE_LOCK(&allocator_mutex); - a->next = allocs->next; - allocs->next = a; - RELEASE_LOCK(&allocator_mutex); } static void removeAllocation(void *addr) { Allocated *prev, *a; - if (allocs == NULL) { - barf("addAllocation: allocator debugger not initialised"); - } if (addr == NULL) { barf("Freeing NULL!"); } - ACQUIRE_LOCK(&allocator_mutex); - prev = allocs; - a = prev->next; - while (a != NULL) { - if (a->addr == addr) { - prev->next = a->next; - memset(addr, 0xaa, a->len); - free(a); - RELEASE_LOCK(&allocator_mutex); - return; + if (allocs != NULL) { + ACQUIRE_LOCK(&allocator_mutex); + prev = allocs; + a = prev->next; + while (a != NULL) { + if (a->addr == addr) { + prev->next = a->next; + memset(addr, 0xaa, a->len); + free(a); + RELEASE_LOCK(&allocator_mutex); + return; + } + prev = a; + a = a->next; } - prev = a; - a = a->next; + /* We would like to barf here, but we can't as conc021 + * allocates some stuff in a constructor which then gets freed + * during hs_exit */ + /* barf("Freeing non-allocated memory at %p", addr); */ + IF_DEBUG(sanity, + debugBelch("Warning: Freeing non-allocated memory at %p\n", + addr);) + RELEASE_LOCK(&allocator_mutex); + } + else { + IF_DEBUG(sanity, + debugBelch("Ignoring free of %p as allocs is NULL\n", + addr);) } - barf("Freeing non-allocated memory at %p", addr); } #endif |