mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
Cleanup at shutdown the JSContexts that xpconnect manages on a per thread basis. This should fix some shutdown leaks.
This commit is contained in:
parent
d4388bb67f
commit
35d002f3fe
@ -176,6 +176,13 @@ nsXPConnect::nsXPConnect()
|
||||
|
||||
nsXPConnect::~nsXPConnect()
|
||||
{
|
||||
// Calling this Cleanup *before* doing the ShutDown stuff below is
|
||||
// fairly aggressive. There is some danger that we could get into trouble
|
||||
// With reentrancy into the xpconnect runtime as we are in the process of
|
||||
// kiling it. But, this seems to be working. This call could be moved lower
|
||||
// in this dtor (or commented out!) if problems develop.
|
||||
xpcPerThreadData::CleanupAllThreads();
|
||||
|
||||
NS_IF_RELEASE(mArbitraryScriptable);
|
||||
NS_IF_RELEASE(mInterfaceInfoManager);
|
||||
NS_IF_RELEASE(mContextStack);
|
||||
|
@ -1348,8 +1348,8 @@ class xpcPerThreadData
|
||||
public:
|
||||
// Get the instance of this object for the current thread
|
||||
static xpcPerThreadData* GetData();
|
||||
static void CleanupAllThreads();
|
||||
|
||||
xpcPerThreadData();
|
||||
~xpcPerThreadData();
|
||||
|
||||
nsIXPCException* GetException();
|
||||
@ -1360,10 +1360,21 @@ public:
|
||||
|
||||
PRBool IsValid() const;
|
||||
|
||||
void Cleanup();
|
||||
|
||||
private:
|
||||
nsIXPCException* mException;
|
||||
nsDeque* mJSContextStack;
|
||||
JSContext* mSafeJSContext;
|
||||
xpcPerThreadData();
|
||||
|
||||
private:
|
||||
nsIXPCException* mException;
|
||||
nsDeque* mJSContextStack;
|
||||
JSContext* mSafeJSContext;
|
||||
xpcPerThreadData* mNextThread;
|
||||
|
||||
static PRLock* gLock;
|
||||
static xpcPerThreadData* gThreads;
|
||||
static PRUintn gTLSIndex;
|
||||
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
@ -1464,10 +1475,6 @@ extern JSBool
|
||||
xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt);
|
||||
|
||||
/***************************************************************************/
|
||||
// the include of declarations of the maps comes last because they have
|
||||
// inlines which call methods on classes above.
|
||||
|
||||
#include "xpcmaps.h"
|
||||
|
||||
// Definition of nsScriptError, defined here because we lack a place to put
|
||||
// XPCOM objects associated with the JavaScript engine.
|
||||
@ -1493,4 +1500,11 @@ private:
|
||||
nsCString mCategory;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
// the include of declarations of the maps comes last because they have
|
||||
// inlines which call methods on classes above.
|
||||
|
||||
#include "xpcmaps.h"
|
||||
|
||||
#endif /* xpcprivate_h___ */
|
||||
|
@ -187,21 +187,74 @@ nsXPCThreadJSContextStackImpl::GetSafeJSContext(JSContext * *aSafeJSContext)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static const PRUintn BAD_TLS_INDEX = (PRUintn) -1;
|
||||
|
||||
PRUintn xpcPerThreadData::gTLSIndex = BAD_TLS_INDEX;
|
||||
PRLock* xpcPerThreadData::gLock = nsnull;
|
||||
xpcPerThreadData* xpcPerThreadData::gThreads = nsnull;
|
||||
|
||||
xpcPerThreadData::xpcPerThreadData()
|
||||
: mException(nsnull),
|
||||
mJSContextStack(new nsDeque(nsnull)),
|
||||
mSafeJSContext(nsnull)
|
||||
mSafeJSContext(nsnull),
|
||||
mNextThread(nsnull)
|
||||
{
|
||||
// empty...
|
||||
if(gLock)
|
||||
{
|
||||
nsAutoLock lock(gLock);
|
||||
mNextThread = gThreads;
|
||||
gThreads = this;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xpcPerThreadData::Cleanup()
|
||||
{
|
||||
NS_IF_RELEASE(mException);
|
||||
|
||||
if(mJSContextStack)
|
||||
{
|
||||
delete mJSContextStack;
|
||||
mJSContextStack = nsnull;
|
||||
}
|
||||
|
||||
if(mSafeJSContext)
|
||||
{
|
||||
JS_DestroyContext(mSafeJSContext);
|
||||
mSafeJSContext = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
xpcPerThreadData::~xpcPerThreadData()
|
||||
{
|
||||
NS_IF_RELEASE(mException);
|
||||
if(mJSContextStack)
|
||||
delete mJSContextStack;
|
||||
if(mSafeJSContext)
|
||||
JS_DestroyContext(mSafeJSContext);
|
||||
Cleanup();
|
||||
|
||||
// Unlink 'this' from the list of threads.
|
||||
if(gLock)
|
||||
{
|
||||
nsAutoLock lock(gLock);
|
||||
if(gThreads == this)
|
||||
gThreads = mNextThread;
|
||||
else
|
||||
{
|
||||
xpcPerThreadData* cur = gThreads;
|
||||
while(cur)
|
||||
{
|
||||
if(cur->mNextThread == this)
|
||||
{
|
||||
cur->mNextThread = mNextThread;
|
||||
break;
|
||||
}
|
||||
cur = cur->mNextThread;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(gLock && !gThreads)
|
||||
{
|
||||
PR_DestroyLock(gLock);
|
||||
gLock = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
@ -283,20 +336,32 @@ xpc_ThreadDataDtorCB(void* ptr)
|
||||
xpcPerThreadData*
|
||||
xpcPerThreadData::GetData()
|
||||
{
|
||||
static const PRUintn BAD_TLS_INDEX = (PRUintn) -1;
|
||||
static PRUintn index = BAD_TLS_INDEX;
|
||||
xpcPerThreadData* data;
|
||||
if(index == BAD_TLS_INDEX)
|
||||
|
||||
if(!gLock)
|
||||
{
|
||||
if(PR_FAILURE == PR_NewThreadPrivateIndex(&index, xpc_ThreadDataDtorCB))
|
||||
{
|
||||
NS_ASSERTION(0, "PR_NewThreadPrivateIndex failed!");
|
||||
index = BAD_TLS_INDEX;
|
||||
gLock = PR_NewLock();
|
||||
if(!gLock)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if(gTLSIndex == BAD_TLS_INDEX)
|
||||
{
|
||||
nsAutoLock lock(gLock);
|
||||
// check again now that we have the lock...
|
||||
if(gTLSIndex == BAD_TLS_INDEX)
|
||||
{
|
||||
if(PR_FAILURE ==
|
||||
PR_NewThreadPrivateIndex(&gTLSIndex, xpc_ThreadDataDtorCB))
|
||||
{
|
||||
NS_ASSERTION(0, "PR_NewThreadPrivateIndex failed!");
|
||||
gTLSIndex = BAD_TLS_INDEX;
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data = (xpcPerThreadData*) PR_GetThreadPrivate(index);
|
||||
data = (xpcPerThreadData*) PR_GetThreadPrivate(gTLSIndex);
|
||||
if(!data)
|
||||
{
|
||||
data = new xpcPerThreadData();
|
||||
@ -307,7 +372,7 @@ xpcPerThreadData::GetData()
|
||||
delete data;
|
||||
return nsnull;
|
||||
}
|
||||
if(PR_FAILURE == PR_SetThreadPrivate(index, data))
|
||||
if(PR_FAILURE == PR_SetThreadPrivate(gTLSIndex, data))
|
||||
{
|
||||
NS_ASSERTION(0, "PR_SetThreadPrivate failed!");
|
||||
delete data;
|
||||
@ -316,3 +381,17 @@ xpcPerThreadData::GetData()
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
xpcPerThreadData::CleanupAllThreads()
|
||||
{
|
||||
if(gLock)
|
||||
{
|
||||
nsAutoLock lock(gLock);
|
||||
|
||||
for(xpcPerThreadData* cur = gThreads; cur; cur = cur->mNextThread)
|
||||
cur->Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user