Bug 525792 - 'Fix leaks running mochitests'.

This commit is contained in:
Ben Turner 2009-11-12 14:16:54 -08:00
parent 483fbb36ea
commit 82191b418a
14 changed files with 162 additions and 101 deletions

View File

@ -285,30 +285,33 @@ PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(
bool
PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginScriptableNPObject(
PPluginScriptableObjectChild** value,
NPError* result)
PPluginScriptableObjectChild** aValue,
NPError* aResult)
{
AssertPluginThread();
NPObject* object;
*result = mPluginIface->getvalue(GetNPP(), NPPVpluginScriptableNPObject,
&object);
if (*result != NPERR_NO_ERROR) {
return true;
NPError result = mPluginIface->getvalue(GetNPP(),
NPPVpluginScriptableNPObject,
&object);
if (result == NPERR_NO_ERROR && object) {
PluginScriptableObjectChild* actor = GetActorForNPObject(object);
// If we get an actor then it has retained. Otherwise we don't need it
// any longer.
PluginModuleChild::sBrowserFuncs.releaseobject(object);
if (actor) {
*aValue = actor;
*aResult = NPERR_NO_ERROR;
return true;
}
NS_ERROR("Failed to get actor!");
result = NPERR_GENERIC_ERROR;
}
PluginScriptableObjectChild* actor = GetActorForNPObject(object);
// If we get an actor then it has retained. Otherwise we don't need it any
// longer.
PluginModuleChild::sBrowserFuncs.releaseobject(object);
if (!actor) {
*result = NPERR_GENERIC_ERROR;
return true;
}
*value = actor;
*aValue = nsnull;
*aResult = result;
return true;
}

View File

@ -164,34 +164,23 @@ PluginInstanceParent::InternalGetValueForNPObject(
{
NPObject* npobject;
NPError result = mNPNIface->getvalue(mNPP, aVariable, (void*)&npobject);
if (result != NPERR_NO_ERROR || !npobject) {
*aValue = nsnull;
*aResult = result;
return true;
}
if (result == NPERR_NO_ERROR) {
NS_ASSERTION(npobject, "Shouldn't return null and NPERR_NO_ERROR!");
PluginScriptableObjectParent* actor =
static_cast<PluginScriptableObjectParent*>(
AllocPPluginScriptableObject());
if (!actor) {
PluginScriptableObjectParent* actor = GetActorForNPObject(npobject);
mNPNIface->releaseobject(npobject);
*aValue = nsnull;
*aResult = NPERR_OUT_OF_MEMORY_ERROR;
return true;
if (actor) {
*aValue = actor;
*aResult = NPERR_NO_ERROR;
return true;
}
NS_ERROR("Failed to get actor!");
result = NPERR_GENERIC_ERROR;
}
if (!CallPPluginScriptableObjectConstructor(actor)) {
mNPNIface->releaseobject(npobject);
DeallocPPluginScriptableObject(actor);
*aValue = nsnull;
*aResult = NPERR_GENERIC_ERROR;
return true;
}
actor->Initialize(const_cast<PluginInstanceParent*>(this), npobject);
*aValue = actor;
*aResult = NPERR_NO_ERROR;
*aValue = nsnull;
*aResult = result;
return true;
}

View File

@ -45,6 +45,7 @@
#include "nsILocalFile.h"
#include "pratom.h"
#include "nsDebug.h"
#include "nsCOMPtr.h"
#include "nsPluginsDir.h"
@ -238,13 +239,42 @@ PluginModuleChild::GetActorForNPObject(NPObject* aObject)
}
#ifdef DEBUG
namespace {
struct SearchInfo {
PluginScriptableObjectChild* target;
bool found;
};
PLDHashOperator
ActorSearch(const void* aKey,
PluginScriptableObjectChild* aData,
void* aUserData)
{
SearchInfo* info = reinterpret_cast<SearchInfo*>(aUserData);
NS_ASSERTION(info->target && ! info->found, "Bad info ptr!");
if (aData == info->target) {
info->found = true;
return PL_DHASH_STOP;
}
return PL_DHASH_NEXT;
}
} // anonymous namespace
bool
PluginModuleChild::NPObjectIsRegistered(NPObject* aObject)
PluginModuleChild::NPObjectIsRegisteredForActor(
PluginScriptableObjectChild* aActor)
{
AssertPluginThread();
NS_ASSERTION(mObjectMap.IsInitialized(), "Not initialized!");
NS_ASSERTION(aObject, "Null pointer!");
return mObjectMap.Get(aObject, nsnull);
NS_ASSERTION(aActor, "Null actor!");
SearchInfo info = { aActor, false };
mObjectMap.EnumerateRead(ActorSearch, &info);
return info.found;
}
#endif
@ -902,6 +932,7 @@ _createobject(NPP aNPP,
if (newObject) {
newObject->_class = aClass;
newObject->referenceCount = 1;
NS_LOG_ADDREF(newObject, 1, "ChildNPObject", sizeof(NPObject));
}
return newObject;
}
@ -915,7 +946,9 @@ _retainobject(NPObject* aNPObj)
printf("[PluginModuleChild] %s: object %p, refcnt %d\n", __FUNCTION__,
aNPObj, aNPObj->referenceCount + 1);
#endif
++aNPObj->referenceCount;
int32_t refCnt = PR_AtomicIncrement((PRInt32*)&aNPObj->referenceCount);
NS_LOG_ADDREF(aNPObj, refCnt, "ChildNPObject", sizeof(NPObject));
return aNPObj;
}
@ -928,7 +961,10 @@ _releaseobject(NPObject* aNPObj)
printf("[PluginModuleChild] %s: object %p, refcnt %d\n", __FUNCTION__,
aNPObj, aNPObj->referenceCount - 1);
#endif
if (--aNPObj->referenceCount == 0) {
int32_t refCnt = PR_AtomicDecrement((PRInt32*)&aNPObj->referenceCount);
NS_LOG_RELEASE(aNPObj, refCnt, "ChildNPObject");
if (refCnt == 0) {
if (aNPObj->_class && aNPObj->_class->deallocate) {
aNPObj->_class->deallocate(aNPObj);
} else {

View File

@ -149,7 +149,7 @@ public:
PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
#ifdef DEBUG
bool NPObjectIsRegistered(NPObject* aObject);
bool NPObjectIsRegisteredForActor(PluginScriptableObjectChild* aActor);
#endif
private:

View File

@ -653,9 +653,10 @@ PluginScriptableObjectChild::~PluginScriptableObjectChild()
else {
PluginModuleChild::sBrowserFuncs.releaseobject(mObject);
}
NS_ASSERTION(!PluginModuleChild::current()->NPObjectIsRegistered(mObject),
"NPObject still registered!");
}
NS_ASSERTION(!PluginModuleChild::current()->
NPObjectIsRegisteredForActor(this),
"NPObjects still registered for this actor!");
}
void
@ -677,6 +678,7 @@ PluginScriptableObjectChild::Initialize(PluginInstanceChild* aInstance,
// dies we will send the destructor message to the parent.
NS_ASSERTION(aObject->referenceCount == 1, "Some kind of live object!");
aObject->referenceCount = 0;
NS_LOG_RELEASE(aObject, 0, "ChildNPObject");
}
else {
// Plugin-provided object, retain here. This should be the only reference we

View File

@ -786,6 +786,7 @@ PluginScriptableObjectParent::Initialize(PluginInstanceParent* aInstance,
// dies we will send the destructor message to the child.
NS_ASSERTION(aObject->referenceCount == 1, "Some kind of live object!");
object->referenceCount = 0;
NS_LOG_RELEASE(aObject, 0, "BrowserNPObject");
}
else {
aInstance->GetNPNIface()->retainobject(aObject);
@ -800,9 +801,6 @@ PluginScriptableObjectParent::AnswerInvalidate()
{
if (mObject) {
NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
if (mObject->_class && mObject->_class->invalidate) {
mObject->_class->invalidate(mObject);
}
const NPNetscapeFuncs* npn = GetNetscapeFuncs(GetInstance());
if (npn) {
npn->releaseobject(mObject);

View File

@ -55,6 +55,28 @@ struct RunnableMethodTraits<mozilla::ipc::AsyncChannel>
namespace mozilla {
namespace ipc {
AsyncChannel::AsyncChannel(AsyncListener* aListener)
: mTransport(0),
mListener(aListener),
mChannelState(ChannelClosed),
mMutex("mozilla.ipc.AsyncChannel.mMutex"),
mCvar(mMutex, "mozilla.ipc.AsyncChannel.mCvar"),
mIOLoop(),
mWorkerLoop()
{
MOZ_COUNT_CTOR(AsyncChannel);
}
AsyncChannel::~AsyncChannel()
{
MOZ_COUNT_DTOR(AsyncChannel);
if (!mChild && mTransport)
Close();
// we only hold a weak ref to the transport, which is "owned"
// by GeckoChildProcess/GeckoThread
mTransport = 0;
}
bool
AsyncChannel::Open(Transport* aTransport, MessageLoop* aIOLoop)
{

View File

@ -90,25 +90,8 @@ public:
};
public:
AsyncChannel(AsyncListener* aListener) :
mTransport(0),
mListener(aListener),
mChannelState(ChannelClosed),
mMutex("mozilla.ipc.AsyncChannel.mMutex"),
mCvar(mMutex, "mozilla.ipc.AsyncChannel.mCvar"),
mIOLoop(),
mWorkerLoop()
{
}
virtual ~AsyncChannel()
{
if (!mChild && mTransport)
Close();
// we only hold a weak ref to the transport, which is "owned"
// by GeckoChildProcess/GeckoThread
mTransport = 0;
}
AsyncChannel(AsyncListener* aListener);
virtual ~AsyncChannel();
// Open from the perspective of the transport layer; the underlying
// socketpair/pipe should already be created.

View File

@ -61,6 +61,24 @@ struct RunnableMethodTraits<mozilla::ipc::RPCChannel>
namespace mozilla {
namespace ipc {
RPCChannel::RPCChannel(RPCListener* aListener,
RacyRPCPolicy aPolicy)
: SyncChannel(aListener),
mPending(),
mStack(),
mDeferred(),
mRemoteStackDepthGuess(0),
mRacePolicy(aPolicy)
{
MOZ_COUNT_CTOR(RPCChannel);
}
RPCChannel::~RPCChannel()
{
MOZ_COUNT_DTOR(RPCChannel);
// FIXME/cjones: impl
}
bool
RPCChannel::Call(Message* msg, Message* reply)
{

View File

@ -71,20 +71,9 @@ public:
RRPParentWins
};
RPCChannel(RPCListener* aListener, RacyRPCPolicy aPolicy=RRPChildWins) :
SyncChannel(aListener),
mPending(),
mStack(),
mDeferred(),
mRemoteStackDepthGuess(0),
mRacePolicy(aPolicy)
{
}
RPCChannel(RPCListener* aListener, RacyRPCPolicy aPolicy=RRPChildWins);
virtual ~RPCChannel()
{
// FIXME/cjones: impl
}
virtual ~RPCChannel();
// Make an RPC to the other side of the channel
bool Call(Message* msg, Message* reply);

View File

@ -60,6 +60,24 @@ struct RunnableMethodTraits<mozilla::ipc::SyncChannel>
namespace mozilla {
namespace ipc {
SyncChannel::SyncChannel(SyncListener* aListener)
: AsyncChannel(aListener),
mPendingReply(0),
mProcessingSyncMessage(false)
#ifdef OS_WIN
, mUIThreadId(0)
, mEventLoopDepth(0)
#endif
{
MOZ_COUNT_CTOR(SyncChannel);
}
SyncChannel::~SyncChannel()
{
MOZ_COUNT_DTOR(SyncChannel);
// FIXME/cjones: impl
}
bool
SyncChannel::Send(Message* msg, Message* reply)
{

View File

@ -62,21 +62,8 @@ public:
Message*& aReply) = 0;
};
SyncChannel(SyncListener* aListener) :
AsyncChannel(aListener),
mPendingReply(0),
mProcessingSyncMessage(false)
#ifdef OS_WIN
, mUIThreadId(0)
, mEventLoopDepth(0)
#endif
{
}
virtual ~SyncChannel()
{
// FIXME/cjones: impl
}
SyncChannel(SyncListener* aListener);
virtual ~SyncChannel();
bool Send(Message* msg) {
return AsyncChannel::Send(msg);

View File

@ -488,11 +488,14 @@ ReportExceptionIfPending(JSContext *cx)
nsJSObjWrapper::nsJSObjWrapper(NPP npp)
: nsJSObjWrapperKey(nsnull, npp)
{
MOZ_COUNT_CTOR(nsJSObjWrapper);
OnWrapperCreated();
}
nsJSObjWrapper::~nsJSObjWrapper()
{
MOZ_COUNT_DTOR(nsJSObjWrapper);
// Invalidate first, since it relies on sJSRuntime and sJSObjWrappers.
NP_Invalidate(this);
@ -1856,6 +1859,16 @@ NPObjWrapperPluginDestroyedCallback(PLDHashTable *table, PLDHashEntryHdr *hdr,
npobj->_class->invalidate(npobj);
}
#ifdef NS_BUILD_REFCNT_LOGGING
{
int32_t refCnt = npobj->referenceCount;
while (refCnt) {
--refCnt;
NS_LOG_RELEASE(npobj, refCnt, "BrowserNPObject");
}
}
#endif
// Force deallocation of plugin objects since the plugin they came
// from is being torn down.
if (npobj->_class && npobj->_class->deallocate) {

View File

@ -1399,6 +1399,7 @@ _createobject(NPP npp, NPClass* aClass)
if (npobj) {
npobj->_class = aClass;
npobj->referenceCount = 1;
NS_LOG_ADDREF(npobj, 1, "BrowserNPObject", sizeof(NPObject));
}
NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
@ -1414,7 +1415,8 @@ _retainobject(NPObject* npobj)
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_retainobject called from the wrong thread\n"));
}
if (npobj) {
PR_AtomicIncrement((PRInt32*)&npobj->referenceCount);
int32_t refCnt = PR_AtomicIncrement((PRInt32*)&npobj->referenceCount);
NS_LOG_ADDREF(npobj, refCnt, "BrowserNPObject", sizeof(NPObject));
}
return npobj;
@ -1430,6 +1432,7 @@ _releaseobject(NPObject* npobj)
return;
int32_t refCnt = PR_AtomicDecrement((PRInt32*)&npobj->referenceCount);
NS_LOG_RELEASE(npobj, refCnt, "BrowserNPObject");
if (refCnt == 0) {
nsNPObjWrapper::OnDestroy(npobj);