From 8fcee6d0e5d50164a4e5090771f18529bcfb744a Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Thu, 9 Sep 2004 22:57:24 +0000 Subject: [PATCH] working around broken usage of XPCOM for bug 256911 "bind lifetime of child stubs to that of the master stub" (based on similar patch by Javier Pedemonte for nsJavaXPTCStub.cpp) git-svn-id: svn://10.0.0.236/trunk@162028 18797224-902f-48f8-a5cc-f745e15eee43 --- .../dconnect/src/ipcDConnectService.cpp | 62 ++++++++++++++++--- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/mozilla/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp b/mozilla/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp index 0006edebd3e..169b3e58194 100644 --- a/mozilla/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp +++ b/mozilla/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp @@ -909,10 +909,11 @@ DConnectStub::~DConnectStub() if (NS_FAILED(rv)) NS_WARNING("failed to send RELEASE event"); - if (mMaster) + if (!mMaster) { - mMaster->mChildren.RemoveElement(this); - NS_RELEASE(mMaster); + // delete each child stub + for (PRInt32 i=0; iAddRef(); + + NS_ASSERT_OWNINGTHREAD("DConnectStub"); + ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "DConnectStub", sizeof(*this)); + return mRefCnt; +} + +NS_IMETHODIMP_(nsrefcnt) +DConnectStub::Release() +{ + if (mMaster) + return mMaster->Release(); + + NS_ASSERT_OWNINGTHREAD("DConnectStub"); + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "DConnectStub"); + if (mRefCnt == 0) + { + mRefCnt = 1; /* stabilize */ + delete this; + return 0; + } \ + return mRefCnt; +} NS_IMETHODIMP DConnectStub::QueryInterface(const nsID &aIID, void **aInstancePtr) @@ -1015,10 +1043,26 @@ DConnectStub::QueryInterface(const nsID &aIID, void **aInstancePtr) stub = (DConnectStub *) result; // add stub to the master's list of children, so we can preserve - // symmetry in future QI calls. each child owns his master, but - // the master only keeps weak references to its children. the - // children are responsible for removing themselves as they die. - NS_ADDREF(master); + // symmetry in future QI calls. the master will delete each child + // when it is destroyed. the refcount of each child is bound to + // the refcount of the master. this is done to deal with code + // like this: + // + // nsCOMPtr bar = ...; + // nsIFoo *foo; + // { + // nsCOMPtr temp = do_QueryInterface(bar); + // foo = temp; + // } + // foo->DoStuff(); + // + // while this code is not valid XPCOM (since it is using |foo| + // after having called Release on it), such code is unfortunately + // very common in the mozilla codebase. the assumption this code + // is making is that so long as |bar| is alive, it should be valid + // to access |foo| even if the code doesn't own a strong reference + // to |foo|! clearly wrong, but we need to support it anyways. + stub->mMaster = master; master->mChildren.AppendElement(stub);