From a35050a4953ccc7f9b852e9279646efcf4d3d1be Mon Sep 17 00:00:00 2001 From: "timeless%mozdev.org" Date: Thu, 23 Jun 2005 08:46:49 +0000 Subject: [PATCH] Bug 280234 [FIX]sometimes get ###!!! ASSERTION: tearoff not empty in dtor: '!(GetInterface()||GetNative()||GetJSObject())' patch by bz r=dbradley sr=brendan a=brendan --- js/src/xpconnect/src/xpcprivate.h | 33 ++++++++++++++++++++--- js/src/xpconnect/src/xpcwrappednative.cpp | 20 +++++++++++--- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 648f2ed2e438..ec6c4d99325f 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -1214,7 +1214,8 @@ public: {return 0 != (mMemberCount & XPC_NATIVE_IFACE_MARK_FLAG);} // NOP. This is just here to make the AutoMarkingPtr code compile. - inline void MarkBeforeJSFinalize(JSContext*) {}; + inline void MarkBeforeJSFinalize(JSContext*) {} + inline void AutoMark(JSContext*) {} static void DestroyInstance(JSContext* cx, XPCJSRuntime* rt, XPCNativeInterface* inst); @@ -1342,7 +1343,8 @@ public: inline void Mark(); // NOP. This is just here to make the AutoMarkingPtr code compile. - inline void MarkBeforeJSFinalize(JSContext*) {}; + inline void MarkBeforeJSFinalize(JSContext*) {} + inline void AutoMark(JSContext*) {} private: void MarkSelfOnly() {mInterfaceCount |= XPC_NATIVE_SET_MARK_FLAG;} @@ -1644,6 +1646,8 @@ public: JS_MarkGCThing(cx, mJSProtoObject, "XPCWrappedNativeProto::mJSProtoObject", nsnull); if(mScriptableInfo) mScriptableInfo->Mark();} + // NOP. This is just here to make the AutoMarkingPtr code compile. + inline void AutoMark(JSContext*) {} // Yes, we *do* need to mark the mScriptableInfo in both cases. void Mark() const @@ -1711,6 +1715,10 @@ public: : mInterface(nsnull), mNative(nsnull), mJSObject(nsnull) {} ~XPCWrappedNativeTearOff(); + // NOP. This is just here to make the AutoMarkingPtr code compile. + inline void MarkBeforeJSFinalize(JSContext*) {} + inline void AutoMark(JSContext*) {} + void Mark() {mJSObject = (JSObject*)(((jsword)mJSObject) | 1);} void Unmark() {mJSObject = (JSObject*)(((jsword)mJSObject) & ~1);} JSBool IsMarked() const {return (JSBool)(((jsword)mJSObject) & 1);} @@ -1938,6 +1946,20 @@ public: } } + inline void AutoMark(JSContext* cx) + { + // If this got called, we're being kept alive by someone who really + // needs us alive and whole. Do not let our mFlatJSObject go away. + // This is the only time we should be marking our mFlatJSObject; + // normally we just go away quietly when it does. Be careful not to + // mark the bogus JSVAL_ONE value we can have during init, though. + if(mFlatJSObject && mFlatJSObject != (JSObject*)JSVAL_ONE) + { + ::JS_MarkGCThing(cx, mFlatJSObject, + "XPCWrappedNative::mFlatJSObject", nsnull); + } + } + #ifdef DEBUG void ASSERT_SetsNotMarked() const {mSet->ASSERT_NotMarked(); @@ -3172,6 +3194,7 @@ public: {if(JSVAL_IS_GCTHING(*mValPtr)) JS_MarkGCThing(cx, JSVAL_TO_GCTHING(*mValPtr), "XPCMarkableJSVal", nsnull);} + void AutoMark(JSContext*) {} private: XPCMarkableJSVal(); // not implemented jsval mVal; @@ -3230,7 +3253,10 @@ public: \ virtual ~ class_ () {} \ \ virtual void MarkBeforeJSFinalize(JSContext* cx) \ - {if(mPtr) mPtr->MarkBeforeJSFinalize(cx); \ + {if(mPtr) { \ + mPtr->MarkBeforeJSFinalize(cx); \ + mPtr->AutoMark(cx); \ + } \ if(mNext) mNext->MarkBeforeJSFinalize(cx);} \ \ virtual void MarkAfterJSFinalize() \ @@ -3253,6 +3279,7 @@ protected: \ DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeInterfacePtr, XPCNativeInterface) DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeSetPtr, XPCNativeSet) DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativePtr, XPCWrappedNative) +DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeTearOffPtr, XPCWrappedNativeTearOff) DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeProtoPtr, XPCWrappedNativeProto) DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingJSVal, XPCMarkableJSVal) diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp index 5327361ed1fa..a9a641c59b93 100644 --- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -1311,7 +1311,13 @@ XPCWrappedNative::FindTearOff(XPCCallContext& ccx, { if(needJSObject && !to->GetJSObject()) { + AutoMarkingWrappedNativeTearOffPtr tearoff(ccx, to); rv = InitTearOffJSObject(ccx, to); + // During shutdown, we don't sweep tearoffs. So make sure + // to unmark manually in case the auto-marker marked us. + // We shouldn't ever be getting here _during_ our + // Mark/Sweep cycle, so this should be safe. + to->Unmark(); if(NS_FAILED(rv)) to = nsnull; } @@ -1337,9 +1343,17 @@ XPCWrappedNative::FindTearOff(XPCCallContext& ccx, to = newChunk->mTearOffs; } - rv = InitTearOff(ccx, to, aInterface, needJSObject); - if(NS_FAILED(rv)) - to = nsnull; + { + // Scope keeps |tearoff| from leaking across the return_result: label + AutoMarkingWrappedNativeTearOffPtr tearoff(ccx, to); + rv = InitTearOff(ccx, to, aInterface, needJSObject); + // During shutdown, we don't sweep tearoffs. So make sure to unmark + // manually in case the auto-marker marked us. We shouldn't ever be + // getting here _during_ our Mark/Sweep cycle, so this should be safe. + to->Unmark(); + if(NS_FAILED(rv)) + to = nsnull; + } return_result: