From 508f51f5f41e1e7af50f5f215688ad77daec0f1a Mon Sep 17 00:00:00 2001 From: Eli Zaretskii <eliz@gnu.org> Date: Mon, 5 Nov 2012 19:23:25 +0200 Subject: [PATCH] Fix bug #12774 with crashes in ralloc.c. src/ralloc.c (relinquish): If real_morecore fails to return memory to the system, don't crash; instead, leave the last heap unchanged and return. --- src/ChangeLog | 6 ++++++ src/ralloc.c | 34 +++++++++++++++++----------------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 3ae755f3d20..c49039a3cf9 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2012-11-05 Eli Zaretskii <eliz@gnu.org> + + * ralloc.c (relinquish): If real_morecore fails to return memory + to the system, don't crash; instead, leave the last heap + unchanged and return. (Bug#12774) + 2012-11-03 Eli Zaretskii <eliz@gnu.org> * lisp.mk: Adjust comments to the fact that term/internal is now diff --git a/src/ralloc.c b/src/ralloc.c index 11897411930..e5bf76b0e6d 100644 --- a/src/ralloc.c +++ b/src/ralloc.c @@ -327,6 +327,8 @@ relinquish (void) if ((char *)last_heap->end - (char *)last_heap->bloc_start <= excess) { + heap_ptr lh_prev; + /* This heap should have no blocs in it. If it does, we cannot return it to the system. */ if (last_heap->first_bloc != NIL_BLOC @@ -335,28 +337,26 @@ relinquish (void) /* Return the last heap, with its header, to the system. */ excess = (char *)last_heap->end - (char *)last_heap->start; - last_heap = last_heap->prev; - last_heap->next = NIL_HEAP; + lh_prev = last_heap->prev; + /* If the system doesn't want that much memory back, leave + last_heap unaltered to reflect that. This can occur if + break_value is still within the original data segment. */ + if ((*real_morecore) (- excess) != 0) + { + last_heap = lh_prev; + last_heap->next = NIL_HEAP; + } } else { excess = (char *) last_heap->end - (char *) ROUNDUP ((char *)last_heap->end - excess); - last_heap->end = (char *) last_heap->end - excess; - } - - if ((*real_morecore) (- excess) == 0) - { - /* If the system didn't want that much memory back, adjust - the end of the last heap to reflect that. This can occur - if break_value is still within the original data segment. */ - last_heap->end = (char *) last_heap->end + excess; - /* Make sure that the result of the adjustment is accurate. - It should be, for the else clause above; the other case, - which returns the entire last heap to the system, seems - unlikely to trigger this mode of failure. */ - if (last_heap->end != (*real_morecore) (0)) - emacs_abort (); + /* If the system doesn't want that much memory back, leave + the end of the last heap unchanged to reflect that. This + can occur if break_value is still within the original + data segment. */ + if ((*real_morecore) (- excess) != 0) + last_heap->end = (char *) last_heap->end - excess; } } } -- 2.39.5