In my C# .Net 4.0 project, I use AppDomains to load plugin assemblies, ask them to do work, and then unload the AppDomain so I don't have to keep the assemblies in the main process.
For one particular plugin, I get a CannotUnloadAppDomainException
when I call AppDomain.Unload()
. I have found that this is most likely because the plugin has started a background thread which is either stuck or taking a long time (~10 seconds) in a catch
or finally
block. Unfortunately, I have no idea where the thread is.
This only happens on a customer's machine so I can't use my debugger to help. I can, however, give them a patch to write more information to a logfile if I can find something more helpful to write out.
I have the source code for the plugin assembly and I have been trying to do some static analysis and running some tests, but it is quite large and I have had no luck finding a place where it is getting stuck in a catch
or finally
.
My questions:
Is there any way where upon getting a CannotUnloadAppDomainException
that I can get a list of threads that are running with their callstacks in the child AppDomain?
Other than catch
and finally
blocks, are there other code sections that can throw this exception?
Using the Microsoft.Diagnostics.Runtime library mentioned in this post (which is a NuGet package) I was able to list all threads still running and their callstacks when the child AppDomain's function was about to return. I did have to temporarily upgrade my app to .NET 4.5 to run with the library, but the source for the library is available on GitHub so it may be possible to build this library with < .Net 4.5
It turns out that it was a bug in a third party library that handles our database connection that left a couple locked up threads when the database was using SSL on the local machine.