public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* throwing exception when new fails
@ 1998-10-20 14:34 Nathan Sidwell
  1998-10-21  8:10 ` Martin von Loewis
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Nathan Sidwell @ 1998-10-20 14:34 UTC (permalink / raw)
  To: egcs

Some time ago I filed a bug report about throwing when there's no memory
( http://www.cygnus.com/ml/egcs-bugs/1998-Sep/0229.html ). The basic
problem is that this process invokes malloc (which doesn't have any
memory) -> boom!

Anyway, I've been figuring out how to fix this. I altered
__new_eh_context to have a static eh_context which it can use, should
malloc fail. Also I added a small buffer to eh_context, which __eh_alloc
and eh_free can use, should malloc fail. I've assumed that __eh_alloc
and eh_free are called in a stack-like manner (I had to alter
__cp_pop_exception, to do this). As __eh_alloc and __eh_free have become
more closely integrateed with __eh_context, I moved them to libgcc2
(from cp/exception.cc). This all works, and provides some degree of
safety in both single threaded and multithreaded applications.

Now the problem I've found is in frame.c. __throw calls 
__frame_state_for to obtain the function frame information. This ends up
generating an ordered list of the fde's (what's FDE stand for?), which
it then searches to locate the function information. This ordered list
is cached for futre use. *But*, guess what, frame_init calls malloc to
generate space for this list. I can find little documentation on what's
going on here. frame.c's pretty well commented, but omits the big
picture about what it's trying to acheive. From what I see modules can
register their functions with __register_frame_info or
__register_frame_info_table, and these get chained along. (I'm not sure
if this is also for DLL functions, I think not.) The first exception
thrown causes this list to be walked to create the ordered table.

Thus, I can fix things so that after the first exception, malloc dying
won't blow the exception mechanism away, but I can't see how to fix it
for the first one. Also, start_fde_sort, doesn't check malloc's failure
-- other parts of frame.c do check bogus info and abort if things are
awry.

Perhaps I should just punt it and if you want throw(bad_alloc) to work,
throw once per thread first (if that is acceptable, then I can simplify
my current fixes). Or perhaps we should allocate the space for the
ordered table during program start up. Suggestions?

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: throwing exception when new fails
  1998-10-20 14:34 throwing exception when new fails Nathan Sidwell
@ 1998-10-21  8:10 ` Martin von Loewis
  1998-10-21 11:41 ` Martin von Loewis
  1998-10-21 20:13 ` Kriang Lerdsuwanakij
  2 siblings, 0 replies; 7+ messages in thread
From: Martin von Loewis @ 1998-10-21  8:10 UTC (permalink / raw)
  To: nathan; +Cc: egcs



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: throwing exception when new fails
  1998-10-20 14:34 throwing exception when new fails Nathan Sidwell
  1998-10-21  8:10 ` Martin von Loewis
@ 1998-10-21 11:41 ` Martin von Loewis
  1998-10-21 20:13 ` Kriang Lerdsuwanakij
  2 siblings, 0 replies; 7+ messages in thread
From: Martin von Loewis @ 1998-10-21 11:41 UTC (permalink / raw)
  To: nathan; +Cc: egcs

> Now the problem I've found is in frame.c. __throw calls
> __frame_state_for to obtain the function frame information. This
> ends up generating an ordered list of the fde's (what's FDE stand
> for?)

Frame Descriptor Element. There is one per function, and it describes
where the function code is located, and what the register lifetimes
and stack layout are within the function.

The data structures are defined in the DWARF specfication, although
not in a very readable way.

Every time an exception is thrown, the code needs to locate the FDE
for the current function, and starts to look for exception regions
from that FDE. This works in a two-level search:
a) in a linear search, find the shared image (i.e. DLL) containing
   the PC
b) using the FDE table for that shared object, locate the FDE using
   binary search (which requires the sorting)

> Suggestions?

If malloc fails, one could try to locate the FDE using linear search.
Of course, this means that there would be considerable computational
overhead, and the code implementing it would rarely be used and not
well tested (unless you design some unit testing for it).

Hope this helps,
Martin

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: throwing exception when new fails
  1998-10-20 14:34 throwing exception when new fails Nathan Sidwell
  1998-10-21  8:10 ` Martin von Loewis
  1998-10-21 11:41 ` Martin von Loewis
@ 1998-10-21 20:13 ` Kriang Lerdsuwanakij
  2 siblings, 0 replies; 7+ messages in thread
