Skip to content

Commit

Permalink
Fix allocation debugger to handle allocations in con/destructors
Browse files Browse the repository at this point in the history
conc021 is an example of a program that broke.
It doesn't handle them particularly well still, but it doesn't crash at
least.
  • Loading branch information
igfoo committed Dec 13, 2006
1 parent 6ffb1ce commit 4307b48
Showing 1 changed file with 64 additions and 29 deletions.
93 changes: 64 additions & 29 deletions rts/RtsUtils.c
Expand Up @@ -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

Expand Down

0 comments on commit 4307b48

Please sign in to comment.