Stackoverflow.. literally.. on azure [duplicate] - c#

I have a recursive call to a method that throws a stack overflow exception. The first call is surrounded by a try catch block but the exception is not caught.
Does the stack overflow exception behave in a special way? Can I catch/handle the exception properly?
Not sure if relevant, but additional information:
the exception is not thrown in the main thread
the object where the code is throwing the exception is manually loaded by Assembly.LoadFrom(...).CreateInstance(...)

Starting with 2.0 a StackOverflow Exception can only be caught in the following circumstances.
The CLR is being run in a hosted environment* where the host specifically allows for StackOverflow exceptions to be handled
The stackoverflow exception is thrown by user code and not due to an actual stack overflow situation (Reference)
*"hosted environment" as in "my code hosts CLR and I configure CLR's options" and not "my code runs on shared hosting"

The right way is to fix the overflow, but....
You can give yourself a bigger stack:-
using System.Threading;
Thread T = new Thread(threadDelegate, stackSizeInBytes);
T.Start();
You can use System.Diagnostics.StackTrace FrameCount property to count the frames you've used and throw your own exception when a frame limit is reached.
Or, you can calculate the size of the stack remaining and throw your own exception when it falls below a threshold:-
class Program
{
static int n;
static int topOfStack;
const int stackSize = 1000000; // Default?
// The func is 76 bytes, but we need space to unwind the exception.
const int spaceRequired = 18*1024;
unsafe static void Main(string[] args)
{
int var;
topOfStack = (int)&var;
n=0;
recurse();
}
unsafe static void recurse()
{
int remaining;
remaining = stackSize - (topOfStack - (int)&remaining);
if (remaining < spaceRequired)
throw new Exception("Cheese");
n++;
recurse();
}
}
Just catch the Cheese. ;)

From the MSDN page on StackOverflowExceptions:
In prior versions of the .NET
Framework, your application could
catch a StackOverflowException object
(for example, to recover from
unbounded recursion). However, that
practice is currently discouraged
because significant additional code is
required to reliably catch a stack
overflow exception and continue
program execution.
Starting with the .NET Framework
version 2.0, a StackOverflowException
object cannot be caught by a try-catch
block and the corresponding process is
terminated by default. Consequently,
users are advised to write their code
to detect and prevent a stack
overflow. For example, if your
application depends on recursion, use
a counter or a state condition to
terminate the recursive loop. Note
that an application that hosts the
common language runtime (CLR) can
specify that the CLR unload the
application domain where the stack
overflow exception occurs and let the
corresponding process continue. For
more information, see
ICLRPolicyManager Interface and
Hosting the Common Language Runtime.

As several users have already said, you can't catch the exception. However, if you're struggling to find out where it's happening, you may want to configure visual studio to break when it's thrown.
To do that, you need to open Exception Settings from the 'Debug' menu. In older versions of Visual Studio, this is at 'Debug' - 'Exceptions'; in newer versions, it's at 'Debug' - 'Windows' - 'Exception Settings'.
Once you have the settings open, expand 'Common Language Runtime Exceptions', expand 'System', scroll down and check 'System.StackOverflowException'. Then you can look at the call stack and look for the repeating pattern of calls. That should give you an idea of where to look to fix the code that's causing the stack overflow.

