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()
to get correct result. 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) {