Why does my program loop on exception when debugging? [duplicate] - c#

(This looks very similar to C# UnhandledException from another thread keeps looping, but am not trying to catch the exception here, just get the chance to log something)
I have some very simple C# code that sets up an UnhandledException event handler, then throws an exception:
class Program
{
static void Main(string[] args)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
//currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
currentDomain.UnhandledException += (sender, eventArgs) =>
{
var exception = (Exception) eventArgs.ExceptionObject;
Console.WriteLine("Unhandled exception: " + exception.Message);
};
throw new AccessViolationException("Bleurgh");
}
}
It behaves as I expect from the console:
Unhandled exception: Bleurgh
Unhandled Exception: System.AccessViolationException: Bleurgh
at UnhandledExceptions.Program.Main(String[] args) in c:\code\sandbox\UnhandledExceptions\UnhandledExceptions\Program.cs:line 20
But when I attempt to debug it in Visual Studio it enters a loop, going into the event handler then dropping out to rethrow the Exception.
The same thing happens when I express the handler as a distinct static method.
Any ideas what's going on?
This is in Visual Studio 2010. EDIT: and .NET 4.

It seems to be down to the behaviour of the ExceptionAssistant specfically. When you continue, the assistant unwinds the call stack to the point at which the exception was thrown -- which causes the exception to be rethrown. I assume this is to allow you to make changes that would allow you to avoid the exception.
If under Tools\Options\Debugger\General you uncheck "Unwind the call stack on unhandled exceptions" then it'll just behave as an independent process would behave, and you'll see the process terminate.

This is how the debugger works, or shall we say, a "feature". If process is created by a debugger (F5) then debugger will prevent process termination, and point you to the line of code that would cause the process termination. Those "unhandled exceptions" are actually handled by the debugger, and so the execution never reaches to your code.
If debugger is attached to the process after the process was created (Ctrl+F5, and then attach) then debugger will eventually reach the unhandled exception "handler", but after exiting the handler it will still prevent process termination, and bring you back to the point where exception occurred.

Related

Global exception handler with UnhandledExceptionEventArgs not working

After reading this MSDN page, I've created a global exception handler in my .net class library, for logging purposes, which looks like this:
static void OnException(object sender, UnhandledExceptionEventArgs args)
{
Exception ex = (Exception)args.ExceptionObject;
Logging.LogException(ex);
}
But then if I throw new UnauthorizedAccessException() or throw new Exception() from a method, this does not catch it at all.
The MSDN page says:
UnhandledExceptionEventArgs provides access to the exception object
and a flag indicating whether the common language runtime is
terminating. The UnhandledExceptionEventArgs is one of the parameters
passed into UnhandledExceptionEventHandler for the
AppDomain.UnhandledException event
I believe what I'm doing falls under the AppDomain (and not ThreadException)? What am I doing wrong here?
PS. I'm trying to avoid a try-catch block, since apparently it's bad practice. This class library is called from a windows service which runs periodically so I'd rather not let it 'crash' to avoid memory leaks due to unforeseen exceptions and would prefer to monitor the event logs regularly.
You will need to install the exception handler in the current app domain in order for it to fire:
AppDomain.CurrentDomain.UnhandledException += OnException;
Otherwise its just a method declaration that will never be called.
You mention that you are trying to avoid a try catch, but inside your handler, that wouldn't be a bad idea:
static void OnException(object sender, UnhandledExceptionEventArgs args)
{
try
{
Exception ex = (Exception)args.ExceptionObject;
Logging.LogException(ex);
}
catch
{
// do nothing to silently swallow error, or try something else...
}
}
...Because you don't want to explode in your error handler. Either swallow if stability is of primary importance, or try a secondary (more basic) logging method to insure that no exception falls through the cracks.
Normally, swallowing an exception silently is a poor practice, but this is inside an error handling block where failure means crashing an app.

Why is Visual Studio looping when debugging UnhandledException events

