mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1121676 - Use a lock to protect the list of top-level actors (r=bent)
This commit is contained in:
parent
8fb0643e63
commit
5389443ac0
@ -551,19 +551,20 @@ InitOnContentProcessCreated()
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
static void
|
||||
ResetTransports(void* aUnused) {
|
||||
ResetTransports(void* aUnused)
|
||||
{
|
||||
ContentChild* child = ContentChild::GetSingleton();
|
||||
mozilla::ipc::Transport* transport = child->GetTransport();
|
||||
int fd = transport->GetFileDescriptor();
|
||||
transport->ResetFileDescriptor(fd);
|
||||
|
||||
IToplevelProtocol* toplevel = child->GetFirstOpenedActors();
|
||||
while (toplevel != nullptr) {
|
||||
nsTArray<IToplevelProtocol*> actors;
|
||||
child->GetOpenedActors(actors);
|
||||
for (size_t i = 0; i < actors.Length(); i++) {
|
||||
IToplevelProtocol* toplevel = actors[i];
|
||||
transport = toplevel->GetTransport();
|
||||
fd = transport->GetFileDescriptor();
|
||||
transport->ResetFileDescriptor(fd);
|
||||
|
||||
toplevel = toplevel->getNext();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -2677,9 +2678,10 @@ GetProtoFdInfos(NuwaProtoFdInfo* aInfoList,
|
||||
content->GetTransport()->GetFileDescriptor();
|
||||
i++;
|
||||
|
||||
for (IToplevelProtocol* actor = content->GetFirstOpenedActors();
|
||||
actor != nullptr;
|
||||
actor = actor->getNext()) {
|
||||
IToplevelProtocol* actors[NUWA_TOPLEVEL_MAX];
|
||||
size_t count = content->GetOpenedActorsUnsafe(actors, ArrayLength(actors));
|
||||
for (size_t j = 0; j < count; j++) {
|
||||
IToplevelProtocol* actor = actors[j];
|
||||
if (i >= aInfoListSize) {
|
||||
NS_RUNTIMEABORT("Too many top level protocols!");
|
||||
}
|
||||
|
@ -21,19 +21,56 @@ using base::ProcessId;
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
#ifdef MOZ_IPDL_TESTS
|
||||
bool IToplevelProtocol::sAllowNonMainThreadUse;
|
||||
#endif
|
||||
static Atomic<size_t> gNumProtocols;
|
||||
static StaticAutoPtr<Mutex> gProtocolMutex;
|
||||
|
||||
IToplevelProtocol::IToplevelProtocol(ProtocolId aProtoId)
|
||||
: mOpener(nullptr)
|
||||
, mProtocolId(aProtoId)
|
||||
, mTrans(nullptr)
|
||||
{
|
||||
size_t old = gNumProtocols++;
|
||||
|
||||
if (!old) {
|
||||
// We assume that two threads never race to create the first protocol. This
|
||||
// assertion is sufficient to ensure that.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
gProtocolMutex = new Mutex("ITopLevelProtocol::ProtocolMutex");
|
||||
}
|
||||
}
|
||||
|
||||
IToplevelProtocol::~IToplevelProtocol()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread() || AllowNonMainThreadUse());
|
||||
mOpenActors.clear();
|
||||
bool last = false;
|
||||
|
||||
{
|
||||
MutexAutoLock al(*gProtocolMutex);
|
||||
|
||||
for (IToplevelProtocol* actor = mOpenActors.getFirst();
|
||||
actor;
|
||||
actor = actor->getNext()) {
|
||||
actor->mOpener = nullptr;
|
||||
}
|
||||
|
||||
void IToplevelProtocol::AddOpenedActor(IToplevelProtocol* aActor)
|
||||
mOpenActors.clear();
|
||||
|
||||
if (mOpener) {
|
||||
removeFrom(mOpener->mOpenActors);
|
||||
}
|
||||
|
||||
gNumProtocols--;
|
||||
last = gNumProtocols == 0;
|
||||
}
|
||||
|
||||
if (last) {
|
||||
gProtocolMutex = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IToplevelProtocol::AddOpenedActorLocked(IToplevelProtocol* aActor)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread() || AllowNonMainThreadUse());
|
||||
gProtocolMutex->AssertCurrentThreadOwns();
|
||||
|
||||
#ifdef DEBUG
|
||||
for (const IToplevelProtocol* actor = mOpenActors.getFirst();
|
||||
@ -44,9 +81,49 @@ void IToplevelProtocol::AddOpenedActor(IToplevelProtocol* aActor)
|
||||
}
|
||||
#endif
|
||||
|
||||
aActor->mOpener = this;
|
||||
mOpenActors.insertBack(aActor);
|
||||
}
|
||||
|
||||
void
|
||||
IToplevelProtocol::AddOpenedActor(IToplevelProtocol* aActor)
|
||||
{
|
||||
MutexAutoLock al(*gProtocolMutex);
|
||||
AddOpenedActorLocked(aActor);
|
||||
}
|
||||
|
||||
void
|
||||
IToplevelProtocol::GetOpenedActorsLocked(nsTArray<IToplevelProtocol*>& aActors)
|
||||
{
|
||||
gProtocolMutex->AssertCurrentThreadOwns();
|
||||
|
||||
for (IToplevelProtocol* actor = mOpenActors.getFirst();
|
||||
actor;
|
||||
actor = actor->getNext()) {
|
||||
aActors.AppendElement(actor);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IToplevelProtocol::GetOpenedActors(nsTArray<IToplevelProtocol*>& aActors)
|
||||
{
|
||||
MutexAutoLock al(*gProtocolMutex);
|
||||
GetOpenedActorsLocked(aActors);
|
||||
}
|
||||
|
||||
size_t
|
||||
IToplevelProtocol::GetOpenedActorsUnsafe(IToplevelProtocol** aActors, size_t aActorsMax)
|
||||
{
|
||||
size_t count = 0;
|
||||
for (IToplevelProtocol* actor = mOpenActors.getFirst();
|
||||
actor;
|
||||
actor = actor->getNext()) {
|
||||
MOZ_RELEASE_ASSERT(count < aActorsMax);
|
||||
aActors[count++] = actor;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
IToplevelProtocol*
|
||||
IToplevelProtocol::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
|
||||
base::ProcessHandle aPeerProcess,
|
||||
@ -62,21 +139,16 @@ IToplevelProtocol::CloneOpenedToplevels(IToplevelProtocol* aTemplate,
|
||||
base::ProcessHandle aPeerProcess,
|
||||
ProtocolCloneContext* aCtx)
|
||||
{
|
||||
for (IToplevelProtocol* actor = aTemplate->GetFirstOpenedActors();
|
||||
actor;
|
||||
actor = actor->getNext()) {
|
||||
IToplevelProtocol* newactor = actor->CloneToplevel(aFds, aPeerProcess, aCtx);
|
||||
AddOpenedActor(newactor);
|
||||
}
|
||||
}
|
||||
MutexAutoLock al(*gProtocolMutex);
|
||||
|
||||
#ifdef MOZ_IPDL_TESTS
|
||||
void
|
||||
IToplevelProtocol::SetAllowNonMainThreadUse()
|
||||
{
|
||||
sAllowNonMainThreadUse = true;
|
||||
nsTArray<IToplevelProtocol*> actors;
|
||||
aTemplate->GetOpenedActorsLocked(actors);
|
||||
|
||||
for (size_t i = 0; i < actors.Length(); i++) {
|
||||
IToplevelProtocol* newactor = actors[i]->CloneToplevel(aFds, aPeerProcess, aCtx);
|
||||
AddOpenedActorLocked(newactor);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
class ChannelOpened : public IPC::Message
|
||||
{
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
#include "mozilla/ipc/MessageLink.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "MainThreadUtils.h"
|
||||
|
||||
#if defined(ANDROID) && defined(DEBUG)
|
||||
@ -181,16 +182,13 @@ public:
|
||||
* IToplevelProtocol tracks all top-level protocol actors created from
|
||||
* this protocol actor.
|
||||
*/
|
||||
class IToplevelProtocol : public LinkedListElement<IToplevelProtocol>
|
||||
class IToplevelProtocol : private LinkedListElement<IToplevelProtocol>
|
||||
{
|
||||
protected:
|
||||
explicit IToplevelProtocol(ProtocolId aProtoId)
|
||||
: mProtocolId(aProtoId)
|
||||
, mTrans(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread() || AllowNonMainThreadUse());
|
||||
}
|
||||
friend class LinkedList<IToplevelProtocol>;
|
||||
friend class LinkedListElement<IToplevelProtocol>;
|
||||
|
||||
protected:
|
||||
explicit IToplevelProtocol(ProtocolId aProtoId);
|
||||
~IToplevelProtocol();
|
||||
|
||||
/**
|
||||
@ -209,19 +207,13 @@ public:
|
||||
|
||||
ProtocolId GetProtocolId() const { return mProtocolId; }
|
||||
|
||||
/**
|
||||
* Return first of actors of top level protocols opened by this one.
|
||||
*/
|
||||
IToplevelProtocol* GetFirstOpenedActors()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread() || AllowNonMainThreadUse());
|
||||
return mOpenActors.getFirst();
|
||||
}
|
||||
const IToplevelProtocol* GetFirstOpenedActors() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread() || AllowNonMainThreadUse());
|
||||
return mOpenActors.getFirst();
|
||||
}
|
||||
void GetOpenedActors(nsTArray<IToplevelProtocol*>& aActors);
|
||||
|
||||
// This Unsafe version should only be used when all other threads are
|
||||
// frozen, since it performs no locking. It also takes a stack-allocated
|
||||
// array and its size (number of elements) rather than an nsTArray. The Nuwa
|
||||
// code that calls this function is not allowed to allocate memory.
|
||||
size_t GetOpenedActorsUnsafe(IToplevelProtocol** aActors, size_t aActorsMax);
|
||||
|
||||
virtual IToplevelProtocol*
|
||||
CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
|
||||
@ -233,27 +225,15 @@ public:
|
||||
base::ProcessHandle aPeerProcess,
|
||||
ProtocolCloneContext* aCtx);
|
||||
|
||||
#ifdef MOZ_IPDL_TESTS
|
||||
static void SetAllowNonMainThreadUse();
|
||||
#endif
|
||||
|
||||
static bool AllowNonMainThreadUse() {
|
||||
#ifdef MOZ_IPDL_TESTS
|
||||
return sAllowNonMainThreadUse;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
void AddOpenedActorLocked(IToplevelProtocol* aActor);
|
||||
void GetOpenedActorsLocked(nsTArray<IToplevelProtocol*>& aActors);
|
||||
|
||||
LinkedList<IToplevelProtocol> mOpenActors; // All protocol actors opened by this.
|
||||
IToplevelProtocol* mOpener;
|
||||
|
||||
ProtocolId mProtocolId;
|
||||
Transport* mTrans;
|
||||
|
||||
#ifdef MOZ_IPDL_TESTS
|
||||
static bool sAllowNonMainThreadUse;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -139,10 +139,6 @@ IPDLUnitTestMain(void* aData)
|
||||
{
|
||||
char* testString = reinterpret_cast<char*>(aData);
|
||||
|
||||
// Some tests require this, and we don't care what thread we're on if we're
|
||||
// not using Nuwa.
|
||||
mozilla::ipc::IToplevelProtocol::SetAllowNonMainThreadUse();
|
||||
|
||||
// Check if we are to run the test using threads instead:
|
||||
const char *prefix = "thread:";
|
||||
const int prefixLen = strlen(prefix);
|
||||
@ -378,10 +374,6 @@ IPDLUnitTestChildInit(IPC::Channel* transport,
|
||||
base::ProcessHandle parent,
|
||||
MessageLoop* worker)
|
||||
{
|
||||
// Some tests require this, and we don't care what thread we're on if we're
|
||||
// not using Nuwa.
|
||||
mozilla::ipc::IToplevelProtocol::SetAllowNonMainThreadUse();
|
||||
|
||||
switch (IPDLUnitTest()) {
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
|
@ -867,7 +867,7 @@ class B2GOptions(MochitestOptions):
|
||||
defaults["testPath"] = ""
|
||||
defaults["extensionsToExclude"] = ["specialpowers"]
|
||||
# See dependencies of bug 1038943.
|
||||
defaults["defaultLeakThreshold"] = 5404
|
||||
defaults["defaultLeakThreshold"] = 5536
|
||||
self.set_defaults(**defaults)
|
||||
|
||||
def verifyRemoteOptions(self, options):
|
||||
|
Loading…
Reference in New Issue
Block a user