Bug 1102439 - Clean up child-side PBackground before thread shutdown. r=khuey

--HG--
extra : transplant_source : %29r%7D%0CP%9F%D6%20%8B%A9%EA%EE%7D%AC%BB%80%1AB%D86
This commit is contained in:
Shih-Chiang Chien 2014-11-20 14:16:36 -08:00
parent fca6c03fd3
commit 1e29b21379
2 changed files with 21 additions and 6 deletions

View File

@ -338,6 +338,7 @@ class ChildImpl MOZ_FINAL : public BackgroundChildImpl
struct ThreadLocalInfo
{
explicit ThreadLocalInfo(nsIIPCBackgroundChildCreateCallback* aCallback)
: mClosed(false)
{
mCallbacks.AppendElement(aCallback);
}
@ -345,6 +346,7 @@ class ChildImpl MOZ_FINAL : public BackgroundChildImpl
nsRefPtr<ChildImpl> mActor;
nsTArray<nsCOMPtr<nsIIPCBackgroundChildCreateCallback>> mCallbacks;
nsAutoPtr<BackgroundChildImpl::ThreadLocal> mConsumerThreadLocal;
DebugOnly<bool> mClosed;
};
// This is only modified on the main thread. It is a FIFO queue for actors
@ -431,6 +433,8 @@ private:
auto threadLocalInfo = static_cast<ThreadLocalInfo*>(aThreadLocal);
if (threadLocalInfo) {
MOZ_ASSERT(threadLocalInfo->mClosed);
if (threadLocalInfo->mActor) {
threadLocalInfo->mActor->Close();
threadLocalInfo->mActor->AssertActorDestroyed();
@ -1640,6 +1644,14 @@ ChildImpl::Shutdown()
MOZ_ASSERT(sThreadLocalIndex != kBadThreadLocalIndex);
auto threadLocalInfo =
static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
if (threadLocalInfo) {
MOZ_ASSERT(!threadLocalInfo->mClosed);
threadLocalInfo->mClosed = true;
}
DebugOnly<PRStatus> status = PR_SetThreadPrivate(sThreadLocalIndex, nullptr);
MOZ_ASSERT(status == PR_SUCCESS);
}
@ -1766,15 +1778,13 @@ ChildImpl::CloseForCurrentThread()
auto threadLocalInfo =
static_cast<ThreadLocalInfo*>(PR_GetThreadPrivate(sThreadLocalIndex));
// If we don't have a thread local we are in one of these conditions:
// 1) Startup has not completed and we are racing
// 2) We were called again after a previous close or shutdown
// For now, these should not happen, so crash. We can add extra complexity
// in the future if it turns out we need to support these cases.
if (!threadLocalInfo) {
MOZ_CRASH("Attempting to close a non-existent PBackground actor!");
return;
}
MOZ_ASSERT(!threadLocalInfo->mClosed);
threadLocalInfo->mClosed = true;
if (threadLocalInfo->mActor) {
threadLocalInfo->mActor->FlushPendingInterruptQueue();
}

View File

@ -29,6 +29,7 @@
#include "mozilla/Services.h"
#include "nsXPCOMPrivate.h"
#include "mozilla/ChaosMode.h"
#include "mozilla/ipc/BackgroundChild.h"
#ifdef MOZ_CRASHREPORTER
#include "nsServiceManagerUtils.h"
@ -323,6 +324,8 @@ SetupCurrentThreadForChaosMode()
/*static*/ void
nsThread::ThreadFunc(void* aArg)
{
using mozilla::ipc::BackgroundChild;
nsThread* self = static_cast<nsThread*>(aArg); // strong reference
self->mThread = PR_GetCurrentThread();
SetupCurrentThreadForChaosMode();
@ -349,6 +352,8 @@ nsThread::ThreadFunc(void* aArg)
// Now, process incoming events...
loop->Run();
BackgroundChild::CloseForCurrentThread();
// Do NS_ProcessPendingEvents but with special handling to set
// mEventsAreDoomed atomically with the removal of the last event. The key
// invariant here is that we will never permit PutEvent to succeed if the