catching Runtime Stack Overflow Exception

  • Thread starter Thread starter assaf
  • Start date Start date
Catch the StackOverflowException. Example:

try
{
// Do something
}
catch( StackOverflowException e )
{
// Handle exception
}

-KIRBY
 
hi kirby.

i wrote exactly this code as u suggested.
however, the exception is not cought.
u can try it yoursef.
just call recursively the same function.

assaf
 
Stack overflows are usually fatal so the app may exit before your catch
handler gets called. Also, a blown stack might make it difficult, if not
impossible, to unwind the faulted thread.

You might try running the code that blows the stack on a worker thread - the
runtime might let the app live if its not the main thread that dies. In that
case you could try hooking the unhandled exception handler.

Also, even if the app gets shutdown I believe finalizers will still run so
you can still do some cleanup, but even that is problematic.

What are you trying to accomplish by catching this exception?
 
during stack overflow, finally blocks won't fire because there is no space
left. catching that exception is usually a sign of poor design. a stack
overflow should be allowed to take down the whole parade.
 
Alvin Bruney said:
during stack overflow, finally blocks won't fire because there is no space
left. catching that exception is usually a sign of poor design. a stack
overflow should be allowed to take down the whole parade.

I partially agree - it depends on a number of factors.

If the thread is the main app thread or in the default appdomain then I
agree, but the situation is not clear for other threads/appdomains. A
managed application ought to be able to setup an execution sandbox that
hosts other managed applications (i.e. in a separate appdomain). If the
sandbox crashes the main app should be able to survive it. An app that
utilizes a plugin architecture has similar concerns - I would not want an
ill-behaved plugin to crash my application. I ought to be able to run a
plugin on a separate thread and only that thread should die if there is a
stack overflow. How an application responds to a stack overflow is a policy
decision that a hosting application should be able to make.
 
hi david

i am running on a 'worker' thread.
with try-catch
nevertheless, it crashes the app.

assaf
 
hmmm, a few concerns come to mind (not thoroughly thought thru btw)

the stack overflow may or may not be coming from the plugin so catching
all stack overflows is not guaranteed to fix the broken case

in the case of a plugin running in its own separate appdomain, the
appdomain should isolate the hosting application from the catastrophic
failure. but you shouldn't attempt to catch the stack exception. the app
domain should be allowed to crash and the hosting application should simply
log the failure. no clean up is needed because the crashed appdomain should
be automatically unloaded.

in the case of the plugin running on a separate thread, it should be
allowed to kill the hosting application as well. the failure will be
restricted to the hosting app domain so it won't take down the webserver for
instance (on IIS 6 for instance, lesser versions will die).
How an application responds to a stack overflow is a policy
decision that a hosting application should be able to make.

So i'm not really clear what you mean by policy.
 
Alvin Bruney said:
hmmm, a few concerns come to mind (not thoroughly thought thru btw)

the stack overflow may or may not be coming from the plugin so catching
all stack overflows is not guaranteed to fix the broken case

I am not suggesting catching all stack overflows - an internal fault in the
host should crash it (a bug is a bug). However, IMO even there finally
blocks on non-faulted threads should still run and currently they will not
(I am not sure about finalizers - they usually run even when finally blocks
do not). This makes it difficult, perhaps impossible, to write critical
cleanup code that will behave correctly in all cases.
in the case of a plugin running in its own separate appdomain, the
appdomain should isolate the hosting application from the catastrophic
failure. but you shouldn't attempt to catch the stack exception. the app
domain should be allowed to crash and the hosting application should simply
log the failure. no clean up is needed because the crashed appdomain should
be automatically unloaded.
I agree, with the caveat that critical cleanup code on non-faulted threads
should still get the opportunity to try to run. It may not be possible, but
if code is critical it should still get an opportunity.
in the case of the plugin running on a separate thread, it should be
allowed to kill the hosting application as well. the failure will be
restricted to the hosting app domain so it won't take down the webserver for
instance (on IIS 6 for instance, lesser versions will die).

I agree, again with the same caveat.
So i'm not really clear what you mean by policy.
--

All I mean is that the decision to crash the application should be one that
the controlling host application should be allowed to make. This is similar
to allowing the host application to determine what happens in the event of
an unhandled exception - should the app swallow and ignore it? Or should the
application be terminated?
 
assaf said:
hi david

i am running on a 'worker' thread.
with try-catch
nevertheless, it crashes the app.
That answers the question, at least for this version of the runtime - it is
fatal.
 
assaf said:
there must be a way to prevent the application from crashing.
the stack-overflowing thread is just a background graphics analysis
operation.
my system should be able to recover from it.

here is its code that blows up the stack:
RectangleF[] rects = this._Region..GetRegionScans(this._Matrix);

as u can see, it is caused by a Region containing too many rectangles.
since a RectangleF is a struct, a value type,
the entire array is allocated on the stack.

