Bug 1377471 - disconnect mChannelChild directly if ActorDestroy is triggered by shutdown. r?mayhemer
HttpBackgroundChannelChild::ActorDestroy is always called on STS thread. However OnSocketThread will return wrong
result during shutdown phase. In this case we need to use gSocketTransportService->IsOnCurrentThreadInfallible()
if the can be execute during shutdown phase. In addition, we should disconnect mChannelChild immediately while
ActorDestroy is not triggered by normal IPDL deletion to release HTTP channel as soon as possible.
MozReview-Commit-ID: CD7v3efS4zf
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
+++ b/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
@@ -430,37 +430,29 @@ HttpBackgroundChannelChild::RecvSetClass
return IPC_OK();
}
void
HttpBackgroundChannelChild::ActorDestroy(ActorDestroyReason aWhy)
{
LOG(("HttpBackgroundChannelChild::ActorDestroy[this=%p]\n", this));
-
- if (!OnSocketThread()) {
- // PBackgroundChild might be destroyed during shutdown and
- // ActorDestroy will be called on main thread directly.
- // Simply disconnect with HttpChannelChild to release memory.
- mChannelChild = nullptr;
- RefPtr<HttpBackgroundChannelChild> self = this;
- mQueuedRunnables.AppendElement(NS_NewRunnableFunction(
- "HttpBackgroundChannelChild::ActorDestroyNonSTSThread", [self]() {
- MOZ_ASSERT(NS_IsMainThread());
- self->mChannelChild = nullptr;
- }));
- return;
- }
-
- MOZ_ASSERT(OnSocketThread());
+ // This function might be called during shutdown phase, so OnSocketThread()
+ // might return false even on STS thread. Use IsOnCurrentThreadInfallible()
+ // to get correct information.
+ MOZ_ASSERT(gSocketTransportService);
+ MOZ_ASSERT(gSocketTransportService->IsOnCurrentThreadInfallible());
// Ensure all IPC messages received before ActorDestroy can be
// handled correctly. If there is any pending IPC message, destroyed
// mChannelChild until those messages are flushed.
- if (!mQueuedRunnables.IsEmpty()) {
+ // If background channel is not closed by normal IPDL actor deletion,
+ // remove the HttpChannelChild reference and notify background channel
+ // destroyed immediately.
+ if (aWhy == Deletion && !mQueuedRunnables.IsEmpty()) {
LOG((" > pending until queued messages are flushed\n"));
RefPtr<HttpBackgroundChannelChild> self = this;
mQueuedRunnables.AppendElement(NS_NewRunnableFunction(
"HttpBackgroundChannelChild::ActorDestroy", [self]() {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<HttpChannelChild> channelChild = self->mChannelChild.forget();
if (channelChild) {
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -312,17 +312,21 @@ HttpChannelChild::OnBackgroundChildReady
mBgInitFailCallback = nullptr;
}
}
void
HttpChannelChild::OnBackgroundChildDestroyed(HttpBackgroundChannelChild* aBgChild)
{
LOG(("HttpChannelChild::OnBackgroundChildDestroyed [this=%p]\n", this));
- MOZ_ASSERT(OnSocketThread());
+ // This function might be called during shutdown phase, so OnSocketThread()
+ // might return false even on STS thread. Use IsOnCurrentThreadInfallible()
+ // to get correct information.
+ MOZ_ASSERT(gSocketTransportService);
+ MOZ_ASSERT(gSocketTransportService->IsOnCurrentThreadInfallible());
nsCOMPtr<nsIRunnable> callback;
{
MutexAutoLock lock(mBgChildMutex);
// mBgChild might be removed or replaced while the original background
// channel is destroyed on STS thread.
if (aBgChild != mBgChild) {