From: Kriang Lerdsuwanakij @ 1998-10-21 20:13 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: egcs

On Tue, 20 Oct 1998, Nathan Sidwell wrote:

> Now the problem I've found is in frame.c. __throw calls 
> __frame_state_for to obtain the function frame information. This ends up
> generating an ordered list of the fde's (what's FDE stand for?), which
> it then searches to locate the function information. This ordered list
> is cached for futre use. *But*, guess what, frame_init calls malloc to
> generate space for this list. I can find little documentation on what's
> going on here. frame.c's pretty well commented, but omits the big
> picture about what it's trying to acheive. From what I see modules can
> register their functions with __register_frame_info or
> __register_frame_info_table, and these get chained along. (I'm not sure
> if this is also for DLL functions, I think not.) The first exception
> thrown causes this list to be walked to create the ordered table.

I proposed a patch to fix this particular problem long ago (achieved at 
http://www.cygnus.com/ml/egcs/1998-Mar/0320.html ).  It fellback to a
slower sequential search if it couldn't build a sorted list.  The patch is
out-of-date but I think the idea may be still useful.

--kriang


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: throwing exception when new fails
  1998-10-21 13:42 Mike Stump
@ 1998-10-22 18:00 ` Martin von Loewis
  0 siblings, 0 replies; 7+ messages in thread
From: Martin von Loewis @ 1998-10-22 18:00 UTC (permalink / raw)
  To: mrs; +Cc: egcs, nathan

> Preallocate at init time maybe?  Or maybe have a fallback that can
> walk unsorted chains if malloc fails.  Anyone else have any ideas on
> good solutions?  I think we've thought about named sections, and
> having the linker combine them, so in the end we wind up enough room
> for the data, but the one has to do something tricky for dyn loaded
> code and shared libraries.

I'd like to emphasize this option. Even if it works only with GNU ld,
there is still value in having the linker sort the FDEs, instead of
sorting at run time. The linker could set a bit somewhere to indicate
that it did the sorting, which would show drastic improvements in
memory consumtion and execution speed for large binaries.

All we need is a volunteer. :-)

Regards,
Martin

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: throwing exception when new fails
       [not found] <362CD14A.CA8.cygnus.egcs@acm.org>
@ 1998-10-21 22:10 ` Jason Merrill
  0 siblings, 0 replies; 7+ messages in thread
From: Jason Merrill @ 1998-10-21 22:10 UTC (permalink / raw)
  To: Nathan Sidwell, egcs

>>>>> Nathan Sidwell <nathan@acm.org> writes:

 > and eh_free can use, should malloc fail. I've assumed that __eh_alloc
 > and eh_free are called in a stack-like manner (I had to alter
 > __cp_pop_exception, to do this).

This is an invalid assumption; it is very possible for exceptions to be
freed in other than reverse order, because of the ability to rethrow.

Jason

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: throwing exception when new fails
@ 1998-10-21 13:42 Mike Stump
  1998-10-22 18:00 ` Martin von Loewis
  0 siblings, 1 reply; 7+ messages in thread
From: Mike Stump @ 1998-10-21 13:42 UTC (permalink / raw)
  To: egcs, nathan

> Date: Tue, 20 Oct 1998 19:07:06 +0100
> From: Nathan Sidwell <nathan@acm.org>
> To: egcs@cygnus.com

> Anyway, I've been figuring out how to fix this.

Your plans sound good.  I think you're on the right track.  I not sure
what is best when it comes to the large mallow up front for the entire
table.  It is there so that we can do a simple binary walk (fast) on
the data structure to look up EH related information during unwinding.

Preallocate at init time maybe?  Or maybe have a fallback that can
walk unsorted chains if malloc fails.  Anyone else have any ideas on
good solutions?  I think we've thought about named sections, and
having the linker combine them, so in the end we wind up enough room
for the data, but the one has to do something tricky for dyn loaded
code and shared libraries.

Thanks for thinking about these issue, and we all look forward to any
improvement you can bring to the code.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~1998-10-22 18:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-10-20 14:34 throwing exception when new fails Nathan Sidwell
1998-10-21  8:10 ` Martin von Loewis
1998-10-21 11:41 ` Martin von Loewis
1998-10-21 20:13 ` Kriang Lerdsuwanakij
1998-10-21 13:42 Mike Stump
1998-10-22 18:00 ` Martin von Loewis
     [not found] <362CD14A.CA8.cygnus.egcs@acm.org>
1998-10-21 22:10 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).