tags:

views:

249

answers:

5

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...

A: 

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.

Jamie Keeling
A: 

Probably you catch and throw again some other exception from Run. Probably _store is null or something.

Hun1Ahpu
Please read description, exception is the expected type.
Dearmash
+3  A: 

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.

Otávio Décio
Dearmash
Well, and other exceptions they are - and they are crashing your app.
Otávio Décio
in the resulting .dmp file, the only exception that is included is my exception. I'm not sure how much clearer I can be.
Dearmash
Can you get this to happen when you use `catch{ }` (That is, a catch with no exception type)?
Jake
Just to leave no stone unturned, I tried just that jake, the exception is still thrown. Sorry Otavio if I was rash.
Dearmash
This didn't solve the problem, however it did lead to some useful information. Thanks
Dearmash
A: 

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?

Dan Bryant
Both handlers are registered and neither are being hit. Otherwise this would have been just a simple matter of parsing our logs. Life became much easier the day I added those handlers to code.To my knowledge, we don't explicitly declare any finalizers in our code. We rely on IDispose quite a bit to remove things after we're done with them.
Dearmash
You might check for threads that linger well beyond application shutdown has started, though I would be surprised if the AppDomain releases its UnhandledException handlers before all of the threads are terminated.
Dan Bryant
+2  A: 

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

Hightechrider
This is a good resource. Unfortunately I'm relatively sure that each of these exceptions can still be caught in a debugger. Unfortunately no amount of debugger is letting me catch whatever is crashing. That looks like a decent blog, good amount of content, if not updated more than 1/month. I'll add it to the list. Thanks,
Dearmash