I'm calling a native library that might be unstable and I want to make sure my C# app can survive a potential AccessViolationException. I found a way to catch the exceptions using <legacyCorruptedStateExceptionsPolicy enabled="true" /> in my App.config. Since the crash happens on a separate thread that I don't care about (I don't care if it dies), is it safe to keep my application running? If not, are there any mechanisms that would allow me to sandbox the native code to prevent crashes?
I don't just want to log the crash, I'm really trying to survive AccessViolationException.
I've tried executing the code in another AppDomain but it doesn't really help since it runs in the same process. I also already have a backup solution that relies on a new Process, and an IPC channel to communicate, but that's hard to maintain and debug. If I could do it in the main process that would simplify things a lot.
If you want to create an environment to test, just create a simple Win32 library with a single function that causes a crash (AccessViolationException).
C Header:
__declspec(dllexport) void do_crash();
C Source:
void do_crash()
{
int *b = NULL;
int c = b[3000];
}
C# source:
[DllImport("CrashLib.dll", EntryPoint = "do_crash")]
extern static void DoCrash();
static void Main(string[] args)
{
ExecuteSandboxed(delegate
{
DoCrash();
});
// Even if there's a AccessViolationException, I can keep going
Console.ReadLine();
}
private static void ExecuteSandboxed(Action action)
{
try
{
Task.Run(action).Wait();
Console.WriteLine("Success");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Exceptions in a Nutshell
The very basic idea behind exceptions is to say "This cannot be done" and to prevent the application from continuing with a corrupted state. When an exception is raised it usually allows for the application to current the situation and continue execution. This is done by rewinding the call stack and looking for exception handlers (try-catch blocks).
Exceptions can come from 3 major sources:
The application itself (using throw ...)
The OS - Exceptions such as FileNotFoundException
The CPU - Exception such as DivideByZeroException (which is raised because ALU can't preform such calculation)
The scariest exceptions by far are those raised by the CPU since they can leave it in an invalid state.
Furthermore exceptions can classified into one of three kinds:
Invalid Operation - Such exceptions are thrown when the application attempts to preform an invalid operation. Actions such as accessing nonexistent files, dividing by zero and so on.
Invalid thread state - Such exceptions are thrown when the state of a given thread is corrupted. Situations such as runtime-stack corruption are a possible cause.
Invalid process (application) state - Such exception are thrown when the entire application is in an invalid state. Running out of memory is a good example.
Each kind of exception is more severe then the one before. The first will terminate the current procedure and start call-stack rewind. The second will terminate the entire thread. And the last will terminate the entire application.
Note: The termination process is much more involved and exceptions are not really divided into the three kinds.
Understanding AccessViolationException
Now that we have a basic understanding of exceptions we can predict the state an AccessViolationException will leave our application in.
First of all, who throws the exception? This is kind of a trick question* but in practice it is thrown by the OS when it realizes that the address is not yet allocated to the process.
What kind of exception is it? Since the exception has nothing to do with the state of the thread nor the application; we just attempted to access "nonexistent" memory (much like we may attempt to access nonexistent files). This is clearly an Invalid Operation exception.
AccessViolationException is an Invalid Operation exception from the OS. Now that we know that we can safely continue execution sine we know for certain that we didn't invalided the CPU state, nor the Application state, nor the Thread state; we just attempted something illegal.
Related
I am currently managing a complicated application. It's written in C# and .Net 4.7.2.
Sometimes this program shuts down without notice. No error message even with a try/catch block and MessageBox.Show() in the Main method (I know it's probably not the best way but should work).
There are several threads running at different points, calling external DLLs and sometimes even drivers. So in order to log whether it's another thread that crashes the whole thing, I do this at the beginning :
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.ThreadException += Application_ThreadException;
Because I'm not sure which one is the correct one. In the methods, I log the Exception (after performing null checks) into a file (using File.AppendText and a timestamped based file).
Still nothing. The application keeps crashing after some random amount of time (between 2 and 6 hours) and I have no log information, no error message and I'm getting kind of lost here.
The app is running in Release mode and I cannot use Visual Studio to run the debugger into it (because that would make it easy). Maybe there's another way to run an external debugger ?
Can someone give me a hint on how to catch up for an exception that would cause an application to crash silently ?
Based on your explanations the only thing that brings to my mind is that you have some fire and forget threads in your application that throw exception sometimes but your application can't keep track of them to log or catch their exceptions.
Make sure all your tasks are awaited correctly and you don't have any async void method.
If you really need some fire and forget actions in your app, at least keep them alive with something like private Task fireAndForgetTaskAliver in your classes.
Another probability could be memory leak in your app that causes stack overflow exception.
The only way to catch an exception that is not caught anywhere in the code is indeed to look it the Windows Event Log, under Applications.
Thanks to Pavel Anikhouski for his comment.
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.
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.
What ?
I am developing a Console Application that needs to keep running 24/7 No Matter WhatIs there any way to stop a Multi-Threaded Application from getting blown up by some unhandled exception happening in "some thread somewhere" ?
Why ?
Please refrain from giving lessons like "you should manage all your exceptions", "this should never happen" etc. I have my reasons : We are in test deployment and we need to keep this running, log exceptions, and restart all threads again. If anything unplanned happens and causes an unhandled exception to be thrown, it needs to be detected and some method called to restart all threads(atomicity is impossible due due the tier design)
This being said, I am aware it might no be possible to restart an application from "within" if it has blown because of and UnhandledException (which I already implemented).
So far, I have used Quartz.net's FileScan Job and a Flag File to detect stuff like that and restart the application from outwards. But this sounds hacky to me. I would like to find something cleaner and less quick and dirty.
DownVoting / Sniping Warning : I KNOW this might NOT be possible "as is'". Please be creative/helpful rather than abruptly critic and think of this more as an "Open question"
If it is going to run 24/7 anyway, why not just write it as a Windows service and take advantage of the recovery options built right into windows?
This approach has the additional advantage of being able to survive a machine reboot, and it will log failures/restarts in the system event logs.
You need to attach an event handler to UnhandledException event on the Current AppDomain:
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler
Inside the handler, you will have to somehow save enough state (to a file, database, etc.) for the restarted application to pass along to the new threads. Then instantiate a new instance of your Console application with a call to System.Diagnostics.Process.Start("MyConsoleApp.exe").
Be very careful to introduce logic to avoid a continuous loop of crash/restart/crash/restart.
You can't keep a process running "no matter what". What if the process is killed?
You don't want to keep a process running "no matter what". What if the process state is corrupted in such a way that "bad things" happen if it keeps running?
Well I can think of a few drawbacks in the following solution, but it is good enough to me for the moment :
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
CS = new ConsoleServer();
CS.Run();
}
public static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception exception = (Exception)e.ExceptionObject;
Logger.Log("UNHANDLED EXCEPTION : " + e.ExceptionObject.ToString());
Process.Start(#"C:\xxxx\bin\x86\Release\MySelf.exe");
}
If your using .Net 2.0 and above, the answer is you can't.
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.
Taken from here:
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
If you want your application to survive, then you will need very aggressive try/catch around your methods so nothing escapes.
I would advise using a windows service as mentioned by others. It's the same as a console application, but with an extra bit of service layer code on top. You could take your console app and covert it to a service application easily. Just need to override service.start/pause/stop methods.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
.NET - What’s the best way to implement a “catch all exceptions handler”
I have a .NET console app app that is crashing and displaying a message to the user.
All of my code is in a try{<code>} catch(Exception e){<stuff>} block, but still errors are occasionally displayed.
In a Win32 app, you can capture all possible exceptions/crashes by installing various exception handlers:
/* C++ exc handlers */
_set_se_translator
SetUnhandledExceptionFilter
_set_purecall_handler
set_terminate
set_unexpected
_set_invalid_parameter_handler
What is the equivalent in the .NET world so I can handle/log/quiet all possible error cases?
You can add an event handler to AppDomain.UnhandledException event, and it'll be called when a exception is thrown and not caught.
Contrary to what some others have posted, there's nothing wrong catching all exceptions. The important thing is to handle them all appropriately. If you have a stack overflow or out of memory condition, the app should shut down for them. Also, keep in mind that OOM conditions can prevent your exception handler from running correctly. For example, if your exception handler displays a dialog with the exception message, if you're out of memory, there may not be enough left for the dialog display. Best to log it and shut down immediately.
As others mentioned, there are the UnhandledException and ThreadException events that you can handle to collection exceptions that might otherwise get missed. Then simply throw an exception handler around your main loop (assuming a winforms app).
Also, you should be aware that OutOfMemoryExceptions aren't always thrown for out of memory conditions. An OOM condition can trigger all sorts of exceptions, in your code, or in the framework, that don't necessarily have anything to do with the fact that the real underlying condition is out of memory. I've frequently seen InvalidOperationException or ArgumentException when the underlying cause is actually out of memory.
This article in codeproject by our host Jeff Atwood is what you need.
Includes the code to catch unhandled exceptions and best pratices for showing information about the crash to the user.
The Global.asax class is your last line of defense.
Look at:
protected void Application_Error(Object sender, EventArgs e)
method
Be aware that some exception are dangerous to catch - or mostly uncatchable,
OutOfMemoryException: anything you do in the catch handler might allocate memory (in the managed or unmanaged side of the CLR) and thus trigger another OOM
StackOverflowException: depending whether the CLR detected it sufficiently early, you might get notified. Worst case scenario, it simply kills the process.
You can use the AppDomain.CurrentDomain.UnhandledException to get an event.
Although catching all exceptions without the plan to properly handle them is surely a bad practice, I think that an application should fail in some graceful way. A crash should not scare the user to death, and at least it should display a description of the error, some information to report to the tech support stuff, and ideally a button to close the application and restart it. In an ideal world, the application should be able to dump on disk the user data, and then try to recover it (but I see that this is asking too much).
Anyway, I usually use:
AppDomain.CurrentDomain.UnhandledException
You may also go with Application.ThreadException Event.
Once I was developing a .NET app running inside a COM based application; this event was the very useful, as AppDomain.CurrentDomain.UnhandledException didn't work in this case.
I think you should rather not even catch all Exception but better let them be shown to the user. The reason for this is that you should only catch Exceptions which you can actually handle. If you run into some Exception which causes the program to stop but still catch it, this might cause much more severe problems.
Also read FAQ: Why does FxCop warn against catch(Exception)?.
Be aware that catching these unhandled exceptions can change the security requirements of your application. Your application may stop running correctly under certain contexts (when run from a network share, etc.). Be sure to test thoroughly.
it doesn't hurt to use both
AppDomain.CurrentDomain.UnhandledException
Application.ThreadException
but keep in mind that exceptions on secondary threads are not caught by these handlers; use SafeThread for secondary threads if needed