-
Notifications
You must be signed in to change notification settings - Fork 593
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AutorecoveringConnection prevents AppDomain.Unload() of enclosing AppDomain #826
Comments
What would you recommend as the desired behavior? How can autorecovering connections detect a condition where they should stop performing recoveries? |
Well, in my opinion an object should not resist its parent AppDomain being unloaded - except for very specific reasons - which I don't see present here. So I would recommend that Does that make sense to you? |
Yes, it does. I just wanted this conversation to move to a specific suggestion. Other clients sometimes limit connection recovery attempts e.g. when they haven't succeeded for a certain number of times. Reacting to domain shutdown, if we can do it easily, makes perfect sense. |
As a note, https://docs.microsoft.com/en-us/dotnet/core/porting/net-framework-tech-unavailable |
Nothing fancy needed at our end. We have not tried to be clever with configuring Ah yes, and things could be entirely different on ASP.NET Core, so it would be very helpful if you could look into the corresponding situation on that platform, too. |
@bording if you have a second, I would be very interested in your opinion here. It seems odd for this library to interact with an |
Wouldn't it make more sense for the user to hook up closing the AutorecoveringConnection on AppDomain.Unload, since the event is never raised in the default AppDomain? https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.domainunload?view=netframework-4.8 |
Doing some quick research, I do see some historical discussion on this topic, and I see the now-vestigial I agree that it's odd for this library to directly be interacting with AppDomain APIs, If someone was creating custom AppDomains themselves as the repro in the initial post demonstrates, then it would be reasonable to say that they need to also wire up the However, you can often be inside a non-default AppDomain without even realizing it, so I'm not sure I'd want the answer here to be "it's up to the user to wire it up themselves." If we take a step back, why do we need to worry about AppDomains unloading at all? If the unload shows up to the It seems like making a |
Good point.
is the typical situation any IIS-hosted ASP.NET WebService will find itself in, so it could be quite common in the Windows ecosystem. |
This does not feel like a "must have" for |
Abstract
An active
RabbitMQ.Client.Framing.Impl.AutorecoveringConnection
instance violently opposes any attempt by its enclosingSystem.AppDomain
to unload itself, resulting an a thrownSystem.CannotUnloadDomainException
and a subsequent crash of the containing OS process.Details
Closer analysis shows that the
RabbitMQ.Client.Framing.Impl.Connection
instance embedded in an AutorecoveringConnection will experience the call toAppDomain.Unload(...)
as aSystem.Threading.ThreadAbortException
inside itsMainLoop
method, specifically in the call toInboundFrame inboundFrame = _frameHandler.ReadFrame()
.Because AutorecoveringConnection generally tries to recover from Thread aborts, it will proceed to enter its automatic recovery procedure.
Thus, an active Connection will be restored, and in all likelyhood the persisting reference to an unmanaged resource - namely a network Socket - is what prevents the AppDomain from unloading in an orderly manner.
All of the above was observed while running RabbitMQ.Client 6.0.0 in the .NET 4.6.1 variant inside a WebService in Microsoft Internet Information Server on Windows Server 2016.
Apparently, previous versions of RabbitMQ.Client exposed a means of subscribing Connection instances to the
AppDomain.DomainUnload
Event via theConnection.HandleDomainUnload(...)
method, but this method is no longer publicly accessible.Relevance
The observed behavior is a relevant problem because IIS is in the habit of maintaining multiple AppDomain instances inside an Application Pool and recycling these AppDomains on various occasions, e.g. changes to the web.config, which will currently result in a crash of the associated Application Pool. This hurts scenarios where IIS is used as a bridging technology from WebServices to RabbitMQ.
Please consider modifying the behavior of the
AutorecoveringConnection
to explicitly handle AppDomain unload scenarios.Workaround
In the present state of affairs, the
System.CannotUnloadDomainException
can be avoided by disposing all active AutorecoveringConnection instances from within an explicitAppDomain.DomainUnload
Event handler.Repro
The code snippet attached below will raise the
CannotUnloadDomainException
onAppDomain.DomainUnload(...)
unless called with theuseWorkaround
parameter.The text was updated successfully, but these errors were encountered: