22

Update: I've filed a bug report on Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/details/568271/debugger-halting-on-exception-thrown-inside-methodinfo-invoke#details

If you can reproduce this problem on your machine, please upvote the bug so it can be fixed!


Ok I've done some testing and I've reduced the problem to something very simple:

i. Create a method in a new class that throws an exception:

public class Class1 {
    public void CallMe() {
        string blah = null;
        blah.ToLower();
    }
}

ii. Create a MethodInfo that points to this method somewhere else:

Type class1 = typeof( Class1 );
Class1 obj = new Class1();
MethodInfo method = class1.GetMethod( "CallMe" );

iii. Wrap a call to Invoke() in a try/catch block:

try {
    method.Invoke( obj, null ); // exception is not being caught!
} catch {
}

iv. Run the program without the debugger (works fine).

v. Now run the program with the debugger. The debugger will halt the program when the exception occurs, even though it's wrapped in a catch handler that tries to ignore it. (Even if you put a breakpoint in the catch block it will halt before it reaches it!)

In fact, the exception is happening when you run it without the debugger too. In a simple test project it's getting ignored at some other level, but if your app has any kind of global exception handling, it will get triggered there as well. [see comments]

This is causing me a real headache because it keeps triggering my app's crash-handler, not to mention the pain it is to attempt to debug.

devios1
  • 36,899
  • 45
  • 162
  • 260
  • 7
    +1 cause you took the time to reduce this into a sane example. – Byron Whitlock Jun 16 '10 at 23:11
  • See here: http://stackoverflow.com/questions/2724703/why-does-vs2010-always-break-on-exception-from-methodinfo-invoke – Dan Bryant Jun 16 '10 at 23:16
  • 4
    Have you enabled the exception as 'stop when throw' in Visual studio? to Stop this behaviour, go to Debug| Exceptions and uncheck stop on throw. – Preet Sangha Jun 16 '10 at 23:16
  • AFAIK, debugger catches everything and doesn't care if it is handled or not. Try to make a short verification code to show that the exception is not caught, which would not involve using a debugger. – Rotsor Jun 16 '10 at 23:18
  • 1
    I did some more experimenting and it's only occurring with .NET 4.0. Should I report this as a bug? – devios1 Jun 16 '10 at 23:19
  • @Dan, I saw that, but it doesn't help in my case. @Rotsor I will work on that. @Preet: stop when throw is not enabled. I checked. – devios1 Jun 16 '10 at 23:20
  • 1
    No repro, works fine on .NET 4.0 RTM on my machine. As it should. – Hans Passant Jun 17 '10 at 00:21
  • Also works fine with my .NET 4.0 RTM, w/ and w/o debugger. – Buu Jun 17 '10 at 03:51
  • @John I deleted my comment, the problem was internal! somehow, the application's startup page was changed on the combo @ project settings, it should be set blank and that's the problem, that it always attempts to set it with the first value, which was a window subclass that has only parameterized public constructors, so it thew the exception you see here, but justified. – Shimmy Weitzhandler Jul 13 '10 at 10:01

2 Answers2

5

I can reproduce this on my .NET 4 box, and you're right -- it only happens on .NET 4.0.

This smells very much like a bug to me, and should go on MS Connect. Major bummer if this is tripping your crash handler. Sounds like a non-pleasing way to work around this is to wrap the invoked method inside its own handler. :-(

One thing I can not reproduce, though, is tripping the crash handler. Here's my program:

namespace trash {
    public class Class1 {
        public void CallMe() {
            string blah = null;
            blah.ToLower();
        }
    }

    class Program {
        static void Main(string[] args) {
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);           
            var class1 = typeof(Class1);
            var method = class1.GetMethod("CallMe");

            try {
                var obj = new Class1();
                method.Invoke(obj, null); // exception is not being caught!
            }
            catch (System.Reflection.TargetInvocationException) {
                Console.Write("what you would expect");
            }

        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
            Console.Write("it would be horrible if this got tripped but it doesn't!");
        }
    }
}
Dave Markle
  • 95,573
  • 20
  • 147
  • 170
  • I haven't yet been able to reproduce the crash handler tripping in a test app either, however I'm working on it. For some reason my real app is dying pretty hard and the exception (which I print to a log file) looks very similar. – devios1 Jun 17 '10 at 01:38
  • I did however discover something else interesting: if you bind to a property in WPF that throws an exception, the debugger will halt there too when you run it--you don't even need to call MethodInfo.Invoke at all ! The crash handler tripping when not in debug mode seems to be false, as it turns out it was a different problem causing that--meaning, this could be a VS2010 bug. – devios1 Jun 17 '10 at 03:43
  • This answer is the same result I get. Basically there is a catch-all somewhere inside `Invoke`, something I think they seriously regret now, but it causes no end of headaches. NB. I believe exactly when the UnhandledException handler will execute depends on the version of Windows! So you may get different results on XP/Vista/7. My testing is on 7 and the UnhandledException event never fires, but it does halt in the debugger. – Daniel Earwicker Jun 17 '10 at 11:01
  • This works for me as expected: only the "What you would expect" is printed. .NET 4.0, 32-bit. Perhaps they fixed it in one of the security updates they release from time to time... – Roman Starkov Oct 06 '11 at 17:06
-1

You can't catch all exceptions. There's a few assumptions in your example. You are, for instance, assuming the exception was raised on the calling thread. Catching unhandled exceptions on other threads depends on which runtimes you're using (console, winforms, WPF, ASP.Net, etc).

Additionally, calls to System.Environment.FailFast() do not generate any handlable condition - the process is effectively terminated with no chance for intervention.

Nathan Ernst
  • 4,540
  • 25
  • 38
  • He's calling Invoke(), not BeginInvoke(), so the call happens on the current thread. There is some external code that gets in between the call when the invocation is done, though. – Dave Markle Jun 16 '10 at 23:37
  • @Dave, but that does not guarantee that the invoked method in question does not cause another thread to be created. My assertion above holds. – Nathan Ernst Jun 16 '10 at 23:46
  • @Dave, by that, I mean, the method called by `Invoke`, could in turn create a thread (directly, or indirectly), I don't mean that `Invoke`, itself, will arbitrarily create another thread. – Nathan Ernst Jun 16 '10 at 23:47
  • It could also torrent the entire Lady Gaga anthology in the background on each call, but I don't see a reason why it would do that either. – Dave Markle Jun 17 '10 at 00:01
  • @Dave, but there is zero guarantee that it doesn't. I personally live in a world where clients invoking my libs cause me to spawn external threads, and while I do my damnedest to handle errors properly on that thread, there are occasions when I cannot. And I'm faced with 2 possiblilites: ignoring the error and providing bad data, or failing and potentially allowing the client to respond. Regardless, I cannot and do not fail silently. – Nathan Ernst Jun 17 '10 at 00:10