I'm working on a project using the ANTLR parser library for C#. I've built a grammar to parse some text and it works well. However, when the parser comes across an illegal or unexpected token, it throws one of many exceptions. The problem is that in some cases (not all) that my try/catch block won't catch it and instead stops execution as an unhandled exception.
The issue for me is that I can't replicate this issue anywhere else but in my full code. The call stack shows that the exception definitely occurs within my try/catch(Exception) block. The only thing I can think of is that there are a few ANTLR assembly calls that occur between my code and the code throwing the exception and this library does not have debugging enabled, so I can't step through it. I wonder if non-debuggable assemblies inhibit exception bubbling? The call stack looks like this; external assembly calls are in Antlr.Runtime:
Expl.Itinerary.dll!TimeDefLexer.mTokens() Line 1213 C#
Antlr3.Runtime.dll!Antlr.Runtime.Lexer.NextToken() + 0xfc bytes
Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.FillBuffer() + 0x22c bytes
Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.LT(int k = 1) + 0x68 bytes
Expl.Itinerary.dll!TimeDefParser.prog() Line 109 + 0x17 bytes C#
Expl.Itinerary.dll!Expl.Itinerary.TDLParser.Parse(string Text = "", Expl.Itinerary.IItinerary Itinerary = {Expl.Itinerary.MemoryItinerary}) Line 17 + 0xa bytes C#
The code snippet from the bottom-most call in Parse() looks like:
try {
// Execution stopped at parser.prog()
TimeDefParser.prog_return prog_ret = parser.prog();
return prog_ret == null ? null : prog_ret.value;
}
catch (Exception ex) {
throw new ParserException(ex.Message, ex);
}
To me, a catch (Exception) clause should've captured any exception whatsoever. Is there any reason why it wouldn't?
Update: I traced through the external assembly with Reflector and found no evidence of threading whatsoever. The assembly seems to just be a runtime utility class for ANTLR's generated code. The exception thrown is from the TimeDefLexer.mTokens() method and its type is NoViableAltException, which derives from RecognitionException -> Exception. This exception is thrown when the lexer cannot understand the next token in the stream; in other words, invalid input. This exception is SUPPOSED to happen, however it should've been caught by my try/catch block.
Also, the rethrowing of ParserException is really irrelevant to this situation. That is a layer of abstraction that takes any exception during parse and convert to my own ParserException. The exception handling problem I'm experiencing is never reaching that line of code. In fact, I commented out the "throw new ParserException" portion and still received the same result.
One more thing, I modified the original try/catch block in question to instead catch NoViableAltException, eliminating any inheritance confusion. I still received the same result.
Someone once suggested that sometimes VS is overactive on catching handled exceptions when in debug mode, but this issue also happens in release mode.
Man, I'm still stumped! I hadn't mentioned it before, but I'm running VS 2008 and all my code is 3.5. The external assembly is 2.0. Also, some of my code subclasses a class in the 2.0 assembly. Could a version mismatch cause this issue?
Update 2: I was able to eliminate the .NET version conflict by porting relevant portions of my .NET 3.5 code to a .NET 2.0 project and replicate the same scenario. I was able to replicate the same unhandled exception when running consistently in .NET 2.0.
I learned that ANTLR has recently released 3.1. So, I upgraded from 3.0.1 and retried. It turns out the generated code is a little refactored, but the same unhandled exception occurs in my test cases.
Update 3:
I've replicated this scenario in a simplified VS 2008 project. Feel free to download and inspect the project for yourself. I've applied all the great suggestions, but have not been able to overcome this obstacle yet.
If you can find a workaround, please do share your findings. Thanks again!
Thank you, but VS 2008 automatically breaks on unhandled exceptions. Also, I don't have a Debug->Exceptions dialog. The NoViableAltException that is thrown is fully intended, and designed to be caught by user code. Since it is not caught as expected, program execution halts unexpectedly as an unhandled exception.
The exception thrown is derived from Exception and there is no multi-threading going on with ANTLR.
I believe I understand the problem. The exception is being caught, the issue is confusion over the debugger's behavior and differences in the debugger settings among each person trying to repro it.
In the 3rd case from your repro I believe you are getting the following message: "NoViableAltException was unhandled by user code" and a callstack that looks like this:
[External Code]
> TestAntlr-3.1.exe!TimeDefLexer.mTokens() Line 852 + 0xe bytes C#
[External Code]
TestAntlr-3.1.exe!TimeDefParser.prog() Line 141 + 0x14 bytes C#
TestAntlr-3.1.exe!TestAntlr_3._1.Program.ParseTest(string Text = "foobar;") Line 49 + 0x9 bytes C#
TestAntlr-3.1.exe!TestAntlr_3._1.Program.Main(string[] args = {string[0x00000000]}) Line 30 + 0xb bytes C#
[External Code]
If you right click in the callstack window and run turn on show external code you see this:
Antlr3.Runtime.dll!Antlr.Runtime.DFA.NoViableAlt(int s = 0x00000000, Antlr.Runtime.IIntStream input = {Antlr.Runtime.ANTLRStringStream}) + 0x80 bytes
Antlr3.Runtime.dll!Antlr.Runtime.DFA.Predict(Antlr.Runtime.IIntStream input = {Antlr.Runtime.ANTLRStringStream}) + 0x21e bytes
> TestAntlr-3.1.exe!TimeDefLexer.mTokens() Line 852 + 0xe bytes C#
Antlr3.Runtime.dll!Antlr.Runtime.Lexer.NextToken() + 0xc4 bytes
Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.FillBuffer() + 0x147 bytes
Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.LT(int k = 0x00000001) + 0x2d bytes
TestAntlr-3.1.exe!TimeDefParser.prog() Line 141 + 0x14 bytes C#
TestAntlr-3.1.exe!TestAntlr_3._1.Program.ParseTest(string Text = "foobar;") Line 49 + 0x9 bytes C#
TestAntlr-3.1.exe!TestAntlr_3._1.Program.Main(string[] args = {string[0x00000000]}) Line 30 + 0xb bytes C#
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x39 bytes
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2b bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x3b bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x81 bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x40 bytes
The debugger's message is telling you that an exception originating outside your code (from NoViableAlt) is going through code you own in TestAntlr-3.1.exe!TimeDefLexer.mTokens() without being handled.
The wording is confusing, but it does not mean the exception is uncaught. The debugger is letting you know that code you own mTokens()" needs to be robust against this exception being thrown through it.
Things to play with to see how this looks for those who didn't repro the problem:
Go to Tools/Options/Debugging and
turn off "Enable Just My code
(Managed only)". or option.
Go to Debugger/Exceptions and turn off "User-unhandled" for
Common-Language Runtime Exceptions.
I can tell you what's happening here...
Visual Studio is breaking because it thinks the exception is unhandled. What does unhandled mean? Well, in Visual Studio, there is a setting in the Tools... Options... Debugging... General... "Enable Just My Code (Managed only)". If this is checked and if the exception propagates out of your code and out to a stack frame associated with a method call that exists in an assembly which is "NOT YOUR CODE" (for example, Antlr), that is considered "unhandled". I turn off that Enable Just My Code feature for this reason. But, if you ask me, this is lame... let's say you do this:
ExternalClassNotMyCode c = new ExternalClassNotMyCode();
try {
c.doSomething( () => { throw new Exception(); } );
}
catch ( Exception ex ) {}
doSomething calls your anonymous function there and that function throws an exception...
Note that this is an "unhandled exception" according to Visual Studio if "Enable Just My Code" is on. Also, note that it stops as if it were a breakpoint when in debug mode, but in a non-debugging or production environment, the code is perfectly valid and works as expected. Also, if you just "continue" in the debugger, the app goes on it's merry way (it doesn't stop the thread). It is considered "unhandled" because the exception propagates through a stack frame that is NOT in your code (i.e. in the external library). If you ask me, this is lousy. Please change this default behavior Microsoft. This is a perfectly valid case of using Exceptions to control program logic. Sometimes, you can't change the third party library to behave any other way, and this is a very useful way to accomplish many tasks.
Take MyBatis for example, you can use this technique to stop processing records that are being collected by a call to SqlMapper.QueryWithRowDelegate.
Regardless of whether the assembly has been compiled as a release build the exception should certainly 'bubble' up to the caller, there's no reason an assembly not being compiled in debug mode should have any affect on that.
I'd agree with Daniel is suggesting that perhaps the exception is occurring on a separate thread - try hooking the thread exception event in Application.ThreadException. This should be raised when any unhandled thread exception occurs. You could adapt your code thus:-
using System.Threading;
...
void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
throw new ParserException(e.Exception.Message, e.Exception);
}
...
var exceptionHandler =
new ThreadExceptionEventHandler(Application_ThreadException);
Application.ThreadException += exceptionHandler;
try {
// Execution stopped at parser.prog()
TimeDefParser.prog_return prog_ret = parser.prog();
return prog_ret == null ? null : prog_ret.value;
}
catch (Exception ex) {
throw new ParserException(ex.Message, ex);
}
finally {
Application.ThreadException -= exceptionHandler;
}
Are you using .Net 1.0 or 1.1? If so then catch(Exception ex) won't catch exceptions from unmanaged code. You'll need to use catch {} instead. See this article for further details:
http://www.netfxharmonics.com/2005/10/net-20-trycatch-and-trycatchexception/
I'm with #Shaun Austin - try wrapping the try with the fully qualified name
catch (System.Exception)
and see if that helps.Does the ANTLR doc say what Exceptions should be thrown?
Is it possible that the exception is being thrown in another thread? Obviously your calling code is single threaded, but maybe the library you are consuming is doing some multithreaded operations under the covers.
To me, a catch (Exception) clause should've captured any exception whatsoever. Is there any reason why it wouldn't?
The only possibility I can think of is that something else is catching it before you and handling it in a way that appears to be an uncaught exception (e.g. exiting the process).
my try/catch block won't catch it and instead stops execution as an unhandled exception.
You need to find what is causing the exit process. It might be something other than an unhandled exception.
You might try using the native debugger with a breakpoint set on "{,,kernel32.dll}ExitProcess". Then use SOS to determine what managed code is calling exit process.
Personally I'm not convinced by the threading theory at all.
The one time I've seen this before, I was working with a library which also defined Exception and the usings I had meant that the actual Catch was referring to a different "Exception" type (if it had been fully qualified it was Company.Lib.Exception but it wasnt because of the using) so when it came to catching a normal exception that was being thrown (some kind of argument exception if I remember correctly) it just wouldn't catch it because the type didn't match.
So in summary, is there another Exception type in a different namespace that is in a using in that class?
EDIT: A quick way to check this is make sure in your catch clause you fully qualify the Exception type as "System.Exception" and give it a whirl!
EDIT2: OK I've tried the code and concede defeat for now. I'll have to have another look at it in the morning if no one has come up with a solution.
Hmm, I don't understand the problem. I downloaded and tried your example solution file.
An exception is thrown in TimeDefLexer.cs, line 852, which is subsequently handled by the catch block in Program.cs that just says Handled exception.
If I uncomment the catch block above it, it will enter that block instead.
What seems to be the problem here?
As Kibbee said, Visual Studio will stop on exceptions, but if you ask it to continue, the exception will get caught by your code.
I downloaded the sample VS2008 project, and am a bit stumped here too. I was able to get past the exceptions however, although probably not in a way that will work will great for you. But here's what I found:
This mailing list post had a discussion of what looks to be the same issue you are experiencing.
From there, I added a couple dummy classes in the main program.cs file:
class MyNoViableAltException : Exception
{
public MyNoViableAltException()
{
}
public MyNoViableAltException(string grammarDecisionDescription, int decisionNumber, int stateNumber, Antlr.Runtime.IIntStream input)
{
}
}
class MyEarlyExitException : Exception
{
public MyEarlyExitException()
{
}
public MyEarlyExitException(int decisionNumber, Antlr.Runtime.IIntStream input)
{
}
}
and then added the using lines into TimeDefParser.cs and TimeDefLexer.cs:
using NoViableAltException = MyNoViableAltException;
using EarlyExitException = NoViableAltException;
With that the exceptions would bubble into the fake exception classes and could be handled there, but there was still an exception being thrown in the mTokens method in TimeDefLexer.cs. Wrapping that in a try catch in that class caught the exception:
try
{
alt4 = dfa4.Predict(input);
}
catch
{
}
I really don't get why wrapping it in the internal method rather than where it is being called from handle the error if threading isn't in play, but anyways hopefully that will point someone smarter than me here in the right direction.
I downloaded your code and everything work as expected.
Visual Studio debugger correctly intercepts all exceptions. Catch blocks work as expected.
I'm running Windows 2003 server SP2, VS2008 Team Suite (9.0.30729.1 SP)
I tried to compile you project for .NET 2.0, 3.0 & 3.5
#Steve Steiner, debugger options you mentioned have nothing to do with this behavior.
I tried to play with these options with no visible effects - catch blocks managed to intercept all exceptions.
Steve Steiner is correct that the exception is originating in the antlr library, passing through the mTokens() method and being caught in the antlr library. The problem is that this method is auto-generated by antlr. Therefore, any changes to handle the exception in mTokens() will be overwritten when your generate your parser/lexer classes.
By default, antlr will log errors and try to recover parsing. You can override this so that the parser.prog() will throw an exception whenever an error is encountered. From your example code i think this is the behaviour you were expecting.
Add this code to your grammer (.g) file. You will also need to turn off "Enable Just My Code" in the debugging menu.
#members {
public override Object RecoverFromMismatchedSet(IIntStream input,RecognitionException e, BitSet follow)
{
throw e;
}
}
#rulecatch {
catch (RecognitionException e)
{
throw e;
}
}
This is my attempt at a C# version of the example given in the "Exiting the recogniser on first error" chapter of the "Definitive ANTLR Reference" book.
Hope this is what you were looking for.
You can set up VS.Net to break as soon as any exception occurs. Just run your project in debug mode, and it will stop as soon as the exception is thrown. Then you should have a better idea of why it isn't being caught.
Also, you can put some code in to catch all unhandled exceptions.
Application.ThreadException += new ThreadExceptionEventHandler(ThreadExceptionHandler);
// Catch all unhandled exceptions in all threads.
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler);
Oh and in reference to what Kibbee said; if you select Debug|Exceptions in VS and just click all the boxes in the 'thrown' column it should pick everything up AFAIK as a 'first chance exception', i.e. VS will indicate when the exception is about to be processed by everything else and break on the relevant code. This should help with debugging.
The best option sounds like setting Visual Studio to break on all unhandled exceptions (Debug -> Exceptions dialog, check the box for "Common Language Runtime Exceptions" and possibly the others as well). Then run your program in debug mode. When the ANTLR parser code throws an exception it should be caught by Visual Studio and allow you to see where it is occurring, the exception type, etc.
Based on the description, the catch block appears to be correct, so one of several things could be happening:
the parser is not actually throwing an exception
the parser is ultimately throwing something that isn't deriving from System.Exception
there is an exception being thrown on another thread that isn't being handled
It sounds like you have potentially ruled out issue #3.
I traced through the external assembly with Reflector and found no evidence of threading whatsoever.
You can't find any threading does not mean there is no threading
.NET has a 'thread pool' which is a set of 'spare' threads that sit around mostly idle. Certain methods cause things to run in one of the thread pool threads so they don't block your main app.
The blatant examples are things like ThreadPool.QueueUserWorkItem, but there are lots and lots of other things which can also run things in the thread pool that don't look so obvious, like Delegate.BeginInvoke
Really, you need to do what kibbee suggests.
have you tried to print (Console.WriteLine()) the exception inside the catch clause, and not use visual studio and run your application on console?
I believe Steve Steiner is correct. When researching Steve's suggestions, I came across this thread talking about the "Enable Just My Code" option in Tools|Options|Debugger|General. It is suggested that the debugger will break in certain conditions when non-user code either throws or handles an exception. I'm not exactly sure why this even matters, or why the debugger specifically says the exception was unhandled when it really was.
I was able to eliminate the false breaks by disabling the "Enable Just My Code" option. This also changes the Debug|Exceptions dialog by removing the "User-handled" column as it no longer applies. Or, you can just uncheck the "User-handled" box for CLR and get the same result.
Bigtime thanks for the help everyone!
"Also, you can put some code in to
catch all unhandled exceptions. Read
the link for more info, but the basics
are these two lines."
This is false. This used to catch all unhandled exceptions in .NET 1.0/1.1 but it was a bug and it wasn't supposed to and it was fixed in .NET 2.0.
AppDomain.CurrentDomain.UnhandledException
Is only intended to be used as a last chance logging saloon so you can log the exception before the program exits. It wont catch the exception as of 2.0 onwards (although in .NET 2.0 at least there is a config value you can modify to make it act like 1.1 but it isn't recommended practice to use this.).
Its worth noting that there are few exceptions that you cannot catch, such as StackOverflowException and OutOfMemoryException. Otherwise as other people have suggested it might be an exception in a background thread somewhere. Also I'm pretty sure you can't catch some/all unmanaged/native exceptions either.
I don't get it...your catch block just throws a new exception (with the same message). Meaning that your statement of:
The problem is that in some cases (not all) that my try/catch block won't catch it and instead stops execution as an unhandled exception.
is exactly what is expected to happen.
I agree with Daniel Auger and kronoz that this smells like an exception that has something to do with threads. Beyond that, here are my other questions:
What does the complete error message say? What kind of exception is it?
Based on the stack trace you've provided here, isn't the exception thrown by you code in TimeDefLexer.mTokens()?
I'm not sure if I'm being unclear, but if so, I'm seeing the debugger halt execution with an "Unhandled Exception" of type NoViableAltException. Initially, I didn't know anything about this Debug->Exceptions menu item because MS expects you, at VS install time, to commit to a profile when you have no idea how they are different. Apparently, I was not on the C# dev profile and was missing this option. After finally debugging all thrown CLR exceptions, I was unfortunately unable to discover any new behavior leading to the reason for this unhandled exception issue. All the exceptions thrown were expected and supposedly handled in a try/catch block.
I reviewed the external assembly and there is no evidence of multithreading. By that, I mean no reference exists to System.Threading and no delegates were used whatsoever. I'm familiar with that constitutes instantiating a thread. I verify this by observing the Threads toolbox at the time of the unhandled exception to view there is only one running thread.
I have an open issue with the ANTLR folks so perhaps they've been able to tackle this issue before. I've been able to replicate it in a simple console app project using .NET 2.0 and 3.5 under VS 2008 and VS 2005.
It's just a pain point because it forces my code to only work with known valid parser input. Using an IsValid() method would be risky if it threw an unhandled exception based on user input. I'll keep this question up to date when more is learned of this issue.
#spoulson,
If you can replicate it, can you post it somewhere? One avenue you could try is usign WinDBG with the SOS extensions to run the app and catch the unhandled exception. It will break on the first chance exception (before the runtime tries to find a handler) and you can see at that point where it is coming from, and what thread.
If you haven't used WinDBG before, it can be a little overwhelming, but here's a good tutorial:
http://blogs.msdn.com/johan/archive/2007/11/13/getting-started-with-windbg-part-i.aspx
Once you start up WinDBG, you can toggle the breaking of unhandled exceptions by going to Debug->Event Filters.
Wow, so of the reports so far, 2 worked correctly, and 1 experienced the issue I reported. What are the versions of Windows, Visual Studio used and .NET framework with build numbers?
I'm running XP SP2, VS 2008 Team Suite (9.0.30729.1 SP), C# 2008 (91899-270-92311015-60837), and .NET 3.5 SP1.
If you are using com objects your project and try catch blocks not catch the exceptions you will be need disable Tools/Debugging/Break when exceptions cross AppDomain or managed/native boundaries(Managed only) option.
Related
NOTE ADDED AFTER SOLUTION: An AccessViolationException was being thrown inside the method called by reflection. This was the reason the TargetInvocationException couldn't be caught.
NOTE: This is OUTSIDE of the IDE. The referenced question is NOT the same.
TL;DR
Can't get a stack trace
Can't get inner exceptions
Can't use debugger (copy protection scheme of a third party library gets in the way)
Any changes to the code prevent the exception from occurring - means I can't add logging to find out where the exception occurrs
How can I get the exception to be caught or get the needed information some other way?
Long description:
I am having a problem with an exception that occurs in a method that gets called by reflection. The exception itself actually occurs in the called method, but since the method is called by reflection, the real exception gets wrapped in a System.Reflection.TargetInvocationException. No problem, just catch it and get the internal exception - except the System.Reflection.TargetInvocationException doesn't get caught. My program crashes, and I get a dump along with an entry in the Windows event log.
The Windows event log doesn't contain the internal exceptions, and neither does the dump.
I can't attach a debugger to the program because then an external library (which is needed to get to the reflection call) won't run - copy protection, don't you know.
If I put a try/catch into the offending method, the exception doesn't occur - which is bad. The cause isn't fixed, it just doesn't happen any more.
The same effect happens if I put logging into the offending method - the exception doesn't occur any more.
I can't use logging, I can't use a debugger, and in the one place where I could catch the exception and log it the exception doesn't get caught.
I'm using Visual Studio 2010 and dotnet 4.0.
To make it clear: The try/catch doesn't work when the program is run outside of Visual Studio, and I can't run it inside of Visual Studio in the debugger because then the program can't reach the point where the exception occurs. This is NOT within the IDE.
Eliminating the reflection isn't an option (I've tried it for just the one case, and the exception goes away.)
The method being called does a lot of stuff, but breaking it down into smaller methods doesn't help - the exception just goes away.
The exception doesn't occur all the time, only when I do a certain sequence of steps - and when it occurs then it is always on the second time through the whole sequence.
In the sequence I am using, the method gets called by two threads almost simultaneously - a particular bunch of data gets entered, which causes a copy of a report and another document to be printed on two separate printers - one report and document to each printer. Since generating the reports and printing the document can take a while, they are done on threads in the background so the user can continue working.
I suspect that the threads are stepping on each others toes (lots of file and database manipulations going on) but without knowing what is really happening I can't fix it.
The code below shows a simplified version of the call by reflection.
Does any one have a suggestion as to what may be causing the System.Reflection.TargetInvocationException to not be caught, or maybe an alternative way to catch the inner exception?
Try
Dim methode As System.Reflection.MethodInfo
methode = GetType(AParticularClass).GetMethod("OneOfManyMethods", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static)
Dim resultobject As Object = methode.Invoke(Nothing, Reflection.BindingFlags.InvokeMethod Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static, Nothing, New Object() {SomeBooleanVariable, SomeStringVariable}, Nothing)
result = DirectCast(resultobject, DataSet)
Catch ex As Exception
'Log the error here.
End Try
Found the reason why I couldn't catch the exception:
The actual exception was an AccessViolationException, which can't be caught in dotnet 4.0 without taking special steps (How to handle AccessViolationException.)
To make things more fun, when AccessViolationException gets thrown in a method called by reflection, only a TargetInvocationException gets logged in the Windows event log, and only the TargetInvocationException is available in the dump.
Once I managed to get the real exception, I found that that it was a call to Application.DoEvents() from a non-GUI thread that caused the AccessViolation. DoEvents() can cause enough fun when called on the GUI-Thread (Use of Application.DoEvents()), let alone when called from a background thread.
Once that was fixed, I found that our third party library (the one with the copy protection) doesn't like being called simultaneously in separate instances. Fixing that was a matter of a synclock in the right place.
The code causing all of this fun was at one time all in the GUI-Thread, and was originally written back in the days of dotnet 1.1 - this explains the call to DoEvents. The code has been converted piece-wise to run in parallel in background threads through several different stages, with no one single developer having a complete overview of the process.
I am not sure I can replicate your issue, but this is how we get it and it work's just fine...
Try
'YOUR CODE'
Catch ex As Exception
'This is where we grab it from... It needs to be in this block to work...
System.Reflection.MethodInfo.GetCurrentMethod.ToString
End Try
Let me know how it work's out for you?
I have a simple try-catch-finally code block that works as expected in .NET3.5, but the same code behaves completely different on a project created with .NET4.5.1. Basically, in .NET4.5.1 the "finally" block doesn't get hit if an exception occurs which is not the behavior I expected from the try-catch-finally block. I tried in different machines, and had 2 other colleagues of mine also trying and we all got the same result. This is a concern for me, because I use the finally block to close DataReaders, certain connections, and whatnot.
.NET4.5.1 does not hit the "finally" block if an exception is thrown in RELEASE mode without debugger or when running the RELEASE compiled EXE file. In debug mode both .NET versions hit the "finally" block.
Again, the code below behaves as expected in .NET3.5 RELEASE mode without debugger but not in .NET4.5.1. Am I missing something? Can someone help?
class Program
{
static void Main(string[] args)
{
try
{
string a = null;
var x = a.Length;
Console.WriteLine(x);
}
catch (Exception ex)
{
throw;
}
finally
{
Console.WriteLine("This is the finally block.");
}
Console.WriteLine("You should not be here if an exception occured!");
}
}
the code below behaves as expected in .NET3.5 RELEASE mode without debugger but not in .NET4.5.1. Am I missing something?
NOTE: I had overstated the level of undefined-ness of this behaviour; thanks to commenter Voo for pointing that out. I should have gone back to the spec in the first place.
Yes. The CLR is required by the CLI specification to end the program when there is an unhandled exception. It is only required to run finally blocks if the exception is handled. The spec is vague on the question of whether the CLR is required, permitted, or disallowed to execute finally blocks when there is an unhandled exception; the safe assumption is then to say that this is behaviour that is undefined by the specification, and that is up to a particular implementation.
The CLR can choose to run finally blocks for unhandled exceptions, or not, at its whim. Many people believe that the CLR uses this algorithm: upon exception, walk up the call stack, executing finally blocks as you go, looking for handlers; if no handler is found, terminate the process. The CLR is not required to conform to this algorithm in a program with an unhandled exception. In particular, the CLR is permitted to determine by black magic that there is no exception handler, and never run any finally blocks. Whether it chooses to do so or not in some versions of the CLR in some circumstances, I don't know. In no case can you rely on that behavior for the correctness of your program because a program that has an unhandled exception is not correct.
The specification also notes that the CLR can choose to offer to start debuggers or not, at its whim. The CLR is not required to do the same thing in debug or release, and it is not required to do the same thing from version to version.
The problem here is that you formed an expectation based on past experience, but there is no documentation which says that past experience is a basis for a prediction of the future. Rather, just the opposite; the CLR is permitted to change its behavior on the basis of the phase of the moon if it likes, in a program that has an unhandled exception.
If you want your program to behave predictably then do not throw unhandled exceptions.
So if I understand you correctly, as long as there is another catch somewhere upstream, the finally block will execute?
No, I didn't say that. Let's break it down.
If there is an uncaught exception in the program then the program's behavior is implementation-defined. Whatever behavior you get, that's the behavior you got, and the CLR is within its rights to produce that behavior. That includes both running finally blocks and not running finally blocks.
Suppose there is not an uncaught exception, and an exception is thrown, and there is a finally block along the way to the catch. Is it guaranteed that the finally block will execute? No. There are many things that could prevent that finally block from executing in a legal program. For example, another finally block or exception filter along the way could go into an infinite loop or fast fail, either of which would prevent the finally block from executing. If you ABSOLUTELY POSITIVELY must have some cleanup code run then you need to be researching Constrained Execution Regions. (I don't know how they work; I've never had need to learn. I hear they are tricky.).
What is guaranteed is that if control leaves a finally-protected block then the finally code will run. Code run during exception filters does not count as leaving the block, and failing fast does not cause program control to exit a block, it causes program control to end abruptly. Obviously infinite loops cause control to never exit a block.
I suppose in the case of a truly unhandled exception, the program should terminate anyways so an orphaned DB connection/transaction shouldn't be an issue?
Whether it is an issue or not, I cannot say. Ask the author of your database.
It is very likely that the program will terminate, though again I note that the CLR is not required to have that behavior. Suppose for example there is some thread that keeps on running while the CLR is trying to figure out whether you have a debugger installed or not. The CLR is within its rights to take arbitrarily long to figure that out, and therefore within its rights to keep that thread running. Whether it does or not, I don't know. What I do know is that I would not want to rely on either behavior.
Also, does using the 'AppDomain.CurrentDomain.UnhandledException event count as 'handling'
Nope. If that thing runs then there was an unhandled exception, and the behavior of the program is implementation-defined. That event handler should be used only to do things like log the fact that the program has a bug.
On top of what Lipper wrote, note that it is written in MSDN... Under the try...finally:
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.
and
Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important.
and then it goes on to explain that if you put a try... catch at a "high" level then the inner try... finally will be executed.
Prior to Framework 4.0 unhandled exceptions launched 'Microsoft .NET Error Reporting Shim', which shows the dialog offering to 'Debug' or 'Close program'. The shim allows .NET applications to close "cleanly".
Starting with Framework 4.0 (as far as I can tell) unhandled exceptions result in Windows launching Windows Error Reporting (WER) which shows-up as Windows Problem Reporting in Task Manager. This application shows a similar dialog to the shim but takes a more hardline approach to killing the application, probably calling TerminateProcess or TerminateThread which would not allow any further code to execute in the misbehaving process.
I am developing a library that will be used by programmers.
When I am throwing an exception, the debugger goes to where the exception was thrown, and not where the class was instantiated or the method was executed.
With a try .. catch this can be solved, but what if the programmer who is using the library does not open a try .. catch? he will see all my code!
How can I avoid this?
he will see all my code!
Well yes, if you distribute your code. If you don't, how would you expect the code to be seen? Don't forget that you're in a different situation to most developers using your library, as you have the source code on your machine. Try the same DLL on a machine which doesn't have the source code.
The developer may see a decompiled version of your code, perhaps - is that such a great problem? If so, you should look at obfuscating your code - but be aware that that comes with some logistical downsides too.
I suspect this really just isn't a problem.
Well, if you make a release version of your library and you don't provide debugger symbols (pdb) the debugger of the libraries user shouldn't show your code.
OTOH, do you know tools like reflector? Your code isn't really a secret.
If I understand what you are looking for I think you want to use a try catch in your code and instead of a catch block where you handle the exception you want to rethrow it like this:
try
{
//exception code
}
catch (Exception e)
{
throw e;
}
If I remember correctly, throwing like this will reset the stack trace whereas just a throw will keep the stack trace in tact.
I have some framework / AOP code that logs exceptions from methods called deeper inside...
try {
..invoke inner code...
}
catch (Exception e) {
log(e);
throw;
}
This works great except for one thing...when my team tries to debug their code in Studio, they only see the exception happening in the logging code (since it gets handled, and then thrown from there).
Is there any way I can get Studio to ignore that my code is catching/throwing an exception...or to inspect the exception on it's way through without catching it?
UPDATE:
The issue is that I have framework code that prevents the correct break-point for the real exception from being hit. I am aware that the debugger in visual studio is capable of fine-grained configuration, and I am hoping that someone here can provide a higher level insight than "Learn VS2010 in 31 Hours" does. I simply want to BOTH log the exceptions that are caused in inner code, AND have the break happen at the site of the error WITHOUT turning on 'Break on All Exceptions' which would cause my team to spend 5 minutes pressing the 'Continue' button every time they launched the app (but that's another story).
UPDATE 2:
The primary question here, is how can I log the exception, but have the debugger not stop on the 'throw' in my logger, but on the initial exception, without having the debugger stop on all exceptions thrown.
Actually you can make VS break on exceptions. Go to the Debug menu, click exceptions and check both the checkboxes for "Common Language Runtime Exceptions". Now you'll get a debug break at the point the exception is thrown.
I've done some digging, and the answer in 1349613 put me on a good scent. I've added the attribute:
[DebuggerNonUserCode]
To my logging class. Now when the internal, invoked code throws an exception, the debugger ignores the logging code, and it's Try/Catch block, and goes straight to the internal exception.
It is possible in VB.NET to examine an exception without catching it, and before any stack unwinding has occurred as a consequence of it. While it is generally dangerous to do very much between the time the exception has been thrown and the time the stack has been unwound, one may capture the exception and then make use of it in a finally block. One might also set a flag or other indicator to let stack-unwinding code know where the exception is going to be caught. Unfortunately, the usefulness of the latter ability is limited because of a (largely language-forced) anti-pattern of code catching exceptions that it needs to react to, but that can't expect to resolve. For example, if an exception is thrown in a constructor after it has created some IDisposable objects and stored them in fields, the constructor has to react to the exception by cleaning up the fields it has created, but has no hope of resolving the situation and returning normally. If a constructor might have multiple return points, it would be semantically cleaner of one could say:
try
{
... create IDisposables
}
finally(Exception ex)
{
if (ex != null)
this.Dispose();
}
than having to say
try
{
... create IDisposables
}
catch(Exception ex)
{
this.Dispose();
throw ex;
}
since the former would avoid catching an exception it had no expectation of handling. One could write a wrapper method in VB that would accept a pair of delegates and implement the second using the same semantics as the finally(Exception ex) above would have, but unfortunately C# provides no such facility itself.
I have a application with similar code (not written by me)
try
{
EnumerateSomeCoolHardwareDevice();
}
catch (Exception ex)
{
}
UPDATE - This is .NET C# & EnumerateSomeCoolHardwareDevice() is using SerialPort?
I know how bad this code is but it works like this for a reason!
My question thou: I can see that it crashes somewhere in the EnumerateSomeCoolHardwareDevice(); but it doesn't get caught by the Catch (...) - It just crashes with the send report dialog! This also currently only happen in the release build... Is their ANY reason why my exception will NOT be caught by the catch (...)?
My guess is that you're not getting an Exception in your language/framework but rather EnumerateSomeCoolHardwareDevice() does weird things that simply cause the OS to kill your process. Remember that hardware details are abstracted by frameworks like Java and .NET, so whenever you do something with hardware directly, you're probably relying on unmanaged resources ... and whatever goes wrong there can kill you, catch or not.
One possible reason would be if the EnumerateSomeCoolHardwareDevice() function uses threading. If an exception is thrown in a thread and isn't handled within it's thread then it can crash an application. This simple app can demonstrate what I mean:
public static void testThread()
{
throw new Exception("oh god it's broken");
}
static void Main(string[] args)
{
try
{
Thread thread = new Thread(testThread);
thread.Start();
Console.ReadKey(); //Just to make sure we don't get out of the try-catch too soon
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
If you run that the app will crash and burn rather than catching the exception as you might expect.
In .NET catch (Exception ex) will only catch .NET exceptions, not native exceptions.
This question (catching native exceptions in C#) may help.
Assuming .NET, if EnumerateSomeCoolHardwareDevice uses Win32 methods via PInvoke (to access the hardware) and an error occurs, most Native methods return an error code. If that error code is not handled, and another native method is called anyway (perhaps with empty out parameters from the failed call), a serious native error (such as bad memory access or something similar) can cause a straight program crash, no exception thrown.
Have you tried the attribute
assembly:RuntimeCompatibility(WrapNonExceptionThrows = true)
That should wrap any non-.Net exceptions into System.Exception so it will be catched in your code.
If it is only happening on the production machine and not the dev machines then it could be down to DLL mismatches. Double check ALL the referenced DLLs and frameworks are the same version.
Secondly if the error is not being thrown by the EnumerateSomeCoolHardwareDevice() then it will crash the app as there is no way for the exception to get back up the stack (or thats my understanding of try/catches) in my experience this has happened to me before.
Lastly, the microsoft error report usually allows you to inspect what will be sent to MS, this should let you see where the error happened and why (assuming it has readable information within it).
Check the Event Viewer as the error should also be logged there, and normally provides an invaluable source of detail regarding the error and with a bit of digging through the error listed there you should be able to trace the fault.
If you are in .Net version 1.1 use a no parameters catch block like
catch{
...
}
Prior to .Net 2.0 there could be native exceptions that do not derive from System.Exception.
Also hook to appdomain unhandled exception event and see what happens.
There may be a try..catch inside EnumerateSomeCoolHardwareDevice().
If the exception is caught and handled there, the outer exception won't be hit unless the Exception is thrown again.
(Assuming Java) Both Error and Exception are subclasses of Throwable. If there is an assertion failing in EnumerateSomeCoolHardwareDevice() for example you will get an Error.
My guess is that there's a stack overflow happening. The .NET VM simply shuts down Release build processes that encounter a stack overflow, no CLR exceptions thrown. There's probably an internal try / catch inside that function that catches StackOverflowException one way or other, that's why it's not propagating to your code in Debug builds either.
The easiest way to figure out what's going on is by making a debug build, attaching a debugger and instructing the debugger to break before any exceptions are thrown (in Visual Studio, Debug/Exceptions and tick "Thrown" for "Common Language Runtime Exceptions" and possibly other ones as well, in cordbg.exe "catch exception")
If it is crashing madly and is using a SerialPort object then it is probably because at some point it skips onto a background thread and an exception happens here. IIRC the .DataReceived event or however you get information back from a serial port returns data on a background thread. Should an exception be thrown in this routine then the entire application will bail.
Find the background thread and put some exception handling round it.
What types of exception have you seen behaving in this way? Do you have a list of them?
Some exceptions will keep propgating up the call stack, even if they've been caught in a catch block, such as ThreadAbortException.
Others are essentially unhandleable, such as StackOverflowException or ExecutionEngineException.
If it is one of these (or some others I have probably missed), then the behaviour is probably as expected. If it is some others, then a deeper look with more information will be necessary.