mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 525792 - 'Fix leaks running mochitests'.
This commit is contained in:
parent
483fbb36ea
commit
82191b418a
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -149,7 +149,7 @@ public:
|
||||
PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
|
||||
|
||||
#ifdef DEBUG
|
||||
bool NPObjectIsRegistered(NPObject* aObject);
|
||||
bool NPObjectIsRegisteredForActor(PluginScriptableObjectChild* aActor);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user