mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1208687: Only discard events from the outermost queue. r=ehsan
When workers shut down we discard the event queue rather than running it to completion. Originally workers managed their event queue themselves and would simply iterate through the array of events and cancel them all. After bug 914762 this was done by setting a (thread-)global "canceling" flag and then calling NS_ProcessPendingEvents. But this neglects that a shut down request can be received while the worker is in a sync queue. In this case, calling NS_ProcessPendingEvents will process any events pending in the sync queue, which is *not* the queue we need to cancel. The fix is, if we are in a sync queue when NotifyInternal is called, to defer clearing the queue until the top-most sync queue is destroyed and we are about to return to the regular event queue. Only then can we call NS_ProcessPendingEvents to clear out the queue. Because we can never process any events from this queue while sync queues are active, the timing of the mass cancellation is unchanged from the perspective of events in the regular queue.
This commit is contained in:
parent
e53fe71370
commit
8ba777d027
@ -575,6 +575,13 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHOD Cancel() override
|
||||
{
|
||||
// We need to run regardless.
|
||||
Run();
|
||||
return WorkerRunnable::Cancel();
|
||||
}
|
||||
|
||||
virtual void
|
||||
PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
|
||||
override
|
||||
@ -1230,6 +1237,13 @@ private:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHOD Cancel() override
|
||||
{
|
||||
// We need to run regardless.
|
||||
Run();
|
||||
return WorkerRunnable::Cancel();
|
||||
}
|
||||
};
|
||||
|
||||
class UpdateRuntimeOptionsRunnable final : public WorkerControlRunnable
|
||||
@ -3823,6 +3837,7 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx,
|
||||
, mRunningExpiredTimeouts(false)
|
||||
, mCloseHandlerStarted(false)
|
||||
, mCloseHandlerFinished(false)
|
||||
, mPendingEventQueueClearing(false)
|
||||
, mMemoryReporterRunning(false)
|
||||
, mBlockedForMemoryReporter(false)
|
||||
, mCancelAllPendingRunnables(false)
|
||||
@ -4651,6 +4666,7 @@ WorkerPrivate::ScheduleDeletion(WorkerRanOrNot aRanOrNot)
|
||||
AssertIsOnWorkerThread();
|
||||
MOZ_ASSERT(mChildWorkers.IsEmpty());
|
||||
MOZ_ASSERT(mSyncLoopStack.IsEmpty());
|
||||
MOZ_ASSERT(!mPendingEventQueueClearing);
|
||||
|
||||
ClearMainEventQueue(aRanOrNot);
|
||||
#ifdef DEBUG
|
||||
@ -4881,6 +4897,7 @@ WorkerPrivate::ClearMainEventQueue(WorkerRanOrNot aRanOrNot)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
MOZ_ASSERT(!mSyncLoopStack.Length());
|
||||
MOZ_ASSERT(!mCancelAllPendingRunnables);
|
||||
mCancelAllPendingRunnables = true;
|
||||
|
||||
@ -5243,6 +5260,11 @@ WorkerPrivate::DestroySyncLoop(uint32_t aLoopIndex, nsIThreadInternal* aThread)
|
||||
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aThread->PopEventQueue(nestedEventTarget)));
|
||||
|
||||
if (!mSyncLoopStack.Length() && mPendingEventQueueClearing) {
|
||||
ClearMainEventQueue(WorkerRan);
|
||||
mPendingEventQueueClearing = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -5509,7 +5531,13 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
||||
// If this is the first time our status has changed then we need to clear the
|
||||
// main event queue.
|
||||
if (previousStatus == Running) {
|
||||
ClearMainEventQueue(WorkerRan);
|
||||
// NB: If we're in a sync loop, we can't clear the queue immediately,
|
||||
// because this is the wrong queue. So we have to defer it until later.
|
||||
if (mSyncLoopStack.Length()) {
|
||||
mPendingEventQueueClearing = true;
|
||||
} else {
|
||||
ClearMainEventQueue(WorkerRan);
|
||||
}
|
||||
}
|
||||
|
||||
// If we've run the close handler, we don't need to do anything else.
|
||||
|
@ -944,6 +944,7 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
||||
bool mRunningExpiredTimeouts;
|
||||
bool mCloseHandlerStarted;
|
||||
bool mCloseHandlerFinished;
|
||||
bool mPendingEventQueueClearing;
|
||||
bool mMemoryReporterRunning;
|
||||
bool mBlockedForMemoryReporter;
|
||||
bool mCancelAllPendingRunnables;
|
||||
|
@ -1,7 +0,0 @@
|
||||
[incoming-message.html]
|
||||
type: testharness
|
||||
disabled:
|
||||
if debug: unstable
|
||||
[close() and incoming message]
|
||||
expected: FAIL
|
||||
|
Loading…
Reference in New Issue
Block a user