diff options
Diffstat (limited to 'malloc/arena.c')
-rw-r--r-- | malloc/arena.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/malloc/arena.c b/malloc/arena.c index d85f3712f7..2466697d1a 100644 --- a/malloc/arena.c +++ b/malloc/arena.c @@ -99,7 +99,7 @@ int __malloc_initialized = -1; } while (0) #define arena_lock(ptr, size) do { \ - if (ptr) \ + if (ptr && !arena_is_corrupt (ptr)) \ (void) mutex_lock (&ptr->mutex); \ else \ ptr = arena_get2 (ptr, (size), NULL); \ @@ -686,7 +686,7 @@ heap_trim (heap_info *heap, size_t pad) if (!prev_inuse (p)) /* consolidate backward */ { p = prev_chunk (p); - unlink (p, bck, fwd); + unlink (ar_ptr, p, bck, fwd); } assert (((unsigned long) ((char *) p + new_size) & (pagesz - 1)) == 0); assert (((char *) p + new_size) == ((char *) heap + heap->size)); @@ -809,7 +809,7 @@ reused_arena (mstate avoid_arena) result = next_to_use; do { - if (!mutex_trylock (&result->mutex)) + if (!arena_is_corrupt (result) && !mutex_trylock (&result->mutex)) goto out; result = result->next; @@ -821,7 +821,21 @@ reused_arena (mstate avoid_arena) if (result == avoid_arena) result = result->next; - /* No arena available. Wait for the next in line. */ + /* Make sure that the arena we get is not corrupted. */ + mstate begin = result; + while (arena_is_corrupt (result) || result == avoid_arena) + { + result = result->next; + if (result == begin) + break; + } + + /* We could not find any arena that was either not corrupted or not the one + we wanted to avoid. */ + if (result == begin || result == avoid_arena) + return NULL; + + /* No arena available without contention. Wait for the next in line. */ LIBC_PROBE (memory_arena_reuse_wait, 3, &result->mutex, result, avoid_arena); (void) mutex_lock (&result->mutex); |