Why cannot this ASP.NET application domain be unloaded?
Symptom:
According to the dump file, there are dozens of application domains for one asp.net web application.
Troubleshooting:
Asp.net starts new appdomain and unloads old one in various scenarios, for example:
· Machine.Config, Web.Config or Global.asax are modified
· The bin directory or its contents is modified
· The number of re-compilations (aspx, ascx or asax) exceeds the limit specified by the <compilation numRecompilesBeforeAppRestart=/> setting in machine.config or web.config (by default this is set to 15)
· The physical path of the virtual directory is modified
· The CAS policy is modified
· The web service is restarted
· (2.0 only) Application Sub-Directories are deleted (see Todd’s blog https://blogs.msdn.com/toddca/archive/2006/07/17/668412.aspx for more info)
This blog article describes the behavior for more details: https://blogs.msdn.com/tess/archive/2006/08/02/asp-net-case-study-lost-session-variables-and-appdomain-recycles.aspx
It will fail to unload the old AppDomain if you are stuck inside unmanaged code which performs an uninterruptable blocking operation.
A System.CannotUnloadAppDomainException will occur and can be found in the dump.
Below is a typical call stack when AppDomain will fail to be unloaded, System.Net.Sockets.Socket.Receive is doing uninterruptable blocking operation:
Child-SP RetAddr Call Site 000000000362d410 00000642749e90b0 DomainNeutralILStubClass.IL_STUB(IntPtr, Byte*, Int32, System.Net.Sockets.SocketFlags) 000000000362d4f0 00000642749e9174 System.Net.Sockets.Socket.Receive(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.Net.Sockets.SocketError ByRef) ……. 000000000362dd00 000006427f62ff5d System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32) |
Resolution:
To fix the issue you should prevent the code from calling inside unmanaged code which performs an uninterruptable blocking operation when AppDomain is unloading.
We did a test to use a background thread calling System.Net.Sockets.Socket.Receive always. When reload new AppDomain, the same System.CannotUnloadAppDomainException occurs.
A recycling of application pool process w3wp.exe will force IIS to unload all AppDomains. It can be considered as a workaround.
Regards,
Juntao Zhu