(This looks very similar to C# UnhandledException from another thread keeps looping, but am not trying to catch the exception here, just get the chance to log something)
I have some very simple C# code that sets up an UnhandledException event handler, then throws an exception:
class Program
{
static void Main(string[] args)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
//currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
currentDomain.UnhandledException += (sender, eventArgs) =>
{
var exception = (Exception) eventArgs.ExceptionObject;
Console.WriteLine("Unhandled exception: " + exception.Message);
};
throw new AccessViolationException("Bleurgh");
}
}
It behaves as I expect from the console:
Unhandled exception: Bleurgh
Unhandled Exception: System.AccessViolationException: Bleurgh
at UnhandledExceptions.Program.Main(String[] args) in c:\code\sandbox\UnhandledExceptions\UnhandledExceptions\Program.cs:line 20
But when I attempt to debug it in Visual Studio it enters a loop, going into the event handler then dropping out to rethrow the Exception.
The same thing happens when I express the handler as a distinct static method.
Any ideas what's going on?
This is in Visual Studio 2010. EDIT: and .NET 4.
It seems to be down to the behaviour of the ExceptionAssistant specfically. When you continue, the assistant unwinds the call stack to the point at which the exception was thrown -- which causes the exception to be rethrown. I assume this is to allow you to make changes that would allow you to avoid the exception.
If under Tools\Options\Debugger\General you uncheck "Unwind the call stack on unhandled exceptions" then it'll just behave as an independent process would behave, and you'll see the process terminate.
This is how the debugger works, or shall we say, a "feature". If process is created by a debugger (F5) then debugger will prevent process termination, and point you to the line of code that would cause the process termination. Those "unhandled exceptions" are actually handled by the debugger, and so the execution never reaches to your code.
If debugger is attached to the process after the process was created (Ctrl+F5, and then attach) then debugger will eventually reach the unhandled exception "handler", but after exiting the handler it will still prevent process termination, and bring you back to the point where exception occurred.

How to fix "'System.AggregateException' occurred in mscorlib.dll"

I'm receiving an unhandled exception while debugging, and the program stops executing. The debugger doesn't show me the line so I don't know what to fix.
An unhandled exception of type 'System.AggregateException' occurred in mscorlib.dll
Additional information: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.
Cannot obtain value of local or argument '<this>' as it is not available at this instruction pointer, possibly because it has been optimized away. System.Threading.Tasks.TaskExceptionHolder
How can I troubleshoot this problem?
I also found this question which is pretty similar.
As the message says, you have a task which threw an unhandled exception.
Turn on Break on All Exceptions (Debug, Exceptions) and rerun the program.
This will show you the original exception when it was thrown in the first place.
(comment appended): In VS2015 (or above). Select Debug > Options > Debugging > General and unselect the "Enable Just My Code" option.
You could handle the exception directly so it would not crash your program (catching the AggregateException). You could also look at the Inner Exception, this will give you a more detailed explanation of what went wrong:
try {
// your code
} catch (AggregateException e) {
}
The accepted answer will work if you can easily reproduce the issue. However, as a matter of best practice, you should be catching any exceptions (and logging) that are executed within a task. Otherwise, your application will crash if anything unexpected occurs within the task.
Task.Factory.StartNew(x=>
throw new Exception("I didn't account for this");
)
However, if we do this, at least the application does not crash.
Task.Factory.StartNew(x=>
try {
throw new Exception("I didn't account for this");
}
catch(Exception ex) {
//Log ex
}
)
In my case I ran on this problem while using Edge.js — all the problem was a JavaScript syntax error inside a C# Edge.js function definition.

How can I get WinForms to stop silently ignoring unhandled exceptions?

