I have a fun issue where during application shutdown, try / catch blocks are being seemingly ignored in the stack.
I don't have a working test project (yet due to deadline, otherwise I'd totally try to repro this), but consider the following code snippet.
class IndexNotFoundException : Exception { }
public static string RunAndPossiblyThrow(int index, bool doThrow)
{
try
{
return Run(index);
}
catch(IndexNotFoundException e)
{
if(doThrow)
throw;
}
return "";
}
public static string Run(int index)
{
if(_store.Contains(index))
return _store[index];
throw new IndexNotFoundException ();
}
public static string RunAndIgnoreThrow(int index)
{
try
{
return Run(index);
}
catch(IndexNotFoundException e)
{
}
return "";
}
During runtime this pattern works famously. We get legacy support for code that relies on exceptions for program control (bad) and we get to move forward and slowly remove exceptions used for program control.
However, when shutting down our UI, we see an exception thrown from "Run" even though "doThrow" is false for ALL current uses of "RunAndPossiblyThrow". I've even gone so far as to verify this by modifying code to look like "RunAndIgnoreThrow" and I'll still get a crash post UI shutdown.
Mr. Eric Lippert, I read your blog daily, I'd sure love to hear it's some known bug and I'm not going crazy.
EDIT
This is multi-threaded, and I've verified all objects are not modified while being accessed
EDIT
Explicitly show exception is ours
EDIT
forgot to mention, this is on closing, and unfortunately visual studio cannot catch the crash directly. It's likely crashing on a thread other than the UI thread, and once the main closes, this closes. I've only been able to debug this by repeatedly running & closing the application, with task manager open, "Create Dump File" and looking at the resulting 400+mb mess in Windbg. Win7 64 for reference. Make sure this makes sense to you.
EDIT
The following code on shutdown still shows the same exception.
class IndexNotFoundException : Exception { }
public static string RunAndPossiblyThrow(int index, bool doThrow)
{
try
{
return Run(index);
}
catch
{
}
return "";
}
public static string Run(int index)
{
if(_store.Contains(index))
return _store[index];
throw new IndexNotFoundException ();
}
The only thing that seems to get rid of the exception is to go straight to
class IndexNotFoundException : Exception { }
public static string RunAndPossiblyThrow(int index, bool doThrow)
{
try
{
return Run(index);
}
catch
{
}
return "";
}
public static string Run(int index)
{
if(_store.Contains(index))
return _store[index];
return "";
}
Naturally the exception's gone, but my fears of going crazy are still present.
EDIT
it just got worse... this still crashes...
class IndexNotFoundException : Exception { }
public static string RunAndPossiblyThrow(int index, bool doThrow)
{
try
{
throw new IndexNotFoundException();
}
catch
{
}
return "";
}
EDIT
I have a distinct feeling this is going to get me nowhere. On top of the wierd behavior, I can also note that during execution of the UI in the above case, the try catch is being executed faithfully. My UI doesn't crash & it's full of empty strings. However once I start closing the UI, the crash shows itself and the try catch no longer holds back the exception.
EDIT & final
Apparently the dump file was listing in it the most recent first-chance exception. I verified this by creating a new project that threw inside a try catch & slept for 10 seconds. During the wait I got the .dmp file & sure enough, my completely caught exception was showing up.
I'll mark some points for the useful answers, however unfortunately there's still no rhyme or reason why my code is crashing...
Add an Exception as an extra catch. I think you are getting some other exception than ApplicationException and that is the one crashing your app.
There are various exceptions that cannot be caught. Stack Overflow in particular! Could one of these be occurring somewhere in your code?
See http://www.bluebytesoftware.com/blog/PermaLink,guid,223970c3-e1cc-4b09-9d61-99e8c5fae470.aspx
Have you tried adding a "finally" clause? just to see if it won't ignore the try/catch completely? In theory it should always jump to that line before it exits the try/catch no matter what.
If it still ignore that then there is something definitely strange about it.
Probably you catch and throw again some other exception from Run. Probably _store is null or something.
A few things that may help with diagnosis:
Register for AppDomain.CurrentDomain.UnhandledException so you can see if something is crashing on a thread other than the UI thread
Register for Application.ThreadException to catch any exceptions not being caught in the UI thread
Since this is happening during shutdown, are you using any Finalizers that could be throwing on the finalizer thread?
Related
For a long time I thought that it allows me to free up all the resources in the finally block and I thought that if an exception happens in the try block, then the resources will still be free up in the finally block. But that seems not to be the case.
I have the following piece of code:
using System;
public sealed class Program
{
public static void Main()
{
try {
int zero = 0;
int i = 1/zero;
} finally {
Console.WriteLine("divide by zero"); //the line is never called
}
}
}
I never reach the line which prints to the console. That means that I will not be able to free up resource in finally block in this case on the exception being thrown inside the try block.
So, I believe there are two things: either I am missing something or the try + finally combination has no use cases in the C#. The second statement makes sense, because I will get the same functionality as is produced by the above code with the code below:
using System;
public sealed class Program
{
public static void Main()
{
int zero = 0;
int i = 1/zero;
Console.WriteLine("divide by zero"); //the line is never called
}
}
But I am afraid that I might be missing something here. So, could someone confirm that the combination is useless or prove that it is not, please?
UPDATE
After the comment which is able to call the finally block in its fiddle, I checked once more in the VS Code, and still I see no output.
You're assumptions are incorrect (sometimes) https://dotnetfiddle.net/hjqmOS
try-finally (C# Reference)
By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block. Typically, the statements of a finally block
run when control leaves a try statement. The transfer of control can
occur as a result of normal execution, of execution of a break,
continue, goto, or return statement, or of propagation of an exception
out of the try statement.
There are cases when it doesn't run though
Within a handled exception, the associated finally block is guaranteed
to be run. However, if the exception is unhandled, execution of the
finally block is dependent on how the exception unwind operation is
triggered. That, in turn, is dependent on how your computer is set up.
Here is the important part
Usually, when an unhandled exception ends an application, whether or
not the finally block is run is not important. However, if you have
statements in a finally block that must be run even in that situation,
one solution is to add a catch block to the try-finally statement.
Alternatively, you can catch the exception that might be thrown in the
try block of a try-finally statement higher up the call stack.
try/catch/finally has nothing to do with freeing up resources. This is strictly application flow and error handling construct. You live in the managed code and garbage collector frees up resources. This construct does the following
try
{
int zero = 0;
int i = 1/zero;
}
catch (DividedByZeroException ex)
{
Console.WriteLine(Exception handled);
throw; // propagate ex to caller
}
finally
{
Console.WriteLine("Method ended execution"); // called with or without exception
}
I believe this is because you have VS to break on unhandled errors and thus VS steps in displaying the exception. If you compile it and run it manually on the command line I believe you will see "divide by zero". Also, instead of changing your VS settings, you can 'handle' the error and then should see the behavior you expect.
Example:
using System;
public sealed class Program
{
public static void Main()
{
try
{
int zero = 0;
int i = 1 / zero;
}
catch
{
}
finally
{
Console.WriteLine("divide by zero");
}
}
}
For a long time I thought that it allows me to free up all the resources in the finally block and I thought that if an exception happens in the try block, then the resources will still be free up in the finally block. But that seems not to be the case.
I have the following piece of code:
using System;
public sealed class Program
{
public static void Main()
{
try {
int zero = 0;
int i = 1/zero;
} finally {
Console.WriteLine("divide by zero"); //the line is never called
}
}
}
I never reach the line which prints to the console. That means that I will not be able to free up resource in finally block in this case on the exception being thrown inside the try block.
So, I believe there are two things: either I am missing something or the try + finally combination has no use cases in the C#. The second statement makes sense, because I will get the same functionality as is produced by the above code with the code below:
using System;
public sealed class Program
{
public static void Main()
{
int zero = 0;
int i = 1/zero;
Console.WriteLine("divide by zero"); //the line is never called
}
}
But I am afraid that I might be missing something here. So, could someone confirm that the combination is useless or prove that it is not, please?
UPDATE
After the comment which is able to call the finally block in its fiddle, I checked once more in the VS Code, and still I see no output.
You're assumptions are incorrect (sometimes) https://dotnetfiddle.net/hjqmOS
try-finally (C# Reference)
By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block. Typically, the statements of a finally block
run when control leaves a try statement. The transfer of control can
occur as a result of normal execution, of execution of a break,
continue, goto, or return statement, or of propagation of an exception
out of the try statement.
There are cases when it doesn't run though
Within a handled exception, the associated finally block is guaranteed
to be run. However, if the exception is unhandled, execution of the
finally block is dependent on how the exception unwind operation is
triggered. That, in turn, is dependent on how your computer is set up.
Here is the important part
Usually, when an unhandled exception ends an application, whether or
not the finally block is run is not important. However, if you have
statements in a finally block that must be run even in that situation,
one solution is to add a catch block to the try-finally statement.
Alternatively, you can catch the exception that might be thrown in the
try block of a try-finally statement higher up the call stack.
try/catch/finally has nothing to do with freeing up resources. This is strictly application flow and error handling construct. You live in the managed code and garbage collector frees up resources. This construct does the following
try
{
int zero = 0;
int i = 1/zero;
}
catch (DividedByZeroException ex)
{
Console.WriteLine(Exception handled);
throw; // propagate ex to caller
}
finally
{
Console.WriteLine("Method ended execution"); // called with or without exception
}
I believe this is because you have VS to break on unhandled errors and thus VS steps in displaying the exception. If you compile it and run it manually on the command line I believe you will see "divide by zero". Also, instead of changing your VS settings, you can 'handle' the error and then should see the behavior you expect.
Example:
using System;
public sealed class Program
{
public static void Main()
{
try
{
int zero = 0;
int i = 1 / zero;
}
catch
{
}
finally
{
Console.WriteLine("divide by zero");
}
}
}
In C# I'm trying to modify the StackTrace property of a custom exception I created. For this, I just override the StackTrace getter and it seems to be working (Exception has it as a virtual method, so it should work). This is my custom exception:
class CustomTimeoutException : Exception
{
private string oldStack;
public CustomTimeoutException(string message, String stack)
: base(message)
{
oldStack = stack;
}
public override string StackTrace
{
get
{
return oldStack;
}
}
public override string Message
{
get
{
return "lalalala2";
}
}
public override System.Collections.IDictionary Data
{
get
{
return null;
}
}
}
I'm using this class the following way:
class Program
{
static void Main(string[] args)
{
try
{
Program p = new Program();
p.throwTimeout2();
}
catch(TimeoutException e)
{
CustomTimeoutException tor = new CustomTimeoutException(e.Message + "with more", e.StackTrace);
Console.WriteLine(tor);
Console.WriteLine(tor.StackTrace);
throw tor;
}
}
public void throwTimeout2()
{
throwTimeout();
}
public void throwTimeout()
{
throw new TimeoutException("this is a message ");
}
}
When I write the property StackTrace to the console, it prints the StackTrace of the TimeoutException, which means it's in fact overriding it. But, when the console shows the error, the StackTrace is not the one it gets from my property, yet the Message is the one it gets from the Message property I'm also overriding.
So, where does the console get the StackTrace of the exception from? I'm using Visual Studio for running.
(Note: one thing I still really don't understand about your question is that, while you seem to be asking for a way to affect how an exception is reported to the console, you also say that you have some "tool" that apparently has access to the Exception object itself and is reporting on the inner-most exception, i.e. following the InnerException property chain until it reaches the last one. These two statements seem to be in contradiction with each other, so I'm not really sure I completely understand the question. Still, I spent some time looking into it, and will share what I have regardless. :) .)
IMHO, there is not a good way to do what you want. There is an ugly way (see below), but I don't recommend it. Especially since your main limitation is the "tool that uses the message"; it is IMHO a very bad idea to go changing production code just to suit some tool. That path leads to big maintenance headaches, if not outright buggy code.
If you really must change the exception message, you should just bite the bullet and toss the entire stack trace text you want to preserve into the message as well. Trying to mess around with the stack trace of the eventually-thrown exception itself is bad news.
That said…
If you were to add diagnostic calls to Console.WriteLine() to your method overrides, you would confirm (as you've probably already guessed) that the StackTrace property is not called when the exception is re-thrown and reported by the CLR to the console. Overriding the property is not going to help.
There are at least two problems with trying that strategy:
The StackTrace property is just a string containing formatted information about the stack trace. The Exception object does actually contain a private field _stackTrace. When you execute the throw statement with an Exception object, the CLR stores the current stack trace information into this field. You would have to find some way to overwrite this field after the fact, to fake a throw site different from the actual one.
The CLR exception handling leverages existing Windows exception handling infrastructure. One of the first things that happens when an exception is thrown is the exception handling code attempts to find a handler up the stack. If it fails to find one, then you get the "Unhandled Exception:" message. But note that in the process, the stack has not been unwound. Thus, the exception handling code does not even need to inspect the Exception object at all to determine the throw site; the stack is still there, and its state can be reported directly. There is literally nothing you can do with the Exception object that would affect reporting, if indeed the exception handling code is looking directly at the stack state.
Now, as it happens, for the version of .NET I'm running on my Windows 8.1 machine, it appears that the CLR is reporting the stack trace as stored in the Exception object and not directly inspecting the stack, per option #2 above. So something like this actually works:
ExceptionWrapper class
class ExceptionWrapper : Exception
{
private readonly string _trace;
private readonly string _message;
private readonly string _toString;
private readonly object _stackTrace;
public ExceptionWrapper(Exception e)
{
_trace = e.StackTrace;
_message = e.Message + ", wrapped";
_toString = e.ToString();
_stackTrace = typeof(Exception).GetField("_stackTrace",
BindingFlags.NonPublic | BindingFlags.Instance).GetValue(e);
}
public override string StackTrace { get { return _trace; } }
public override string Message
{
get
{
typeof(Exception)
.GetField("_stackTrace", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(this, _stackTrace);
return _message;
}
}
public override string ToString() { return _toString; }
}
Test program
class Program
{
static void Main(string[] args)
{
try
{
M1();
}
catch (Exception e)
{
throw;
}
}
private static void M1()
{
try
{
M();
}
catch (Exception e)
{
throw new ExceptionWrapper(e);
}
}
static void M()
{
throw new Exception("test exception");
}
}
There is a very significant caveat though. This works only because of two specific facts:
The CLR is not taking advantage of the current stack state, but instead is trusting the Exception object to contain correct stack information in the _stackTrace field.
The CLR calls the Message getter of the Exception object before retrieving the stack trace. This gives the object an opportunity to overwrite the _stackTrace field before the CLR accesses it for the purpose of reporting the stack trace.
Both of these are, as near as I can tell, completely undocumented implementation details. The second one in particular is very fragile; while I can see why the CLR might always have to stick with the first detail, I see no reason at all that Microsoft (never mind other implementors of the CLS) should feel compelled to preserve the behavior in the second point.
Writing code that relies on these implementation details is just asking for trouble. Whatever the broader goal here is, I simply cannot imagine it would be worthwhile to suffer the risk of breaking your project for this need. IMHO, it would be much more reasonable to simply rewrite this "tool" you are trying to accommodate.
Tools are (or at least should be) inherently simple in nature, and not only would rewriting it allow you to produce the results you want without mucking around with private implementation details in third-party code, it would also give you the chance to a) add new features, such as providing options for controlling how to process exception data (e.g. looking at something other than the inner-most exception), and b) have a tool for which you do have the source code, with which you can make further improvements in the future.
I strongly advise that you not paint yourself into this particular corner. :)
I'm developing C# application for windows phone 8.1 (Silverlight). Lately I've came across the problem connected to application falling asleep and storyboards.
The construction goes as follows:
class X : DependencyObject
{
public static readonly DependencyProperty vProperty =
DependencyProperty.Register("v", typeof(double), typeof(X), new PropertyMetadata(0.0));
public double v
{
get
{
return (double)GetValue(vProperty);
}
set
{
SetValue(vProperty, value);
}
}
private Storyboard _storyboard;
void Prepare()
{
_storyboard = new Storyboard();
var animation= new DoubleAnimation
{
From = 0,
To = 1,
BeginTime = 0,
Duration = 0,
};
_storyboard.Children.Add(animation);
Storyboard.SetTarget(animation, this);
Storyboard.SetTargetProperty(animation, vProperty);
}
void Go()
{
_storyboard.Begin();
}
}
There is a NullReferenceException thrown from inside of _storyboard.Begin() if application is placed in background between "Prepare" and "Go" (about 10% reproduction rate). Of course it ends up with crash.
I was not able to determine problem source and as I need quickfix for that I've decided to just catch this NullRefereneceException in this rare scenario. This is where real question starts. I've changed "Go" implementation to:
public void Go()
{
Debug.WriteLine("BreakPoint 1");
try
{
_storyboard.Begin();
}
catch (NullReferenceException)
{
Debug.WriteLine("BreakPoint 2");
}
}
Afterwards the crash is not reproducible at all, but the problem is that "BreakPoint 2" is never hit (no printout in Output either). "BreakPoint 1" is normally hit and printed as well. Changing NullReferenceException to other Exception type (not parent type ofc) causes crash to reappear.
So... What's going on here? Is this crash cached or not? What kind of weird behavior is that? Is it safe to assume that it will work as expected?
Additional question: Maybe you know why the original code crashes in the first place?
EDIT:
End of stack trace of internalException of TargetInvocationExceptions looks as follows:
at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
at MS.Internal.XcpImports.Storyboard_Begin(Storyboard storyboard)
at System.Windows.Media.Animation.Storyboard.Begin()
at X.Go()
I know that you've said that you've tried to use parent types for NullReferenceException, but please try the following without running in the debugger:
public void Go()
{
Debug.WriteLine("BreakPoint 1");
try
{
_storyboard.Begin();
}
catch (Exception)
{
Debug.WriteLine("BreakPoint 2");
System.Diagnostics.Debugger.Break();
}
}
My suspicion is that the catch is not firing because you are running from within the debugger. Also try System.Diagnostics.Debugger.Launch(); in the catch if .Break(); does not work. And finally also try throw; in the catch if .Launch(); does not work.
If the debugger attempts to launch in either case, then you have another clue.
UPDATE:
I can't give you all of the reasons why this might happen as it may not be possible to determine precisely what is causing it in your situation.
I've seen behavior like this due to use of multithreading. Multithreading can behave differently when running with a debugger attached then without. Timing issues and race conditions can prevent exceptions from being thrown while in the debugger that otherwise may occur frequently when there is no debugger attached.
I've also encountered instances where System.Diagnostics.Debugger.IsAttached was used in third party code and even my team's code which caused the application to behave differently based on if statements using this check.
And lastly, I've had times where I could not come up with a specific reason why the behavior was occurring. I've learned to use the System.Diagnostics.Debugger.Break() method whenever I see behavior exhibited differently depending on whether a debugger is attached or not. Sometimes it really is just a gut feeling.
I have some code that currently looks somewhat like this:
public void MainFunction()
{
try
{
SomeProblemFunction();
}
catch
{
AllFineFunction();
}
}
private void SomeProblemFunction() { ... }
private void AllFineFunction() { ... }
As you can see, I'm currently wrapping the call to SomeProblemFunction around a try statement because that function could fail (it relies on an outside web service call).
My question is this: should the try statement be a) outside the problem function (like I have it now) or b) inside the problem function?
Thanks.
Typically you want to allow your exceptions propagate up to your application boundaries. You're only going to want to do one of a few things with your exception:
Wrap it
Replace it
Let it propagate
Update
From your question it seems that you are looking for a fault tolerant solution for your web service calls. This is a more complex problem than simply "where do I put my try-catch?" You would still place your exception handling at the application boundary, but there you would implement your fault tolerance strategy. This would need to have many considerations, including asynchronously calling your web service, number of retry attempts, etc. I would suggest doing a search for web service fault tolerance.
What you have is correct; see the MSDN example:
public class ThrowTestB
{
static void Main()
{
try
{
// TryCast produces an unhandled exception.
TryCast();
}
catch (Exception ex)
{
// Catch the exception that is unhandled in TryCast.
Console.WriteLine
("Catching the {0} exception triggers the finally block.",
ex.GetType());
// Restore the original unhandled exception. You might not
// know what exception to expect, or how to handle it, so pass
// it on.
throw;
}
}
public static void TryCast()
{
int i = 123;
string s = "Some string";
object obj = s;
try
{
// Invalid conversion; obj contains a string, not a numeric type.
i = (int)obj;
// The following statement is not run.
Console.WriteLine("WriteLine at the end of the try block.");
}
finally
{
// Report that the finally block is run, and show that the value of
// i has not been changed.
Console.WriteLine("\nIn the finally block in TryCast, i = {0}.\n", i);
}
}
// Output:
// In the finally block in TryCast, i = 123.
// Catching the System.InvalidCastException exception triggers the finally block.
// Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
}
As a rule of thumb I try and build code that focuses try catches to the exact spot the problem may occur.
That said both of your solutions are correct.
If it were my code I would do this
public void MainFunction()
{
try
{
SomeProblemFunction();
}
catch(Exception e)
{
Messagebox.Show(e.Message);
}
}
private void SomeProblemFunction() {
try{
web call
}
catch{
throw a specific exception related to this spot
}
}
private void AllFineFunction() { ... }
With this method you can easily create applications that handle a slew of very accurate exceptions
A fine question, I think. I'll attempt an answer.
If you want to recover within SomeProblemFunction, then it would make perfect sense to move the try...catch inside of that method. If, however, you are comfortable saying that if anything fails in SomeProblemFunction, then the whole thing is a failure, then keep it as you have it now and recover in (or throw from) MainFunction.
Thanks to the comment below, I'm adding some clarity. Depending on the specific exception that is being thrown within SomeProblemFunction, you may not have the ability to recover within that method. If you have a mixture of recoverable and non-recoverable, then it would be prudent to have the try...catch in both places.
The most important thing is that you NEVER catch an exception from which you cannot recover without throwing it on after doing your thing. It's tempting to add big broad catches (catch (Exception)) to avoid your app crashing during development, but it is never worth it. If those things make it into your production code, you've introduced a problem-solving and debugging nightmare.
In my opinion, there is no straight answer for this. The try catch is used to handle the exceptions that may occur. If your exception handling code is going in the main function then you should have the try catch in the main function. If your exception handling code in the problem function then you should add it to the problem function.
My preference though is to put it in both functions. If you put the try catch in the problem function, you can throw the exception and catch it in the main function. This always appear to other developers that the exception was thought of in that function and not missed handling it by mistake.
This depends on how severe this web service call failure would be.
Is it a failure that would prevent further processing of your code to run? If so, have no try/catch here, allowing it to propagate up to the guy who needs to know that this web service call failed. Optionally, you could still catch and throw a new exception with some more meaningful Exception type/ details.
Do you simply just want to re-try the web service call again if it doesn't work? IF so, then you have the try in the correct place; you just need to add a loop.
Is it not a big deal if this web service call fails? e.g. - will the rest of your code work OK? (I've found this to be uncommon). If so, leave the try/catch where it is, and log the error somewhere so that you're alerted.