Bug 1364624 - Part 1: Manually manage locks in MessageChannel::Close. r=froydnj

This switches over to manually managing the locking in MessageChannel::Close
in order to avoid a deadlock on msvc opt builds. It has the added benefit of
avoid a superfluous lock/unlock pair.

--HG--
extra : rebase_source : f3b0ee5499bd75bc75b3d1fe44c0c7efd3063aee
This commit is contained in:
Eric Rahm 2018-04-26 17:14:22 -07:00
Родитель 031610cc8e
Коммит 4e0fc495d6
1 изменённых файлов: 13 добавлений и 2 удалений

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/Logging.h"
#include "mozilla/Move.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TimeStamp.h"
@ -2696,7 +2697,16 @@ MessageChannel::Close()
AssertWorkerThread();
{
MonitorAutoLock lock(*mMonitor);
// We don't use MonitorAutoLock here as that causes some sort of
// deadlock in the error/timeout-with-a-listener state below when
// compiling an optimized msvc build.
mMonitor->Lock();
// Instead just use a ScopeExit to manage the unlock.
RefPtr<RefCountedMonitor> monitor(mMonitor);
auto exit = MakeScopeExit([m = Move(monitor)] () {
m->Unlock();
});
if (ChannelError == mChannelState || ChannelTimeout == mChannelState) {
// See bug 538586: if the listener gets deleted while the
@ -2705,7 +2715,8 @@ MessageChannel::Close()
// also be deleted and the listener will never be notified
// of the channel error.
if (mListener) {
MonitorAutoUnlock unlock(*mMonitor);
exit.release(); // Explicitly unlocking, clear scope exit.
mMonitor->Unlock();
NotifyMaybeChannelError();
}
return;