зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1132537 - Make WebSocketImpl::Dispatch less racy, r=smaug
This commit is contained in:
Родитель
d8781fab29
Коммит
1c1bceba4d
|
@ -90,6 +90,7 @@ public:
|
|||
, mHasFeatureRegistered(false)
|
||||
#endif
|
||||
, mIsMainThread(true)
|
||||
, mMutex("WebSocketImpl::mMutex")
|
||||
, mWorkerShuttingDown(false)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
|
@ -222,6 +223,9 @@ public:
|
|||
nsWeakPtr mWeakLoadGroup;
|
||||
|
||||
bool mIsMainThread;
|
||||
|
||||
// This mutex protects mWorkerShuttingDown.
|
||||
mozilla::Mutex mMutex;
|
||||
bool mWorkerShuttingDown;
|
||||
|
||||
private:
|
||||
|
@ -422,7 +426,14 @@ public:
|
|||
|
||||
~MaybeDisconnect()
|
||||
{
|
||||
if (mImpl->mWorkerShuttingDown) {
|
||||
bool toDisconnect = false;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mImpl->mMutex);
|
||||
toDisconnect = mImpl->mWorkerShuttingDown;
|
||||
}
|
||||
|
||||
if (toDisconnect) {
|
||||
mImpl->Disconnect();
|
||||
}
|
||||
}
|
||||
|
@ -886,7 +897,7 @@ WebSocket::WebSocket(nsPIDOMWindow* aOwnerWindow)
|
|||
, mCheckMustKeepAlive(true)
|
||||
, mOutgoingBufferedAmount(0)
|
||||
, mBinaryType(dom::BinaryType::Blob)
|
||||
, mMutex("WebSocketImpl::mMutex")
|
||||
, mMutex("WebSocket::mMutex")
|
||||
, mReadyState(CONNECTING)
|
||||
{
|
||||
mImpl = new WebSocketImpl(this);
|
||||
|
@ -1982,7 +1993,11 @@ public:
|
|||
MOZ_ASSERT(aStatus > workers::Running);
|
||||
|
||||
if (aStatus >= Canceling) {
|
||||
mWebSocketImpl->mWorkerShuttingDown = true;
|
||||
{
|
||||
MutexAutoLock lock(mWebSocketImpl->mMutex);
|
||||
mWebSocketImpl->mWorkerShuttingDown = true;
|
||||
}
|
||||
|
||||
mWebSocketImpl->CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
|
||||
}
|
||||
|
||||
|
@ -1991,7 +2006,11 @@ public:
|
|||
|
||||
bool Suspend(JSContext* aCx) MOZ_OVERRIDE
|
||||
{
|
||||
mWebSocketImpl->mWorkerShuttingDown = true;
|
||||
{
|
||||
MutexAutoLock lock(mWebSocketImpl->mMutex);
|
||||
mWebSocketImpl->mWorkerShuttingDown = true;
|
||||
}
|
||||
|
||||
mWebSocketImpl->CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
|
||||
return true;
|
||||
}
|
||||
|
@ -2551,9 +2570,13 @@ namespace {
|
|||
|
||||
class WorkerRunnableDispatcher MOZ_FINAL : public WorkerRunnable
|
||||
{
|
||||
nsRefPtr<WebSocketImpl> mWebSocketImpl;
|
||||
|
||||
public:
|
||||
WorkerRunnableDispatcher(WorkerPrivate* aWorkerPrivate, nsIRunnable* aEvent)
|
||||
WorkerRunnableDispatcher(WebSocketImpl* aImpl, WorkerPrivate* aWorkerPrivate,
|
||||
nsIRunnable* aEvent)
|
||||
: WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
|
||||
, mWebSocketImpl(aImpl)
|
||||
, mEvent(aEvent)
|
||||
{
|
||||
}
|
||||
|
@ -2561,6 +2584,13 @@ public:
|
|||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
// No messages when disconnected.
|
||||
if (mWebSocketImpl->mDisconnectingOrDisconnected) {
|
||||
NS_WARNING("Dispatching a WebSocket event after the disconnection!");
|
||||
return true;
|
||||
}
|
||||
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, true);
|
||||
return !NS_FAILED(mEvent->Run());
|
||||
}
|
||||
|
@ -2596,12 +2626,12 @@ WebSocketImpl::Dispatch(nsIRunnable* aEvent, uint32_t aFlags)
|
|||
return NS_DispatchToMainThread(aEvent);
|
||||
}
|
||||
|
||||
// No messages when disconnected.
|
||||
if (mDisconnectingOrDisconnected) {
|
||||
NS_WARNING("Dispatching a WebSocket event after the disconnection!");
|
||||
return NS_OK;
|
||||
}
|
||||
// If the target is a worker, we have to use a custom WorkerRunnableDispatcher
|
||||
// runnable.
|
||||
nsRefPtr<WorkerRunnableDispatcher> event =
|
||||
new WorkerRunnableDispatcher(this, mWorkerPrivate, aEvent);
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mWorkerShuttingDown) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2612,10 +2642,6 @@ WebSocketImpl::Dispatch(nsIRunnable* aEvent, uint32_t aFlags)
|
|||
MOZ_ASSERT(HasFeatureRegistered());
|
||||
#endif
|
||||
|
||||
// If the target is a worker, we have to use a custom WorkerRunnableDispatcher
|
||||
// runnable.
|
||||
nsRefPtr<WorkerRunnableDispatcher> event =
|
||||
new WorkerRunnableDispatcher(mWorkerPrivate, aEvent);
|
||||
if (!event->Dispatch(nullptr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче