Bug 1875528 - Part 1: Make IProtocol hold a strong reference to manager, r=ipc-reviewers,mccr8

This makes accessing `Manager()` on an IPDL protocol safer, and replaces the
previous ActorLifecycleProxy reference, which would only keep the manager alive
until IPDL drops its reference.

Unfortunately this introduces some leaks due to reference cycles, which will be
fixed in follow-up parts.

Differential Revision: https://phabricator.services.mozilla.com/D198624
This commit is contained in:
Nika Layzell 2024-01-24 20:54:40 +00:00
Родитель b50a4036ee
Коммит 3c0d6b5c0b
5 изменённых файлов: 16 добавлений и 22 удалений

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

@ -24,7 +24,9 @@ class AccShowEvent;
*/
class DocAccessibleChild : public PDocAccessibleChild {
public:
DocAccessibleChild(DocAccessible* aDoc, IProtocol* aManager) : mDoc(aDoc) {
DocAccessibleChild(DocAccessible* aDoc,
mozilla::ipc::IRefCountedProtocol* aManager)
: mDoc(aDoc) {
MOZ_COUNT_CTOR(DocAccessibleChild);
SetManager(aManager);
}

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

@ -57,7 +57,7 @@ UntypedManagedEndpoint::~UntypedManagedEndpoint() {
}
bool UntypedManagedEndpoint::BindCommon(IProtocol* aActor,
IProtocol* aManager) {
IRefCountedProtocol* aManager) {
MOZ_ASSERT(aManager);
if (!mInner) {
NS_WARNING("Cannot bind to invalid endpoint");

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

@ -214,7 +214,7 @@ class UntypedManagedEndpoint {
~UntypedManagedEndpoint() noexcept;
bool BindCommon(IProtocol* aActor, IProtocol* aManager);
bool BindCommon(IProtocol* aActor, IRefCountedProtocol* aManager);
private:
friend struct IPDLParamTraits<UntypedManagedEndpoint>;
@ -267,7 +267,8 @@ class ManagedEndpoint : public UntypedManagedEndpoint {
ManagedEndpoint(const PrivateIPDLInterface&, IProtocol* aActor)
: UntypedManagedEndpoint(aActor) {}
bool Bind(const PrivateIPDLInterface&, PFooSide* aActor, IProtocol* aManager,
bool Bind(const PrivateIPDLInterface&, PFooSide* aActor,
IRefCountedProtocol* aManager,
ManagedContainer<PFooSide>& aContainer) {
if (!BindCommon(aActor, aManager)) {
return false;

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

@ -257,12 +257,6 @@ ActorLifecycleProxy::ActorLifecycleProxy(IProtocol* aActor) : mActor(aActor) {
MOZ_ASSERT(mActor->CanSend(),
"Cannot create LifecycleProxy for non-connected actor!");
// Take a reference to our manager's lifecycle proxy to try to hold it &
// ensure it doesn't die before us.
if (mActor->mManager) {
mManager = mActor->mManager->mLifecycleProxy;
}
// Record that we've taken our first reference to our actor.
mActor->ActorAlloc();
}
@ -493,13 +487,13 @@ bool IProtocol::DeallocShmem(Shmem& aMem) {
return ok;
}
void IProtocol::SetManager(IProtocol* aManager) {
void IProtocol::SetManager(IRefCountedProtocol* aManager) {
MOZ_RELEASE_ASSERT(!mManager || mManager == aManager);
mManager = aManager;
mToplevel = aManager->mToplevel;
}
void IProtocol::SetManagerAndRegister(IProtocol* aManager) {
void IProtocol::SetManagerAndRegister(IRefCountedProtocol* aManager) {
// Set the manager prior to registering so registering properly inherits
// the manager's event target.
SetManager(aManager);
@ -507,7 +501,8 @@ void IProtocol::SetManagerAndRegister(IProtocol* aManager) {
aManager->Register(this);
}
void IProtocol::SetManagerAndRegister(IProtocol* aManager, int32_t aId) {
void IProtocol::SetManagerAndRegister(IRefCountedProtocol* aManager,
int32_t aId) {
// Set the manager prior to registering so registering properly inherits
// the manager's event target.
SetManager(aManager);

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

@ -215,7 +215,7 @@ class IProtocol : public HasResultCodes {
const char* GetProtocolName() const { return ProtocolIdToName(mProtocolId); }
int32_t Id() const { return mId; }
IProtocol* Manager() const { return mManager; }
IRefCountedProtocol* Manager() const { return mManager; }
ActorLifecycleProxy* GetLifecycleProxy() { return mLifecycleProxy; }
WeakActorLifecycleProxy* GetWeakLifecycleProxy();
@ -259,13 +259,13 @@ class IProtocol : public HasResultCodes {
// We have separate functions because the accessibility code manually
// calls SetManager.
void SetManager(IProtocol* aManager);
void SetManager(IRefCountedProtocol* aManager);
// Sets the manager for the protocol and registers the protocol with
// its manager, setting up channels for the protocol as well. Not
// for use outside of IPDL.
void SetManagerAndRegister(IProtocol* aManager);
void SetManagerAndRegister(IProtocol* aManager, int32_t aId);
void SetManagerAndRegister(IRefCountedProtocol* aManager);
void SetManagerAndRegister(IRefCountedProtocol* aManager, int32_t aId);
// Helpers for calling `Send` on our underlying IPC channel.
bool ChannelSend(UniquePtr<IPC::Message> aMsg);
@ -333,7 +333,7 @@ class IProtocol : public HasResultCodes {
Side mSide;
LinkStatus mLinkStatus;
ActorLifecycleProxy* mLifecycleProxy;
IProtocol* mManager;
RefPtr<IRefCountedProtocol> mManager;
IToplevelProtocol* mToplevel;
};
@ -666,10 +666,6 @@ class ActorLifecycleProxy {
IProtocol* MOZ_NON_OWNING_REF mActor;
// Hold a reference to the actor's manager's ActorLifecycleProxy to help
// prevent it from dying while we're still alive!
RefPtr<ActorLifecycleProxy> mManager;
// When requested, the current self-referencing weak reference for this
// ActorLifecycleProxy.
RefPtr<WeakActorLifecycleProxy> mWeakProxy;