Why don’t the managed Debugging APIs expose the Finalizer thread?

That’s a fair question. Part of the answer is we don’t believe people could use it properly.  The main reasons we find people ask are:

1) User curiosity:
Users just like to know this sort of trivia when they’re debugging. You see 6 threads in the VS threads window when debugging what you thought was a single-threaded app, and you want to know why.  See Steve’s post about naming threads for the debugger. Unfortunately, the CLR doesn’t name the finalizer thread. (I’m told it’s for perf reasons, but I don’t understand…). I think the correct fix here is to make naming the finalizer thread work just like the rest of the thread-naming (and fix whatever perf problems came up before); not add a special debugger API to recognize it.

2) Work around for Bugs:
People hit a threading bug exposed by the finalizer thread and then want to be able to identify the finalizer thread to special case some behavior around the bug. Evil! The finalizer plays by the same rule as other threads, so threading bugs (whether in the debugger or a regular managed app). Thus threading bugs that happen to occur with the finalizer thread could very likely happen in other arrangements too.

Now empirically, the finalizer appears to behave differently than your main thread. The finalizer doesn’t actually show up in managed code until it runs finalizers, and that could happen at any random time. That’s because the managed debugger doesn’t see threads until they actually run managed code (see more trivia about ICorDebugThread). Since the main thread immediately runs your managed Main() function, this is not an issue. 

However, other threads could behave the same way as the finalizer. In general, a native thread could enter managed code at anytime. In MC++, a thread may start off in the native portion of the app, and then happen to call a C++ compiled to IL and then become managed.  

Other trivia:
Yun Jin mentions other special theads in the CLR.

Comments (4)

  1. Jeff Stong says:

    I occasionaly visit Mike Stall’s .NET Debugging Blog because it’s interesting to peer beneath the hood…

  2. Trackback from dotnetkicks.com

  3. When you attach to a managed debuggee (via ICorDebug::DebugActiveProcess), ICorDebug generates a set