зеркало из https://github.com/mozilla/gecko-dev.git
Bug 684938 - Proxy nsXPCWrappedJS::Release to the main thread. r=mrbkap.
--HG-- extra : rebase_source : faf9c46616c52bc03b776a4aae8fd3f87e11f132
This commit is contained in:
Родитель
20669cb83c
Коммит
1d05a88d12
|
@ -43,6 +43,7 @@
|
||||||
|
|
||||||
#include "xpcprivate.h"
|
#include "xpcprivate.h"
|
||||||
#include "nsAtomicRefcnt.h"
|
#include "nsAtomicRefcnt.h"
|
||||||
|
#include "nsProxyRelease.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsTextFormatter.h"
|
#include "nsTextFormatter.h"
|
||||||
|
|
||||||
|
@ -196,6 +197,21 @@ nsXPCWrappedJS::Release(void)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||||
|
|
||||||
|
if (mMainThreadOnly && !NS_IsMainThread()) {
|
||||||
|
// We'd like to abort here, but this can happen if someone uses a proxy
|
||||||
|
// for the nsXPCWrappedJS.
|
||||||
|
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||||
|
// If we can't get the main thread anymore we just leak, but this really
|
||||||
|
// shouldn't happen.
|
||||||
|
NS_ASSERTION(mainThread,
|
||||||
|
"Can't get main thread, leaking nsXPCWrappedJS!");
|
||||||
|
if (mainThread) {
|
||||||
|
NS_ProxyRelease(mainThread,
|
||||||
|
static_cast<nsIXPConnectWrappedJS*>(this));
|
||||||
|
}
|
||||||
|
return mRefCnt;
|
||||||
|
}
|
||||||
|
|
||||||
// need to take the map lock here to prevent GetNewOrUsed from trying
|
// need to take the map lock here to prevent GetNewOrUsed from trying
|
||||||
// to reuse a wrapper on one thread while it's being destroyed on another
|
// to reuse a wrapper on one thread while it's being destroyed on another
|
||||||
XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
|
XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
|
||||||
|
@ -264,6 +280,28 @@ nsXPCWrappedJS::GetJSObject(JSObject** aJSObj)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CheckMainThreadOnly(nsXPCWrappedJS *aWrapper)
|
||||||
|
{
|
||||||
|
if(aWrapper->IsMainThreadOnly())
|
||||||
|
return NS_IsMainThread();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIClassInfo> ci;
|
||||||
|
CallQueryInterface(aWrapper, getter_AddRefs(ci));
|
||||||
|
if (ci) {
|
||||||
|
PRUint32 flags;
|
||||||
|
if (NS_SUCCEEDED(ci->GetFlags(&flags)) && !(flags & nsIClassInfo::MAIN_THREAD_ONLY))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!NS_IsMainThread())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aWrapper->SetIsMainThreadOnly();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
nsresult
|
nsresult
|
||||||
nsXPCWrappedJS::GetNewOrUsed(XPCCallContext& ccx,
|
nsXPCWrappedJS::GetNewOrUsed(XPCCallContext& ccx,
|
||||||
|
@ -317,7 +355,9 @@ nsXPCWrappedJS::GetNewOrUsed(XPCCallContext& ccx,
|
||||||
// the root will do double duty as the interface wrapper
|
// the root will do double duty as the interface wrapper
|
||||||
wrapper = root = new nsXPCWrappedJS(ccx, aJSObj, clazz, nsnull,
|
wrapper = root = new nsXPCWrappedJS(ccx, aJSObj, clazz, nsnull,
|
||||||
aOuter);
|
aOuter);
|
||||||
if (root)
|
if (!root)
|
||||||
|
goto return_wrapper;
|
||||||
|
|
||||||
{ // scoped lock
|
{ // scoped lock
|
||||||
#if DEBUG_xpc_leaks
|
#if DEBUG_xpc_leaks
|
||||||
printf("Created nsXPCWrappedJS %p, JSObject is %p\n",
|
printf("Created nsXPCWrappedJS %p, JSObject is %p\n",
|
||||||
|
@ -326,6 +366,14 @@ nsXPCWrappedJS::GetNewOrUsed(XPCCallContext& ccx,
|
||||||
XPCAutoLock lock(rt->GetMapLock());
|
XPCAutoLock lock(rt->GetMapLock());
|
||||||
map->Add(root);
|
map->Add(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CheckMainThreadOnly(root)) {
|
||||||
|
XPCAutoLock lock(rt->GetMapLock());
|
||||||
|
map->Remove(root);
|
||||||
|
|
||||||
|
wrapper = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
goto return_wrapper;
|
goto return_wrapper;
|
||||||
} else {
|
} else {
|
||||||
// just a root wrapper
|
// just a root wrapper
|
||||||
|
@ -351,6 +399,13 @@ nsXPCWrappedJS::GetNewOrUsed(XPCCallContext& ccx,
|
||||||
XPCAutoLock lock(rt->GetMapLock());
|
XPCAutoLock lock(rt->GetMapLock());
|
||||||
map->Add(root);
|
map->Add(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CheckMainThreadOnly(root)) {
|
||||||
|
XPCAutoLock lock(rt->GetMapLock());
|
||||||
|
map->Remove(root);
|
||||||
|
|
||||||
|
goto return_wrapper;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +450,8 @@ nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx,
|
||||||
mRoot(root ? root : this),
|
mRoot(root ? root : this),
|
||||||
mNext(nsnull),
|
mNext(nsnull),
|
||||||
mOuter(root ? nsnull : aOuter),
|
mOuter(root ? nsnull : aOuter),
|
||||||
mMainThread(NS_IsMainThread())
|
mMainThread(NS_IsMainThread()),
|
||||||
|
mMainThreadOnly(root && root->mMainThreadOnly)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_stats_jband
|
#ifdef DEBUG_stats_jband
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
|
@ -404,6 +460,8 @@ nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx,
|
||||||
printf("//////// %d instances of nsXPCWrappedJS created\n", count);
|
printf("//////// %d instances of nsXPCWrappedJS created\n", count);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
JS_ASSERT_IF(mMainThreadOnly, mMainThread);
|
||||||
|
|
||||||
InitStub(GetClass()->GetIID());
|
InitStub(GetClass()->GetIID());
|
||||||
|
|
||||||
// intentionally do double addref - see Release().
|
// intentionally do double addref - see Release().
|
||||||
|
|
|
@ -3036,6 +3036,9 @@ public:
|
||||||
JSBool IsAggregatedToNative() const {return mRoot->mOuter != nsnull;}
|
JSBool IsAggregatedToNative() const {return mRoot->mOuter != nsnull;}
|
||||||
nsISupports* GetAggregatedNativeObject() const {return mRoot->mOuter;}
|
nsISupports* GetAggregatedNativeObject() const {return mRoot->mOuter;}
|
||||||
|
|
||||||
|
void SetIsMainThreadOnly() {JS_ASSERT(mMainThread); mMainThreadOnly = true;}
|
||||||
|
bool IsMainThreadOnly() const {return mMainThreadOnly;}
|
||||||
|
|
||||||
void TraceJS(JSTracer* trc);
|
void TraceJS(JSTracer* trc);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static void PrintTraceName(JSTracer* trc, char *buf, size_t bufsize);
|
static void PrintTraceName(JSTracer* trc, char *buf, size_t bufsize);
|
||||||
|
@ -3059,6 +3062,7 @@ private:
|
||||||
nsXPCWrappedJS* mNext;
|
nsXPCWrappedJS* mNext;
|
||||||
nsISupports* mOuter; // only set in root
|
nsISupports* mOuter; // only set in root
|
||||||
bool mMainThread;
|
bool mMainThread;
|
||||||
|
bool mMainThreadOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче