12

I'm getting an unhandled exception in my application when I close the last window:

An unhandled exception of type 'System.NullReferenceException' occurred in PresentationFramework.dll

Additional information: Object reference not set to an instance of an object.

This only occurs if, during the application's lifetime, I open a child window through a certain process that I have set up. The window exists in another assembly that is loaded at runtime dynamically with MEF, and then instantiated with Castle. If I then call a certain method, it creates a new STA thread and opens a WPF dialog window.

Some caveats:

  • This only happens on certain machines/environments (I'm not able to discern a pattern though)
  • I have an UnhandledException handler on the dispatcher for the application which catches all unhandled exceptions. This is not caught by that.

The call stack is:

PresentationFramework.dll!MS.Internal.Controls.ConnectionPointCookie.Disconnect()
PresentationFramework.dll!MS.Internal.Controls.ConnectionPointCookie.Finalize()

Has anyone seen this before, or would anyone know how to debug this? It's strange that there's no call stack and it happens right as the program is exiting.

qJake
  • 16,821
  • 17
  • 83
  • 135
  • I think you need to edit this question to include the ShutdownMode in your app.xaml file. – Gayot Fow Apr 30 '14 at 15:13
  • The `ShutdownMode` property is set to `OnMainWindowClose`, however, during startup there are a few dialogs that can be triggered, so it is temporarily switched to `OnExplicitShutdown` during App Startup, but it is **always** switched back to `OnMainWindowClose` before the main window even opens. – qJake Apr 30 '14 at 15:24
  • I don't know what causes the exception, but I would try to debug it by starting it from another app that redirects the Stderr/Stdio streams and hope (absolutely *hope*) that there's an artefact in those streams that gives a clue. – Gayot Fow Apr 30 '14 at 15:56
  • Visual Studio already does this (via the Output window) and there is nothing of significance except what was already mentioned. – qJake Apr 30 '14 at 16:17
  • Well, no, actually the console error stream is not shown in the vs output window. Hence my suggestion that it might be worth inspecting for any artefact. – Gayot Fow Apr 30 '14 at 16:51
  • If you're sure about the stack trace, and if you have the latest version of the framework, then it looks like a bug in PresentationFramework. I suspect it's a multithreading issue since the code looks fine so far (when looked using a tool such as .NET Reflector or similar or reference source). You should report it to connect: http://connect.microsoft.com/ – Simon Mourier May 23 '14 at 15:52

2 Answers2

13

Your question is devoid of details and the stack trace is short but gives lots of clues towards the underlying problem. Some visible facts:

  • the exception occurs on the finalizer thread, the reason the stack trace is so short. An unhandled exception in a finalizer is fatal, they'll always terminate the program. The reason that trying to use try/catch in your code had no effect.
  • a connection-point cookie is a COM term, you get one when you subscribe a COM event. That cookie needs to be used again when you unsubscribe the event, that happens in the finalizer. There is only one class in WPF that uses it, the WebBrowser control. The WPF class is a wrapper around Internet Explorer, a COM component.
  • the exception, while it has a managed exception name, is not caused by managed code. The finalizer already checks for null references, it is Internet Explorer that throws an unmanaged AccessViolationException under the hood. These are treated the exact same way by the CLR since they have the exact same cause, the finalizer doesn't otherwise do anything to make the distinction clearer. Unmanaged code is just as vulnerable as managed code to null pointers. More so, heap corruption is a very common cause.
  • the finalizer already catches all exceptions, an NRE is however a critical exception so it rethrows it, that's the end of your program.

Using WebBrowser is a liability, browsers in general are rather crash-prone. This is amplified when you use the control in your app, it runs in-process and doesn't have the kind of crash protection that Internet Explorer itself uses. So anything that goes wrong in the browser will directly affect the stability of your app, often with a very hard to diagnose crash reason since it is unmanaged code that bombs.

And such crashes repeat very poorly, the core reason that you trouble getting a repro for it yourself. The most common troublemakers in browsers are add-ins, ActiveX controls (like Flash) and anti-malware. You'll have extra trouble if you can't control the kind of web sites that are navigated, there are plenty that probe a browser for vulnerabilities intentionally.

There is one specific countermeasure you can use, call the control's Dispose() method when you no longer use it. Typically in the Window's Closing event handler. That will immediately unregister the COM event and trigger the crash, now you can catch it. Do strongly consider shutting down your program when that happens, you do have a dead corpse in your process that will turn in a zombie when you try to revive it.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I do in fact use a WebBrowser control (the fact that you were able to discern that just from the stack trace is impressive), and I'll try disposing of it by hand to see if that remedies the problem. FYI, the application is already targeting .NET 4, so it must be handling things similarly as previous versions did. I'll update here after I've tested it. – qJake May 23 '14 at 18:04
  • Okay, cancel that, looks like it just got moved. – Hans Passant May 23 '14 at 18:07
  • Looks like that was the problem! I disposed the WebBrowser and discarded any exceptions that came from it, and the application shuts down cleanly now. Thanks! – qJake May 23 '14 at 18:17
1

I had the same problem in one of my applications and never found the real problem behind it. But I found a workaround for this application. At Closing event of the main window I implemented a loop that closed all other windows before. Then it worked. Maybe this could work for you too. If you find the reason it would be even better.

CRABOLO
  • 8,605
  • 39
  • 41
  • 68
Crow1973
  • 31
  • 5