This is getting extremely irritating. Right now I have a winforms application, and things were not working right, but no exceptions were being thrown as far as I could tell. After stepping through almost all pieces of relevant code, it turns out that an exception was being thrown at the start of my application.
Long story short, in WinForms, being as awesome as it is, if an exception occurs the WinForms library ignores it. No "an unhandled exception has occurred" JIT message is thrown, it just stops processing the current event and goes back to the GUI.
This is causing random bugs, because code to load data isn't being called due to the exception occurring prior to this data being loaded.
To see this in action I created a brand new WinForms application, and entered the following code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string blah = null;
blah.Trim();
}
}
Press F5 and the form loads without any errors showing, even though a null reference is being thrown.
I then tried to go to my Program.cs main method and add Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); to it. Still my form loads without causing any errors to be thrown.
Even though I know that I can tell VS to break on all exceptions, I find this situation really bad. It causes really wierd issues that are hard to debug in production, and as this is an internal tool I really want to have it so it actually errors out when an exception occurs, and not silently disregards it.
Does anyone know how to do this?
Update: Just to update on things I have learned from the comments.
This does appear to be a 64-bit issue with windows, as I learned from this question which I did not see before posting. In that question it pointed to a Microsoft bug report about this, which had this to say:
Hello,
This bug was closed as "External" because this behavior results from how x64 version of Windows handle exceptions. When a user mode exception crosses a kernel transition, x64 versions of Windows do not allow the exception to propagate. Therefore attached debuggers are unaware of the fact that an exception occured resulting in the debugger failing to break on the unhandled exception.
Unfortunately where is nothing that the Visual Studo team can do to address this, it is the result of operating system design. All feedback regarding this issue should be addressed to the Windows team; however the Windows team considers this to be the "correct" operating system design, and considers the x86 behavior to be "incorrect".
Best Regards,
Visual Studio Debugger
That being said, builds not run through visual studio (or using Ctrl+F5 to run) does seem to show the JIT exception message box EXCEPT if you have the following code in your Program.cs:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
That code will cause windows to ignore the exception.
However, if you (instead) subscribe to the Application.ThreadException event, not only will your exceptions be caught, visual studio's debugger will break on unhandled exceptions!
In your Program.cs' Main function you should also ensure that you've wrapped your call to open the form in a try/catch. Additionally use the AppDomain.UnhandledException to catch exceptions. We also add Application.ThreadException too.
I believe the following will give you hooks into all the exceptions that can be thrown...
static void Main()
{
try
{
System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
System.Windows.Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(OnGuiUnhandedException);
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
var form = new MainForm();
form.ShowDialog();
}
catch (Exception e)
{
HandleUnhandledException(e);
}
finally
{
// Do stuff
}
}
private static void HandleUnhandledException(Object o)
{
// TODO: Log it!
Exception e = o as Exception;
if (e != null)
{
}
}
private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs e)
{
HandleUnhandledException(e.ExceptionObject);
}
private static void OnGuiUnhandedException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
HandleUnhandledException(e.Exception);
}
Try the following.
Handle exceptions in your main application entry point.
Also, manage unhandled thread exceptions using a ThreadExceptionEventHandler
This is the code snippet:
[STAThread]
public static void Main(string[] args)
{
try
{
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
//your program entry point
}
catch (Exception ex)
{
//manage also these exceptions
}
}
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
ProcessException(e.Exception);
}
An easy fix is not to run under the debugger.
The debugger is masking the exception for some reason. If you run your app normally (Ctrl+F5), you'll get the usual "Unhandled exception has occurred in your application... Continue/Quit?" dialog.
Having experienced this often and identified the issue regarding 64 bit OS and the Form.Load event, I always just make a point of doing all my start up functions in the Form.Shown event. For all practical purposes this is the same thing (aside from a few rare, exceptional circumstances), and the JIT message is produced in the Shown event.

BackgroundWorker & Exceptions

The MSDN Docs says
If the operation raises an exception that your code does not handle, the BackgroundWorker catches the exception and passes it into the RunWorkerCompleted event handler, where it is exposed as the Error property of System.ComponentModel.RunWorkerCompletedEventArgs
But when I tried
_workers[i].DoWork += (s, args) =>
{
throw new Exception("Error!");
};
I get Exception Unhandled error ... The code doesn't seem to go to RunWorkerCompleted. How are errors supposed to be handled?
UPDATE
I have setup simple handlers
_workers[i].DoWork += (s, args) =>
{
throw new Exception("Error!");
}
...
_workers[i].RunWorkerCompleted += (s, args) =>
{
if (args.Error != null) {
string dummy = args.Error.Message;
}
...
};
The code never leaves DoWork
If an exception is thrown and passes through user frames but is then not caught by user code, it is considered "user-unhandled".
So I think there are 3 possibilities:
This is a first-chance exception - so if you press F5, the exception will propagate as normal.
Click "edit code" in the Exception Assistant. Then do some Edit and Continue to solve the problem.
Go to Debug->Exceptions and de-select the "user-unhandled" column.
If you are running through the debugger, Visual Studio will stop on exceptions in the BackgroundWorker.DoWork event handler rather than silently passing the exception to the RunWorkerCompleted event which is what happens when not in the debugger.
1) You can just hit F5 and continue execution to follow the exception (as RoadWarrior mentioned)
2) If that is too annoying, for DoWork don't use delegates/lambdas but use named methods and decorate with [DebuggerStepThrough] Attribute. This will let the debugger ignore that method and not stop on exception so you can view the "normal" behavior of the Backgroundworker.
See: Visual Studio 2008 Debugging - Skipping code
I've done exception handling in BackgroundWorker yesterday. I didn't add any throw in Worker's DoWork handler. If exception happens, you will be able to get it in RunWorkerCompleted without throwing it. Just don't forget to cancel you Worker if exception occurs.

Categories

Resources