PATCH: Re: What happens when memory resources run out?

Nathan Sidwell nathan@acm.org
Thu Jan 21 03:27:00 GMT 1999


Loren J. Rittle wrote:
> I have a number of complex test cases that I have run against your
> patches.  Here are my comments:
Excellent.

> 1. In new_eh_context(), you changed the post-condition which ensured
>    that struct eh_context was always the first item in struct
>    eh_full_context.  As written, unless you have a buggy compiler,
>    your condition will always be true.  The old condition would catch
>    someone adding fields to struct eh_full_context incorrectly.  Since
>    I saw later that you added code to perform the correct offsetof()
>    calculation before free()ing, perhaps this entire post-condition
>    should be explicitly removed (or at least put back the way it was).
I've no preference here, I did think Mike was being rather paranoid with the
check.

> 2. In eh_context_free(), it is acceptable to perform the (ptr ==
>    &single_eh_context.context) check outside of holding the mutex,
>    thus I propose that the lock/unlock pair only appear within the
>    then-clause.  This way the nominal multi-threaded case of plain
>    free()ing will not incur the performance penalty of allocating the
>    mutex.  This is a performance issue only.
Yes, you are correct. I guess single_eh_alloc should be volatile too.

> 3. In frame.c, execute_cfa_insn(), is it really safe to return NULL
>    when memory can't be allocated for a "remembered" state?  It
>    appears (but I don't claim to understand) that __throw() or
>    throw_helper() will get a NULL back in this case.  They in turn
>    will call terminate() in that case.  Any idea how likely these
>    "remembered" states are to appear?  I have never seen one, but this
>    would appear to be a remaining hole in low-memory exception
>    handling.
Again, you are correct. The dwarf remember_state record is real nasty here. The
remember and restore records are available to insert function exit sequences
into the middle of a function, though they can be used anywhere you have one
branch of code which ends with a register state the same as it started. Of
course you can restore the register state with other dwarf records. From the
dwarf specs, it appears that remember state can be arbitrarily nested. I think
it's a bad design. A better choice would have been a skip record which allowed
an unwinder to ignore a whole set of dwarf records, if the PC was outside of
that block. Such a design would make unwinding quicker, but prevent sequential
emission of dwarf records (you'd have to back anotate for the forward
references). Luckily for us, egcs does not emit remember_state records. May be
we should put a depth one fallback in here too. It can be shared between
threads, as it not needed for unbounded periods of time.

> 5. If I link with -lpthread, none of my examples work when memory is
>    truly gone and exception handling kicks in for the first time
>    within a thread.  They fail with a form of the following backtrace
>    (taken right before malloc() would return NULL):
Bum, I was afraid of something like this. The only way I see of well and truely
knocking this on the head is to hook into the threading library's create thread
routine. We need to preallocate the thread context we require for exception
handling. If this is possible, then things become simpler. We need one static
instance of the eh_context, for non-threaded apps, and for threaded ones, the
context is created when the thread is. If we cannot hook into thread creation,
then perhaps we should provide a library function which can be explicitly
called at the start of a thread which allocates these objects and returns an
error code (rather than killing the program) in the event of failure.

> 7. One way to force this to be resolved early (either way :-), is to
>    insert this line of code at the top of any top-level function
>    (main() and those functions passed to pthread_create()):
> 
>    try {class dummy {}; throw dummy();} catch (...) {} // force init of EH
Yes, this is a good work around (the simpler 'try{throw 1;} catch(...)}' is
just as good). If memory is short at that point, the program will still die
horribly though.

> Conclusions:
> 
> 8. No behavior is worse with your patch than without it.  I agree with
>    the way you implemented everything except minor items noted in 1-3.
>    However, I don't claim to understand most of frame.c. :-)
thanks for taking the time to look at it. Point 5 is the next hurdle to
overcome for threaded exceptions, but I think this is a step in the right
direction and I'd like to get it deployed before progressing.

nathan
-- 
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
      You can up the bandwidth, but you can't up the speed of light      
nathan@acm.org  http://www.cs.bris.ac.uk/~nathan/  nathan@cs.bris.ac.uk



More information about the Gcc-patches mailing list