Bug 953435 - Browser hang on Mac if an AfterProcessNextEvent callback tries to spin the event loop, r=nfroyd+smichaud

--HG--
extra : rebase_source : e999d852f5f73b18f37ff6a5488cc171c95d9e61
This commit is contained in:
Olli Pettay 2014-01-09 00:10:06 +02:00
parent 6967c61375
commit cb3b85db05
6 changed files with 41 additions and 9 deletions

View File

@ -109,7 +109,6 @@ protected:
// to 3%-4%). See bmo bug 395397.
static const uint32_t kHadMoreEventsCountMax = 3;
int32_t mRecursionDepth;
int32_t mNativeEventCallbackDepth;
// Can be set from different threads, so must be modified atomically
int32_t mNativeEventScheduledDepth;

View File

@ -210,7 +210,6 @@ nsAppShell::nsAppShell()
, mTerminated(false)
, mSkippedNativeCallback(false)
, mHadMoreEventsCount(0)
, mRecursionDepth(0)
, mNativeEventCallbackDepth(0)
, mNativeEventScheduledDepth(0)
{
@ -712,11 +711,14 @@ nsAppShell::ProcessNextNativeEvent(bool aMayWait)
bool
nsAppShell::InGeckoMainEventLoop()
{
if ((gXULModalLevel > 0) || (mRecursionDepth > 0))
if (gXULModalLevel > 0)
return false;
if (mNativeEventCallbackDepth <= 0)
return false;
return true;
bool isProcessingEvents = false;
NS_GetCurrentThread()->GetIsProcessingEvents(&isProcessingEvents);
return !isProcessingEvents;
}
// Run
@ -818,8 +820,6 @@ nsAppShell::OnProcessNextEvent(nsIThreadInternal *aThread, bool aMayWait,
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
mRecursionDepth = aRecursionDepth;
NS_ASSERTION(mAutoreleasePools,
"No stack on which to store autorelease pool");
@ -845,8 +845,6 @@ nsAppShell::AfterProcessNextEvent(nsIThreadInternal *aThread,
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
mRecursionDepth = aRecursionDepth;
CFIndex count = ::CFArrayGetCount(mAutoreleasePools);
NS_ASSERTION(mAutoreleasePools && count,

View File

@ -462,6 +462,17 @@ LazyIdleThread::ProcessNextEvent(bool aMayWait,
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
LazyIdleThread::GetIsProcessingEvents(bool* aIsProcessing)
{
if (mThread) {
return mThread->GetIsProcessingEvents(aIsProcessing);
}
*aIsProcessing = false;
return NS_OK;
}
NS_IMETHODIMP
LazyIdleThread::Notify(nsITimer* aTimer)
{

View File

@ -17,7 +17,7 @@
*
* See nsIThreadManager for the API used to create and locate threads.
*/
[scriptable, uuid(9c889946-a73a-4af3-ae9a-ea64f7d4e3ca)]
[scriptable, uuid(4df07d3a-e759-4256-ba4e-7e2265354ec3)]
interface nsIThread : nsIEventTarget
{
/**
@ -82,4 +82,10 @@ interface nsIThread : nsIEventTarget
* not the current thread.
*/
boolean processNextEvent(in boolean mayWait);
/**
* true if we're processing runnables or thread observers and if this is the
* current thread.
*/
readonly attribute boolean isProcessingEvents;
};

View File

@ -304,6 +304,7 @@ nsThread::nsThread(MainThreadFlag aMainThread, uint32_t aStackSize)
, mThread(nullptr)
, mRunningEvent(0)
, mStackSize(aStackSize)
, mProcessingEvent(0)
, mShutdownContext(nullptr)
, mShutdownRequired(false)
, mEventsAreDoomed(false)
@ -596,6 +597,8 @@ nsThread::ProcessNextEvent(bool mayWait, bool *result)
}
}
++mProcessingEvent;
bool notifyMainThreadObserver =
(MAIN_THREAD == mIsMainThread) && sMainThreadObserver;
if (notifyMainThreadObserver)
@ -650,9 +653,22 @@ nsThread::ProcessNextEvent(bool mayWait, bool *result)
if (notifyMainThreadObserver && sMainThreadObserver)
sMainThreadObserver->AfterProcessNextEvent(this, mRunningEvent, *result);
--mProcessingEvent;
return rv;
}
NS_IMETHODIMP
nsThread::GetIsProcessingEvents(bool* aIsProcessing)
{
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
return NS_ERROR_NOT_SAME_THREAD;
}
*aIsProcessing = mProcessingEvent != 0;
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsISupportsPriority

View File

@ -150,6 +150,8 @@ protected:
uint32_t mRunningEvent; // counter
uint32_t mStackSize;
uint32_t mProcessingEvent;
struct nsThreadShutdownContext *mShutdownContext;
bool mShutdownRequired;