This was originally observed in a CI environment using DotCover to run NUnit tests where it led to hung builds.
After a lot of digging, I was able to pin this down to a what strongly appears to be a bug that occurs when the code is running in .NET Framework 64-bit release builds using RyuJIT (which is the default 64-bit JIT). I was able to observe in the debugger that a ThreadAbortException, which in this case was triggered by AppDomain.Unload, would be thrown repeatedly without exciting the while loop inside of AsynchronousWorker. Eventually the unload times out and will throw a CannotUnloadAppDomainException. I was very fortunate to find this blog post which details the exact same scenario.
Thanks to @WramblinWreck, who started the debugging and narrowed it down to the DogStatsdService.
Afaict, the issue manifests from the addition of this catch, which should not change behavior. I assume the JIT optimizes something incorrectly which causes the ThreadAbortException to not be re-thrown at the end of the catch as it should be.
The workaround is to catch and rethrow the ThreadAbortException manually and I've got a PR incoming shortly.
This was originally observed in a CI environment using DotCover to run NUnit tests where it led to hung builds.
After a lot of digging, I was able to pin this down to a what strongly appears to be a bug that occurs when the code is running in .NET Framework 64-bit release builds using RyuJIT (which is the default 64-bit JIT). I was able to observe in the debugger that a ThreadAbortException, which in this case was triggered by AppDomain.Unload, would be thrown repeatedly without exciting the while loop inside of AsynchronousWorker. Eventually the unload times out and will throw a CannotUnloadAppDomainException. I was very fortunate to find this blog post which details the exact same scenario.
Thanks to @WramblinWreck, who started the debugging and narrowed it down to the DogStatsdService.
Afaict, the issue manifests from the addition of this catch, which should not change behavior. I assume the JIT optimizes something incorrectly which causes the ThreadAbortException to not be re-thrown at the end of the catch as it should be.
The workaround is to catch and rethrow the ThreadAbortException manually and I've got a PR incoming shortly.