As mentioned above several times, it's not possible to catch a StackOverflowException that was raised by the System due to corrupted process-state. But there's a way to notice the exception as an event:
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
Starting with the .NET Framework version 4, this event is not raised for exceptions that corrupt the state of the process, such as stack overflows or access violations, unless the event handler is security-critical and has the HandleProcessCorruptedStateExceptionsAttribute attribute.
Nevertheless your application will terminate after exiting the event-function (a VERY dirty workaround, was to restart the app within this event haha, havn't done so and never will do). But it's good enough for logging!
In the .NET Framework versions 1.0 and 1.1, an unhandled exception that occurs in a thread other than the main application thread is caught by the runtime and therefore does not cause the application to terminate. Thus, it is possible for the UnhandledException event to be raised without the application terminating. Starting with the .NET Framework version 2.0, this backstop for unhandled exceptions in child threads was removed, because the cumulative effect of such silent failures included performance degradation, corrupted data, and lockups, all of which were difficult to debug. For more information, including a list of cases in which the runtime does not terminate, see Exceptions in Managed Threads.

Yes from CLR 2.0 stack overflow is considered a non-recoverable situation. So the runtime still shut down the process.
For details please see the documentation http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx

You can't. The CLR won't let you. A stack overflow is a fatal error and can't be recovered from.

You can't as most of the posts are explaining, let me add another area:
On many websites you will find people saying that the way to avoid this is using a different AppDomain so if this happens the domain will be unloaded. That is absolutely wrong (unless you host your CLR) as the default behavior of the CLR will raise a KillProcess event, bringing down your default AppDomain.

It's impossible, and for a good reason (for one, think about all those catch(Exception){} around).
If you want to continue execution after stack overflow, run dangerous code in a different AppDomain. CLR policies can be set to terminate current AppDomain on overflow without affecting original domain.

Related

Does an appcrash with a STATUS_STACK_OVERFLOW in a .Net application mean the stack overflow occured in native code?

I get an appcrash with execution code c00000fd (STATUS_STACK_OVERFLOW) in ntdll.dll.
Does that mean there was a stack overflow somewhere in native code, outside my managed code? Because for managed code, we have System.StackOverflowException. But there is none in my case, and no stack trace that could provide a clue.
You cant catch System.StackOverflowException any more
Starting with .Net 2.0 they can only be caught in the following
circumstances.
The CLR is being run in a hosted environment where the host specifically allows for StackOverflow exceptions to be handled
The stackoverflow exception is thrown by user code and not due to an actual stack overflow situation (Reference)
Although the error says it occurred in ntdll.dll it is most likely caused form your code.
My first steps would be to add, or turn on your highest debug logging in production, so you can try to narrow down where it's happening and the circumstances.
Second I'd start debugging (attaching the debugger) and scrutinising that method class until you find it. Most likely it's due to some recursion, that's the first place I'd start looking.
Additional Resources and references
C# catch a stack overflow exception
How to find the source of a StackOverflowException in my application
How to debug System.StackOverflowException without link to source code?
How do I prevent and/or handle a StackOverflowException?
How to debug a stackoverflowexception in .NET
Troubleshooting Exceptions: System.StackOverflowException
StackOverflowException Class
In the .NET Framework 1.0 and 1.1, you could catch a
StackOverflowException object (for example, to recover from unbounded
recursion). Starting with the .NET Framework 2.0, you can’t catch a
StackOverflowException object with a try/catch block, and the
corresponding process is terminated by default. Consequently, you
should write your code to detect and prevent a stack overflow. For
example, if your app depends on recursion, use a counter or a state
condition to terminate the recursive loop.

C# stack overflow is not able to be handled [duplicate]

I have a recursive call to a method that throws a stack overflow exception. The first call is surrounded by a try catch block but the exception is not caught.
Does the stack overflow exception behave in a special way? Can I catch/handle the exception properly?
Not sure if relevant, but additional information:
the exception is not thrown in the main thread
the object where the code is throwing the exception is manually loaded by Assembly.LoadFrom(...).CreateInstance(...)
Starting with 2.0 a StackOverflow Exception can only be caught in the following circumstances.
The CLR is being run in a hosted environment* where the host specifically allows for StackOverflow exceptions to be handled
The stackoverflow exception is thrown by user code and not due to an actual stack overflow situation (Reference)
*"hosted environment" as in "my code hosts CLR and I configure CLR's options" and not "my code runs on shared hosting"
The right way is to fix the overflow, but....
You can give yourself a bigger stack:-
using System.Threading;
Thread T = new Thread(threadDelegate, stackSizeInBytes);
T.Start();
You can use System.Diagnostics.StackTrace FrameCount property to count the frames you've used and throw your own exception when a frame limit is reached.
Or, you can calculate the size of the stack remaining and throw your own exception when it falls below a threshold:-
class Program
{
static int n;
static int topOfStack;
const int stackSize = 1000000; // Default?
// The func is 76 bytes, but we need space to unwind the exception.
const int spaceRequired = 18*1024;
unsafe static void Main(string[] args)
{
int var;
topOfStack = (int)&var;
n=0;
recurse();
}
unsafe static void recurse()
{
int remaining;
remaining = stackSize - (topOfStack - (int)&remaining);
if (remaining < spaceRequired)
throw new Exception("Cheese");
n++;
recurse();
}
}
Just catch the Cheese. ;)
From the MSDN page on StackOverflowExceptions:
In prior versions of the .NET
Framework, your application could
catch a StackOverflowException object
(for example, to recover from
unbounded recursion). However, that
practice is currently discouraged
because significant additional code is
required to reliably catch a stack
overflow exception and continue
program execution.
Starting with the .NET Framework
version 2.0, a StackOverflowException
object cannot be caught by a try-catch
block and the corresponding process is
terminated by default. Consequently,
users are advised to write their code
to detect and prevent a stack
overflow. For example, if your
application depends on recursion, use
a counter or a state condition to
terminate the recursive loop. Note
that an application that hosts the
common language runtime (CLR) can
specify that the CLR unload the
application domain where the stack
overflow exception occurs and let the
corresponding process continue. For
more information, see
ICLRPolicyManager Interface and
Hosting the Common Language Runtime.
As several users have already said, you can't catch the exception. However, if you're struggling to find out where it's happening, you may want to configure visual studio to break when it's thrown.
To do that, you need to open Exception Settings from the 'Debug' menu. In older versions of Visual Studio, this is at 'Debug' - 'Exceptions'; in newer versions, it's at 'Debug' - 'Windows' - 'Exception Settings'.
Once you have the settings open, expand 'Common Language Runtime Exceptions', expand 'System', scroll down and check 'System.StackOverflowException'. Then you can look at the call stack and look for the repeating pattern of calls. That should give you an idea of where to look to fix the code that's causing the stack overflow.
As mentioned above several times, it's not possible to catch a StackOverflowException that was raised by the System due to corrupted process-state. But there's a way to notice the exception as an event:
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
Starting with the .NET Framework version 4, this event is not raised for exceptions that corrupt the state of the process, such as stack overflows or access violations, unless the event handler is security-critical and has the HandleProcessCorruptedStateExceptionsAttribute attribute.
Nevertheless your application will terminate after exiting the event-function (a VERY dirty workaround, was to restart the app within this event haha, havn't done so and never will do). But it's good enough for logging!
In the .NET Framework versions 1.0 and 1.1, an unhandled exception that occurs in a thread other than the main application thread is caught by the runtime and therefore does not cause the application to terminate. Thus, it is possible for the UnhandledException event to be raised without the application terminating. Starting with the .NET Framework version 2.0, this backstop for unhandled exceptions in child threads was removed, because the cumulative effect of such silent failures included performance degradation, corrupted data, and lockups, all of which were difficult to debug. For more information, including a list of cases in which the runtime does not terminate, see Exceptions in Managed Threads.
Yes from CLR 2.0 stack overflow is considered a non-recoverable situation. So the runtime still shut down the process.
For details please see the documentation http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx
You can't. The CLR won't let you. A stack overflow is a fatal error and can't be recovered from.
You can't as most of the posts are explaining, let me add another area:
On many websites you will find people saying that the way to avoid this is using a different AppDomain so if this happens the domain will be unloaded. That is absolutely wrong (unless you host your CLR) as the default behavior of the CLR will raise a KillProcess event, bringing down your default AppDomain.
It's impossible, and for a good reason (for one, think about all those catch(Exception){} around).
If you want to continue execution after stack overflow, run dangerous code in a different AppDomain. CLR policies can be set to terminate current AppDomain on overflow without affecting original domain.

Is there any way to print any extended information on StackOverflowException?

One of my clients reported that the software I develop terminates unexpectedly. In app log, the only text available is Process is terminated due to StackOverflowException. There is no more information which would help me diagnose and fix it.
Is there any way to get the location where the exception was thrown? VS breaks on StackOverflowException, but is there any feasible method of diagnosing it without running the application in the debugger (or looking for it in all methods which contain recursion)?
You cannot normally execute any code after a stack overflow, it's one of the rare uncatchable fatal exceptions, so you cannot simply catch it to log any extended details.
The only way you could work around that is by tracking the exceptions from outside of the code that has a stack overflow. You would need to create a native code application to hosts the CLR. If you do that, you can specify that StackOverflowException is not 100% fatal. This is briefly mentioned on the StackOverflowException MSDN page:
If your app hosts the common language runtime (CLR), it can specify that the CLR should unload the application domain where the stack overflow exception occurs and let the corresponding process continue. For more information, see ICLRPolicyManager Interface.
But even that would still mean that a simple try...catch is not sufficient to actually catch the exception. You would have to make sure that the exception handling is not done from the app domain that has a stack overflow. It might be done from a different app domain, or it might be done from unmanaged code.

Can I prevent StackOverflowException from crashing my debuggee in Visual Studio?

I'm debugging a 3rd party library that is littered with properties that occasionally throw StackOverFlowException.
Whenever I look at objects from this library in the Watch window, I end up getting the error message "Function evaluation was aborted" and the app I'm debugging crashes.
I wrote an example of a property that reproduces this (when trying to evaluate it in the Watch window):
private static int CausesStackoverflow
{
get { return CausesStackoverflow; }
}
Is there any way to evaluate properties in the Watch window without risking my app crashing due to a Stackoverflow?
You should prevent (using counters or other tricks) and not catch StackOverflowExceptions.
Since this is 3rd party code (so I suppose it can't be changed) you can try this:
Starting with 2.0 a StackOverflow Exception can only be caught in the following circumstances.
The CLR is being run in a hosted environment where the host specifically allows for StackOverflow exceptions to be handled
The stackoverflow exception is thrown by user code and not due to an actual stack overflow situation (Reference)
From MSDN StackOverflowException page:
In prior versions of the .NET
Framework, your application could
catch a StackOverflowException object
(for example, to recover from
unbounded recursion). However, that
practice is currently discouraged
because significant additional code is
required to reliably catch a stack
overflow exception and continue
program execution.
Starting with the .NET Framework
version 2.0, a StackOverflowException
object cannot be caught by a try-catch
block and the corresponding process is
terminated by default. Consequently,
users are advised to write their code
to detect and prevent a stack
overflow. For example, if your
application depends on recursion, use
a counter or a state condition to
terminate the recursive loop. Note
that an application that hosts the
common language runtime (CLR) can
specify that the CLR unload the
application domain where the stack
overflow exception occurs and let the
corresponding process continue. For
more information, see
ICLRPolicyManager Interface and
Hosting the Common Language Runtime.

C# - How does one handle/catch StackOverFlowExceptions?

I don't need a lesson in switching from recursive to non-recursive means, I just want to know why we can't deal with this type of exception. Regardless, I'm using recursive functions on very large lists.
I have written code to attempt to catch StackOverFlowExceptions:
try { recursiveFxn(100000); }
catch(Exception){}
private void recursiveFxn(int countdown)
{
if (countdown > 0)
recursiveFxn(countdown - 1);
else
throw new Exception("lol. Forced exception.");
}
But still I get program crashes (in both NUnit and a webpage I'm running). Why isn't the exception caught?
Since .NET Framework 2.0, StackOverflowException cannot be caught. This is because it is considered a bad practice. Quoting the MSDN documentation:
Starting with the .NET Framework
version 2.0, a StackOverflowException
object cannot be caught by a try-catch
block and the corresponding process is
terminated by default. Consequently,
users are advised to write their code
to detect and prevent a stack
overflow. For example, if your
application depends on recursion, use
a counter or a state condition to
terminate the recursive loop.
Now, the only way to catch a StackOverflowException is when it was thrown by user code, as explained in a blog by Jared Parsons. Other than that, by hosting the CLR, you can handle (but not catch) a StackOverflowException and devise a way to let the execution of your program continue.
Note that because the stack is unwound when an exception occurs, in pre-2.0 versions of .Net the stack would actually be much shorter when the StackOverflowException is handled, making it possible to do so without generating another StackOverflowException.
You can't catch a stack overflow exception because when it happens it kills the thread dead. Try... catch... is performed by the same thread so that won't work. There may be some lower level APIs that you could P/Invoke and have another thread catch it.
There may also be some lower level APIs to change the maximum stack size, but I don't see anything in the .NET Framework to help with that so again you would need to P/Invoke something.

Categories

Resources