No it's not. Arrays themselves are *always* reference types. The values
will be on the heap. It's more likely that GetRegionScans is recursing
too deeply.
 
hi David.

there must be a way to prevent the application from crashing.
the stack-overflowing thread is just a background graphics analysis
operation.
my system should be able to recover from it.

here is its code that blows up the stack:
RectangleF[] rects = this._Region..GetRegionScans(this._Matrix);

as u can see, it is caused by a Region containing too many rectangles.
since a RectangleF is a struct, a value type,
the entire array is allocated on the stack.

but this is something that if it happens, my application can simply ignore
it!
there is no way that this operation should bring down the entire
application.


please help me.

assaf
 
ok,

so what is the solution?

we are talking about a background analysis thread
that if it fails, the app could do without it.

the crash only happens when the system is overwhelmed with user input.
this is rare, but i would rather catch the exception then shut down
unexpectedly.

please help me.


assaf


Jon Skeet said:
assaf said:
there must be a way to prevent the application from crashing.
the stack-overflowing thread is just a background graphics analysis
operation.
my system should be able to recover from it.

here is its code that blows up the stack:
RectangleF[] rects = this._Region..GetRegionScans(this._Matrix);

as u can see, it is caused by a Region containing too many rectangles.
since a RectangleF is a struct, a value type,
the entire array is allocated on the stack.

No it's not. Arrays themselves are *always* reference types. The values
will be on the heap. It's more likely that GetRegionScans is recursing
too deeply.
 
assaf said:
so what is the solution?

we are talking about a background analysis thread
that if it fails, the app could do without it.

the crash only happens when the system is overwhelmed with user input.
this is rare, but i would rather catch the exception then shut down
unexpectedly.

please help me.

Well, can you post the code for GetRegionScans? It could be that you
can either detect when the stack is going to overflow, or rewrite it so
that it doesn't overflow in the first place.
 
A stack overflow is obviously a fatal condition, so your only option is to
avoid overflowing the stack.


As Jon said, post the code. You state that this only happens when the system
is overwhelmed with user input - what do you mean by this?
 
assaf said:
ok,

so what is the solution?

we are talking about a background analysis thread
that if it fails, the app could do without it.

the crash only happens when the system is overwhelmed with user input.
this is rare, but i would rather catch the exception then shut down
unexpectedly.

please help me.


*Every* recursive algorithm can be rewritten using a stack.
A good starting point is
"Algorithms in <insert you favorite language>" by Robert Sedgewick.

bye
Rob
 
yes, post that code. i fear you have some funky stuff going on inside that
routine.
 
hi david.

the user through interaction with the application causes rectangles to be
added to the region.
so if the user interacts a lot, many rectangles will be added to the region.


assaf
 
hi,
private RectangleF[] GetRegionScans(Region re)
{
Matrix m = new Matrix();
m.Reset();
RectangleF[] rects = re.GetRegionScans(m); // this line throws the
StackOverflowException!!!
return rects;
}

Are you kidding? :-) However, try this:

private RectangleF[] GetRegionScans(Region re)
{
Matrix m = new Matrix();
m.Reset();
// endless recursion condition
if (re != this) {
RectangleF[] rects = re.GetRegionScans(m);
return rects;
}
else {
return whatever but don't recurse!
}
}

bye
Rob
 
hi all

here is the code.
it is not so pretty.
but really its nothing more then:
put many rects into region.
get rects array from region -> crash
u can try it yourselves.

assaf

********************* my code ****************************

// background thread proc
private void ProcessBuffersThreadProc()
{
while(true)
{
try
{
this.ProcessBuffers();
}
catch(StackOverflowException ex)
{
WinForms.MessageBox.Show(ex.Message, this.ToString());
}
}
}

private void ProcessBuffers()
{
Region r = new Region();
r.MakeEmpty();
while(true)
{
if(this._Queue.Count == 0)
{
break;
}
object pBuff = this._Queue.Dequeue();
IntPtr ip = (IntPtr)pBuff; // queue contains buffers, each buffer is
an array of rects
// union add buff to region
this.GetAndUnionRects(ip, re); // iterate all rects, union-add them
each to our region
}
RectangleF[] rectArray;
rectArray = this.GetRegionScans(r); // crashes in here
// .... more fun stuff, that we never get to
}

private void GetAndUnionRects(IntPtr ip, Region r)
{
for(int j = 0; j < this.gArray.ulRects; j++)
{
Rectangle rect = this.GetRect(this.gArray.Rects[j]);
r.Union(rect); // this is where we add a rect into the region
}
}

private RectangleF[] GetRegionScans(Region re)
{
Matrix m = new Matrix();
m.Reset();
RectangleF[] rects = re.GetRegionScans(m); // this line throws the
StackOverflowException!!!
return rects;
}




********************* my code ****************************


assaf
 
Back
Top