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?
Related
I have a large WPF application which also uses C++ libraries for some functionality.
From time to time the application crashes due to a unhandled exception or access violation in the C++ code. EDIT: it sometime also crashes on the main thread due to unhandled C# exception.
I already employ the following handlers to log information about the crash:
DispatcherUnhandledException
TaskScheduler.UnobservedTaskException
AppDomain.CurrentDomain.UnhandledException
(EDIT: I register to these events very similar to this example: https://stackoverflow.com/a/46804709/2523211)
However, if I enabled dump file creation and these functions are reached (i.e. in an unhandled exception scenario) then the stack of the original exception has already unwound itself and there is no way for me to inspect the call stack along with the memory and threads at the moment of the error itself.
I can obviously see the stack trace itself in the exception that I get as argument to those handlers, but that is as far as that goes and I wish to see the state of my code when the exception was thrown.
(EDIT: The call stack just shows that I'm in a dispatcher frame and I cannot inspect the variables and other memory state of the application at the moment of the exception. I can use the data from the exception itself and see the call stack from it, but that's not enough to reproduce or really understand why the exception happened)
If I don't subscribe to those events then nothing changes, I still can't see the original call stack in the dump file. (EDIT: because I only get a call stack in the dispatcher)
I've also tried to set e.Handled = false but I think that that is the default value anyways.
Is there someway to indicate to WPF's dispatcher or maybe the issue is somewhere else, so that if an exception does happen, let it propagate all the way up such that when a dump is created for it, I will be able to have a helpful dump file?
What you are asking for is impossible to do within dotnet. You want to handle an exception without the stack being unwound, and dump your core for later analysis.
You can however do this outside of dotnet using the WinDbg APIs. Luckily, there is a wrapper for the WinDbg APIs called clrmd.
Just implement IDebugEventCallbacks.Exception and then call WriteDumpFile.
See https://github.com/microsoft/clrmd/blob/124b189a2519c4f13610c6bf94e516243647af2e/src/TestTasks/src/Debugger.cs for more details.
However, you should note. This solution would be attaching a debugger to production. Thus has the associated costs.
If you are just trying to collect information to solve the problem some options include
Use ProcDump https://learn.microsoft.com/en-us/sysinternals/downloads/procdump This can be configured to dump on 1st chance and 2nd chance exceptions, collecting multiple dump files if required i.e. allow app to keep running during 1st chance exceptions while capturing the app state in a dump file. Extensive configuration is possible via cmd line i.e. only handle specific exceptions etc, number of dump files to generate.
Use Time Travel Debugging feature of WinDbg, in this case you can walk backwards through your trace to find cause. This will severely degrade performance and if it takes more than several minutes to reproduce your issue these traces can quickly get very massive. If you copy the TTD folder out of WinDbg installation you can use it via command line to do a "ring mode" trace and specify a maximum buffer size which is more suitable if it takes a long time to reproduce issue, finding the options by running ttd.exe with no parameters.
Create a parent process that attaches as a debugger and will give you near full control over how you to decide to handle exceptions in the child process. Example here of creating a basic debugger
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 have a Windows Forms application. It loads assemblies with the extension .Plugin.dll with Assembly.LoadFile. One of these "plugins" calls into another assembly dll. That dll eventually throws a ValidationException exception. The method that throws the exception is in a class that inherits from IDataErrorInfo. This class is a class that is contained in a Linq to SQL class (.dbml). In the "plugin" I call DataContext.SubmitChanges. This is wrapped in a try/catch block. This causes my business logic to validate the data before submitting to the database in the OnValidate override. The result that I see is that after the ValidationExeption is thrown, the debugger stops at the bottom of the OnValidate method indicating that an unhandled exception has occured. If I continue to run the app my catch block is executed. That is what I wanted in the first place, but why am i getting an unhandled exception when it truly is handled?
I am 99% sure your "real" exception causing this is indeed unhandled -this is what the Debugger tells you at first place, and he is generally right.
When you continue to run the App in VS after that, it is not actually what would happen when you will execute your exe out of the debugger. In fact, the debugger notifies you first of the unhandled exception, and then continues some pending logic if any (that's why you see you ValidationException error). But the unhandled exception is still there. I don't exactly know the details and causes of this behavior, but I noticed this many times.
You have to catch the precise error at the precise place where the unhandledexception is thrown after you identify it.
Maybe posting your code sample would help.
Firstly, is the plugin in the same AppDomain?
Secondly, it sounds to be like you have your debugger to "Break when exception is thrown" rather than "Break when exception is user-unhandled".
In VS.NET, go to Debug --> Exceptions...
Expand the "Common Language Runtime Exceptions" node and see if any are ticked.
Using C#'s System.Diagnostics.Process object, I start an unmanaged exe, that later starts yet another unmanaged exe.
The 2nd exe is causing an unhandled-exception that I'd like my application to ignore, but can't seem to.
I'm using a try/catch statement when I start the first process, but it doesn't seem to catch the exception raised by the 2nd process. When the exception occurs, the just-in-time debugger notifies me and halts my application until I manually click "yes" I want to debug or "no". Then my application proceeds.
The JIT debugger doesn't have source code for the 2ndprocess.exe that is throwing the exception. So, it doesn't tell me what the exception is. I don't really care what the exception is, I just want to know how to catch it and ignore it so my application doesn't get halted by it. By the time the exception occurs, the work is done anyway.
Can anyone offer some insight?
You should be properly handling the exception in the second executable. Your main program won't catch the exception because it isn't throwing one, it is executing something that is.
Edit:
Do you have access to the source of the second process (the one throwing the exception)? Your application shouldn't ever just crash. If the exceptional case gets handled correctly in the second process, you won't have this problem in your primary application.
Edit2:
Since you have access to the source (open source) I recommend you fix the bug. This will help you in two ways:
1) Your program will finally work.
2) You can say you contributed to an open source project.
And, as a special bonus, you get to help out a project you use frequently. Win/Win
Since you are using process.start to actually launch the application, the application creates a separate application domain. Capturing the exception from that application is not something that I believe will be possible, since more than likely the JIT dialog is coming up due to that failed process.
Although not a solution you could stop the dialog if needed, but that has issues of its own.
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.