Bug 957693: Fix a worker hang and other related bugs. r=bent

This commit is contained in:
Kyle Huey 2014-01-10 16:37:47 -08:00
parent 8267f04e5f
commit 45cb351d71
4 changed files with 58 additions and 21 deletions

View File

@ -177,6 +177,13 @@ private:
virtual void
PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
MOZ_OVERRIDE;
NS_DECL_NSICANCELABLERUNNABLE
void
ShutdownScriptLoader(JSContext* aCx,
WorkerPrivate* aWorkerPrivate,
bool aResult);
};
class ScriptLoaderRunnable MOZ_FINAL : public WorkerFeature,
@ -740,11 +747,26 @@ ScriptExecutorRunnable::PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
}
}
aWorkerPrivate->RemoveFeature(aCx, &mScriptLoader);
aWorkerPrivate->StopSyncLoop(mSyncLoopTarget, result);
ShutdownScriptLoader(aCx, aWorkerPrivate, result);
}
}
NS_IMETHODIMP
ScriptExecutorRunnable::Cancel()
{
ShutdownScriptLoader(mWorkerPrivate->GetJSContext(), mWorkerPrivate, false);
return NS_OK;
}
void
ScriptExecutorRunnable::ShutdownScriptLoader(JSContext* aCx,
WorkerPrivate* aWorkerPrivate,
bool aResult)
{
aWorkerPrivate->RemoveFeature(aCx, &mScriptLoader);
aWorkerPrivate->StopSyncLoop(mSyncLoopTarget, aResult);
}
bool
LoadAllScripts(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
nsTArray<ScriptLoadInfo>& aLoadInfos, bool aIsWorkerScript)

View File

@ -1067,8 +1067,8 @@ public:
: WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
mStatus(aStatus)
{
MOZ_ASSERT(aStatus == Terminating || aStatus == Canceling ||
aStatus == Killing);
MOZ_ASSERT(aStatus == Closing || aStatus == Terminating ||
aStatus == Canceling || aStatus == Killing);
}
private:
@ -4873,11 +4873,26 @@ WorkerPrivate::RunCurrentSyncLoop()
}
// Make sure that the stack didn't change underneath us.
MOZ_ASSERT(!mSyncLoopStack.IsEmpty());
MOZ_ASSERT(mSyncLoopStack.Length() - 1 == currentLoopIndex);
MOZ_ASSERT(mSyncLoopStack[currentLoopIndex] == loopInfo);
// We're about to delete |loop|, stash its event target and result.
return DestroySyncLoop(currentLoopIndex);
}
bool
WorkerPrivate::DestroySyncLoop(uint32_t aLoopIndex, nsIThreadInternal* aThread)
{
MOZ_ASSERT(!mSyncLoopStack.IsEmpty());
MOZ_ASSERT(mSyncLoopStack.Length() - 1 == aLoopIndex);
if (!aThread) {
nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(mThread);
MOZ_ASSERT(thread);
aThread = thread.get();
}
// We're about to delete the loop, stash its event target and result.
SyncLoopInfo* loopInfo = mSyncLoopStack[aLoopIndex];
nsIEventTarget* nestedEventTarget =
loopInfo->mEventTarget->GetWeakNestedEventTarget();
MOZ_ASSERT(nestedEventTarget);
@ -4891,11 +4906,11 @@ WorkerPrivate::RunCurrentSyncLoop()
MutexAutoLock lock(mMutex);
#endif
// This will delete |loop|!
mSyncLoopStack.RemoveElementAt(currentLoopIndex);
// This will delete |loopInfo|!
mSyncLoopStack.RemoveElementAt(aLoopIndex);
}
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(thread->PopEventQueue(nestedEventTarget)));
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aThread->PopEventQueue(nestedEventTarget)));
return result;
}

View File

@ -34,6 +34,7 @@ class nsIEventTarget;
class nsIPrincipal;
class nsIScriptContext;
class nsIThread;
class nsIThreadInternal;
class nsITimer;
class nsIURI;
@ -1098,6 +1099,9 @@ private:
bool
RunCurrentSyncLoop();
bool
DestroySyncLoop(uint32_t aLoopIndex, nsIThreadInternal* aThread = nullptr);
void
InitializeGCTimers();
@ -1157,10 +1161,13 @@ class AutoSyncLoopHolder
{
WorkerPrivate* mWorkerPrivate;
nsCOMPtr<nsIEventTarget> mTarget;
uint32_t mIndex;
public:
AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate)
: mWorkerPrivate(aWorkerPrivate), mTarget(aWorkerPrivate->CreateNewSyncLoop())
: mWorkerPrivate(aWorkerPrivate)
, mTarget(aWorkerPrivate->CreateNewSyncLoop())
, mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1)
{
aWorkerPrivate->AssertIsOnWorkerThread();
}
@ -1170,6 +1177,7 @@ public:
if (mWorkerPrivate) {
mWorkerPrivate->AssertIsOnWorkerThread();
mWorkerPrivate->StopSyncLoop(mTarget, false);
mWorkerPrivate->DestroySyncLoop(mIndex);
}
}

View File

@ -508,8 +508,8 @@ private:
{
MOZ_ASSERT(NS_FAILED(mErrorCode));
Throw(aCx, mErrorCode);
}
Throw(aCx, mErrorCode);
}
};
public:
@ -1807,14 +1807,6 @@ XMLHttpRequest::SendInternal(const nsAString& aStringBody,
return;
}
// If our sync XHR was canceled during the send call the worker is going
// away. We have no idea how far through the send call we got. There may
// be a ProxyCompleteRunnable in the sync loop, but rather than run the loop
// to get it we just let our RAII helpers clean up.
if (mCanceled) {
return;
}
autoUnpin.Clear();
if (!autoSyncLoop.ref().Run()) {