We are using XPConnect with Spidermonkey for a "standalone" application. The build is ff1.5 final release. Unfortunately, we are getting an access violation on shutdown of the GRE in JS_HashTableEnumerateEntries, or the application hangs in what seems to be an infinite loop in a related piece of code. At the end, I have included call stacks. Oddly, the crash seems tobe reproducable only while running outside the MSVC++ (7.1) debugger. However, sometimes it does not crash at all. If I comment out the AddFunction method below, then it seems to work, but we need that functionality. I have narrowed it down to the myXPConnectService->WrapNative call that is causing the problem, but I don't know how it does that. (If I leave it commented in it crashes. Otherwise it does not.) For the records, the functionality of the code works fine, when all of the code is commented in.
In an older thread I posted to mozilla.dev.tech.js-engine, I thought the problem might be some of the Spidermonkey calls, but I now doubt that is the case. http://groups.google.ca/group/mozilla.dev.tech.js-engine/browse_frm/thread/72c0dea3a5533b4e/8b8fc13b3b4ba862?lnk=st&q=crash+JS_HashTableEnumerateEntries&rnum=1#8b8fc13b3b4ba862 Does anyone have any insight into how we can fix these crashes? Thanks. // For reference only. NS_IMETHODIMP JSEngine::StartScriptEngine(PRBool *_retval) { nsresult result; isWorldLoaded = false; // get the JSRuntime from the runtime svc result = myServiceManager->GetServiceByContractID("@mozilla.org/js/xpc/RuntimeService;1", NS_GET_IID(nsIJSRuntimeService), getter_AddRefs(myRuntimeService)); if(NS_FAILED(result) || NS_FAILED(myRuntimeService->GetRuntime(&myRuntime)) || !myRuntime) { return NS_ERROR_FAILURE; } result = myServiceManager->GetServiceByContractID("@mozilla.org/js/xpc/ContextStack;1", NS_GET_IID(nsIJSContextStack), getter_AddRefs(myContextStack)); // get a safe context and push it on the stack //setup js context myContext = JS_NewContext(myRuntime, gStackSize); if(!myContext) { return NS_ERROR_FAILURE; } myContextStack->Push(myContext); //get xpconnect result = myServiceManager->GetService(nsIXPConnect::GetCID(), NS_GET_IID(nsIXPConnect), getter_AddRefs(myXPConnectService)); if(!myXPConnectService) { return NS_ERROR_FAILURE; } // set up the global object, make it the wrapped native VOM Viewer xpcom object myGlobal = JS_NewObject(myContext, &global_class, NULL, NULL); if (!JS_InitStandardClasses(myContext, myGlobal)) { return NS_ERROR_FAILURE; } if (!JS_DefineFunctions(myContext, myGlobal, glob_functions)) { return NS_ERROR_FAILURE; } if (NS_FAILED(myXPConnectService->InitClasses(myContext, myGlobal))) { return NS_ERROR_FAILURE; } myXPConnectService->SetSafeJSContextForCurrentThread( myContext ); //setup the security manager mySecurityManager = new ScriptSecurityManager(); if(!mySecurityManager) { return NS_ERROR_FAILURE; } if(!NS_SUCCEEDED(myXPConnectService->SetSecurityManagerForJSContext( myContext, mySecurityManager, nsIXPCSecurityManager::HOOK_ALL))) { return NS_ERROR_FAILURE; } //setup error reporting JS_SetErrorReporter(myContext, myErrorCallback); // set the branch callback for GC JS_SetBranchCallback(myContext, myBranchCallback); return NS_OK; } NS_IMETHODIMP JSEngine::AddFunction( nsIDOMEventTarget *target, const nsAString & eventName, const nsAString & jsEventHandlerName, PRBool capture, PRBool *_retval ) { NS_ENSURE_ARG_POINTER( target ); NS_ENSURE_ARG_POINTER( _retval ); NS_ENSURE_STATE( myContext ); NS_ENSURE_STATE( myXPConnectService ); *_retval = PR_FALSE; // be pessimistic. nsEmbedString name( eventName ); nsEmbedString handlerName( jsEventHandlerName ); nsCOMPtr< nsIXPConnectJSObjectHolder > holder; NS_ENSURE_SUCCESS( myXPConnectService->WrapNative( myContext, myGlobal, target, NS_GET_IID( nsISupports ), getter_AddRefs( holder ) ), NS_ERROR_UNEXPECTED ); JSObject* jsTarget = nsnull; NS_ENSURE_SUCCESS( holder->GetJSObject( &jsTarget ), NS_ERROR_UNEXPECTED ); NS_ENSURE_STATE( jsTarget ); universal_string eventNameStr( name.get() ); // Converts to wstring. const char *argList[] = { "event" }; JSFunction* function = ::JS_CompileUCFunction( myContext, jsTarget, universal_string_val< TCHAR >( eventNameStr ).c_str(), 1, argList, (jschar*) handlerName.get(), handlerName.Length(), __FUNCTION__, __LINE__ ); if ( function == NULL ) { return NS_ERROR_FAILURE; } boost::shared_ptr< JSObject* > functionObject( new JSObject* ); NS_ENSURE_TRUE( functionObject, NS_ERROR_OUT_OF_MEMORY ); *functionObject = ::JS_GetFunctionObject( function ); NS_ENSURE_TRUE( ::JS_AddNamedRootRT( myRuntime, &(*functionObject), "JScriptEngine::AddEventListener" ), NS_ERROR_OUT_OF_MEMORY ); myGCRootsToRemove.push_back( functionObject ); // just a std::vector member variable. // Now that the event handler was compiled and assigned as a property to the target, // we can go about wrapping it in an event listener and add it as a listener to the target. nsCOMPtr< vIJavaScriptable > jsListener; // This is our own listener implementation. We are not using it with the Mozilla DOM, but a similar event // handling structure instead. componentManager->CreateInstanceByContractID( JSEVENTLISTENER_CONTRACTID, NULL, NS_GET_IID( vIJavaScriptable ), getter_AddRefs( jsListener ) ); NS_ENSURE_SUCCESS( jsListener->SetJsContext( myContext ), NS_ERROR_UNEXPECTED ); NS_ENSURE_SUCCESS( jsListener->SetScope( myGlobal ), NS_ERROR_UNEXPECTED ); nsCOMPtr< nsIDOMEventListener > listener( do_QueryInterface( jsListener ) ); nsresult result = target->AddEventListener( eventName, listener, capture ); NS_ENSURE_SUCCESS( result, NS_ERROR_UNEXPECTED ); *_retval = PR_TRUE; return NS_OK; } class RemoveGCRoot : public std::unary_function< JSObject*, void > { public: RemoveGCRoot( JSRuntime* runtime ) : myRuntime( runtime ) {} void operator()( boost::shared_ptr< JSObject* > gcRoot ) const { if ( gcRoot == NULL ) return; JSBool success = ::JS_RemoveRootRT( myRuntime, reinterpret_cast< void* >( &(*gcRoot) ) ); assert( success ); } private: JSRuntime* myRuntime; }; NS_IMETHODIMP JSEngine::StopScriptEngine(PRBool *_retval) { std::for_each( myGCRootsToRemove.begin(), myGCRootsToRemove.end(), RemoveGCRoot( myRuntime ) ); myGCRootsToRemove.clear(); // Prevent use of myContext after it is deleted. myXPConnectService->SetSafeJSContextForCurrentThread( NULL ); // Take out the trash. JS_ClearScope( myContext, myGlobal ); JS_GC( myContext ); // Clear our entry in the JSContext, bugzilla bug 66413 JS_SetContextPrivate(myContext, nsnull); // Clear the branch callback, bugzilla bug 238218 JS_SetBranchCallback(myContext, nsnull); myErrorCallback = 0; myBranchCallback = 0; myGlobal = 0; myContextStack->Pop(&myContext); myXPConnectService->SyncJSContexts(); // This calls JS_DestroyContext for us. myXPConnectService->ReleaseJSContext(myContext, false); // Do not call JS_DestroyRuntime(myRuntime); It will be called in NS_ShutdownXPCOM, because // XPConnect still has a context which references it. // Do not call JS_ShutDown(); It will be called in NS_ShutdownXPCOM. delete mySecurityManager; myRuntime = 0; myContext = 0; myContextStack = nsnull; myXPConnectService = nsnull; myRuntimeService = nsnull; myLogManager = nsnull; return NS_OK; } [EMAIL PROTECTED]() + 0x283bd ntdll.dll!_DbgPrint() + 0x1a [EMAIL PROTECTED]() + 0x12 [EMAIL PROTECTED]() + 0x2b8e2 msvcr71.dll!free(void * pBlock=0x00360198) Line 103 C js3250.dll!js_free_atom(void * priv=0x01f753dc, JSHashEntry * he=0x00360198, unsigned int flag=1) Line 252 + 0x11 C > js3250.dll!JS_HashTableRawRemove(JSHashTable * ht=0x01f5dfd0, JSHashEntry > * * hep=0x0012f53c, JSHashEntry * he=0x00360198) Line 280 + 0x13 C js3250.dll!JS_HashTableEnumerateEntries(JSHashTable * ht=0x01f5dfd0, int (JSHashEntry *, int, void *)* f=0x020a862e, void * arg=0x01f753dc) Line 382 + 0x11 C js3250.dll!js_SweepAtomState(JSAtomState * state=0x01f753dc) Line 494 + 0xc C js3250.dll!js_GC(JSContext * cx=0x01f187e0, unsigned int gcflags=2) Line 1821 C js3250.dll!js_ForceGC(JSContext * cx=0x01f187e0, unsigned int gcflags=2) Line 1510 + 0x1f C js3250.dll!js_DestroyContext(JSContext * cx=0x01f187e0, JSGCMode gcmode=JS_FORCE_GC) Line 266 C js3250.dll!JS_DestroyContext(JSContext * cx=0x01f187e0) Line 932 + 0xb C xpc3250.dll!XPCJSContextStack::~XPCJSContextStack() Line 62 C++ xpc3250.dll!XPCJSContextStack::`scalar deleting destructor'() + 0x8 C++ xpc3250.dll!XPCPerThreadData::CleanupAllThreads() Line 544 + 0xe C++ xpc3250.dll!nsXPConnect::~nsXPConnect() Line 150 C++ xpc3250.dll!nsXPConnect::`scalar deleting destructor'() + 0x8 C++ xpc3250.dll!nsXPConnect::Release() Line 48 + 0x23 C++ xpc3250.dll!nsXPConnect::ReleaseXPConnectSingleton() Line 244 C++ xpc3250.dll!xpcModuleDtor(nsIModule * self=0x01f51fd8) Line 133 C++ xpcom_core.dll!nsGenericModule::Shutdown() Line 339 + 0x3 C++ xpcom_core.dll!nsGenericModule::`scalar deleting destructor'() + 0xe C++ xpcom_core.dll!nsGenericModule::Release() Line 244 + 0x20 C++ xpcom_core.dll!nsDll::Shutdown() Line 271 + 0x6 C++ xpcom_core.dll!nsFreeLibrary(nsDll * dll=0x7c93040c, nsIServiceManager * serviceMgr=0x0012f710, int when=3) Line 291 C++ xpcom_core.dll!nsFreeLibraryEnum(nsHashKey * aKey=0x01f51fc0, void * aData=0x01f2a710, void * closure=0x00000000) Line 360 + 0x28 C++ xpcom_core.dll!hashEnumerate(PLDHashTable * table=0x0036efe4, PLDHashEntryHdr * hdr=0x0036f028, unsigned int i=0, void * arg=0x0012f770) Line 131 + 0x13 C++ xpcom_core.dll!PL_DHashTableEnumerate(PLDHashTable * table=0x00000000, PLDHashOperator (PLDHashTable *, PLDHashEntryHdr *, unsigned int, void *)* etor=0x0037665a, void * arg=0x0012f770) Line 621 + 0xb C xpcom_core.dll!nsHashtable::Enumerate(int (nsHashKey *, void *, void *)* aEnumFunc=0x0039865f, void * aClosure=0x0012f788) Line 319 + 0x16 C++ xpcom_core.dll!nsNativeComponentLoader::UnloadAll(int aWhen=3) Line 978 C++ xpcom_core.dll!nsComponentManagerImpl::UnloadLibraries(nsIServiceManager * serviceMgr=0x00000000, int aWhen=3) Line 3122 C++ xpcom_core.dll!nsComponentManagerImpl::Shutdown() Line 900 C++ xpcom_core.dll!NS_ShutdownXPCOM_P(nsIServiceManager * servMgr=0x00000000) Line 842 + 0x5 C++ foo.exe!_GRE_Shutdown() Line 515 + 0x7 Or to "unpin pinned atoms": js3250.dll!JS_HashTableEnumerateEntries(JSHashTable * ht=0x01f23840, int (JSHashEntry *, int, void *)* f=0x020a8677, void * arg=0x00000000) Line 363 C js3250.dll!js_UnpinPinnedAtoms(JSAtomState * state=0x01f753dc) Line 511 + 0xd C js3250.dll!js_DestroyContext(JSContext * cx=0x01f188d0, JSGCMode gcmode=JS_FORCE_GC) Line 227 C js3250.dll!JS_DestroyContext(JSContext * cx=0x01f188d0) Line 932 + 0xb C xpc3250.dll!nsXPConnect::ReleaseJSContext(JSContext * aJSContext=0x01f188d0, int noGC=0) Line 1205 C++ ScriptEngine.dll!JScriptEngine::StopScriptEngine(int * _retval=0x0012ee68) Line 419 C++ Controls.dll!ViewWin32::WndProcess(HWND__ * hWnd=0x000406f8, unsigned int message=2, unsigned int wParam=0, long lParam=0) Line 1876 C++ Controls.dll!WndProc(HWND__ * hWnd=0x000406f8, unsigned int message=2, unsigned int wParam=0, long lParam=0) Line 47 C++ [EMAIL PROTECTED]() + 0x28 [EMAIL PROTECTED]() + 0xb7 [EMAIL PROTECTED]() + 0x4d [EMAIL PROTECTED]() + 0x24 [EMAIL PROTECTED]() + 0x13 [EMAIL PROTECTED]() + 0xc [EMAIL PROTECTED]() + 0x27 [EMAIL PROTECTED]() + 0x57 Controls.dll!MainFrameWin32::WndProcess(HWND__ * hWnd=0x000406ea, unsigned int message=16, unsigned int wParam=0, long lParam=0) Line 323 + 0x16 C++ [EMAIL PROTECTED]() + 0x28 [EMAIL PROTECTED]() + 0xb7 [EMAIL PROTECTED]() + 0x4d [EMAIL PROTECTED]() + 0x24 [EMAIL PROTECTED]() + 0x13 [EMAIL PROTECTED]() + 0xc [EMAIL PROTECTED]() + 0x27 uxtheme.dll!DoMsgDefault() + 0x29 uxtheme.dll!OnDwpSysCommand() + 0x2b uxtheme.dll!_ThemeDefWindowProc() + 0x103 [EMAIL PROTECTED]() + 0x18 [EMAIL PROTECTED]() + 0x11c46 Controls.dll!MainFrameWin32::WndProcess(HWND__ * hWnd=0x000406ea, unsigned int message=274, unsigned int wParam=61536, long lParam=16320066) Line 323 + 0x16 C++ [EMAIL PROTECTED]() + 0x28 [EMAIL PROTECTED]() + 0xb7 [EMAIL PROTECTED]() + 0xc8 [EMAIL PROTECTED]() + 0x49 uxtheme.dll!OnDwpNcLButtonDown() + 0xa8 uxtheme.dll!_ThemeDefWindowProc() + 0x103 [EMAIL PROTECTED]() + 0x18 [EMAIL PROTECTED]() + 0x11c46 Controls.dll!MainFrameWin32::WndProcess(HWND__ * hWnd=0x000406ea, unsigned int message=161, unsigned int wParam=20, long lParam=16320066) Line 323 + 0x16 C++ [EMAIL PROTECTED]() + 0x28 [EMAIL PROTECTED]() + 0xb7 [EMAIL PROTECTED]() + 0xdc [EMAIL PROTECTED]() + 0xf Controls.dll!MainFrameWin32::run() Line 126 C++ Controls.dll!MainFrame::Run() Line 68 C++ Hangs in an infinite (?) while loop in this call stack > js3250.dll!JS_HashTableEnumerateEntries(JSHashTable * ht=0x046e7318, int > (JSHashEntry *, int, void *)* f=0x04868677, void * arg=0x00000000) Line > 362 + 0x3 C js3250.dll!js_UnpinPinnedAtoms(JSAtomState * state=0x046ebaac) Line 511 + 0xd C js3250.dll!js_DestroyContext(JSContext * cx=0x046e9760, JSGCMode gcmode=JS_FORCE_GC) Line 227 C js3250.dll!JS_DestroyContext(JSContext * cx=0x046e9760) Line 932 + 0xb C xpc3250.dll!nsXPConnect::ReleaseJSContext(JSContext * aJSContext=0x046e9760, int noGC=0) Line 1205 C++ SEngine.dll!JScriptEngine::StopScriptEngine(int * _retval=0x0013e474) Line 418 C++ _______________________________________________ dev-tech-xpcom mailing list [email protected] https://lists.mozilla.org/listinfo/dev-tech-xpcom
